Skip to content

Commit 73ec41a

Browse files
committed
feat: package CLI
1 parent 7f868ed commit 73ec41a

9 files changed

Lines changed: 265 additions & 23 deletions

File tree

packages/cli/README.md

Lines changed: 237 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,237 @@
1-
# cli
1+
# Bucket CLI
2+
3+
Command-line interface for interacting with Bucket services. The CLI allows you to manage apps, features, authentication, and generate TypeScript types for your Bucket features. With this tool, you can streamline your feature flagging workflow directly from your terminal.
4+
5+
## Installation
6+
7+
You can install the Bucket CLI either locally to your project or globally on your system.
8+
9+
### Local Installation (Recommended)
10+
11+
Local installation is recommended for project-specific usage and ensures consistent CLI versions across your team.
12+
13+
```bash
14+
# npm
15+
npm install --save-dev @bucketco/cli
16+
17+
# yarn
18+
yarn add --dev @bucketco/cli
19+
20+
# pnpm
21+
pnpm add --save-dev @bucketco/cli
22+
```
23+
24+
When installed locally, use the CLI with npx:
25+
26+
```bash
27+
npx bucket <command>
28+
```
29+
30+
or as a `package.json` script
31+
32+
```json
33+
{
34+
"scripts": {
35+
"bucket": "bucket"
36+
}
37+
}
38+
```
39+
40+
### Global Installation
41+
42+
Global installation makes the CLI available system-wide.
43+
44+
```bash
45+
# npm
46+
npm install -g @bucketco/cli
47+
48+
# yarn
49+
yarn global add @bucketco/cli
50+
51+
# pnpm
52+
pnpm add -g @bucketco/cli
53+
```
54+
55+
When installed globally, use the CLI directly:
56+
57+
```bash
58+
bucket <command>
59+
```
60+
61+
## Quick Start
62+
63+
Get started quickly with the following commands:
64+
65+
```bash
66+
# Initialize CLI (if not setup), create a feature, and generate types all at once
67+
bucket new "My Feature"
68+
69+
# Or perform operations individually:
70+
71+
# Initialize Bucket in your project
72+
bucket init
73+
74+
# Create a new feature
75+
bucket features create "My Feature"
76+
77+
# Generate TypeScript types for your features
78+
bucket features types
79+
```
80+
81+
## Configuration
82+
83+
The CLI creates a `bucket.config.json` file in your project directory when you run `bucket init`. This file contains all the necessary settings for your Bucket integration.
84+
85+
### Configuration File Structure
86+
87+
Here's a comprehensive list of configuration options available in the `bucket.config.json` file:
88+
89+
```json
90+
{
91+
"$schema": "https://unpkg.com/@bucketco/cli@latest/schema.json",
92+
"baseUrl": "https://app.bucket.co",
93+
"apiUrl": "https://app.bucket.co/api",
94+
"appId": "ap123456789",
95+
"typesOutput": "gen/features.ts",
96+
"keyFormat": "camelCase"
97+
}
98+
```
99+
100+
| Option | Description | Default |
101+
| ------------- | --------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- |
102+
| `$schema` | Autocompletion for the config. `latest` can be replaced with a specific version. | "https://unpkg.com/@bucketco/cli@latest/schema.json" |
103+
| `baseUrl` | Base URL for Bucket services. | "https://app.bucket.co" |
104+
| `apiUrl` | API URL for Bucket services (overrides baseUrl for API calls). | "https://app.bucket.co/api" |
105+
| `appId` | Your Bucket application ID. | Required |
106+
| `typesOutput` | Path where TypeScript types will be generated. | "gen/features.ts" |
107+
| `keyFormat` | Format for feature keys (options: custom, pascalCase, camelCase, snakeCaseUpper, snakeCaseLower, kebabCaseUpper, kebabCaseLower). | "custom" |
108+
109+
You can override these settings using command-line options for individual commands.
110+
111+
## Commands
112+
113+
### `bucket init`
114+
115+
Initialize a new Bucket configuration in your project. This creates a `bucket.config.json` file with your settings and prompts for any required information not provided via options.
116+
117+
```bash
118+
bucket init [--force]
119+
```
120+
121+
Options:
122+
123+
- `--force`: Overwrite existing configuration file if one exists
124+
- `--app-id <id>`: Set the application ID
125+
- `--key-format <format>`: Set the key format for features
126+
127+
### `bucket new [featureName]`
128+
129+
All-in-one command to get started quickly. This command combines `init`, feature creation, and type generation in a single step. Use this for the fastest way to get up and running with Bucket.
130+
131+
```bash
132+
bucket new "My Feature" [--key my-feature] [--app-id ap123456789] [--key-format custom] [--out gen/features.ts]
133+
```
134+
135+
Options:
136+
137+
- `--key`: Specific key for the feature
138+
- `--app-id`: App ID to use
139+
- `--key-format`: Format for feature keys (custom, snake, camel, etc.)
140+
- `--out`: Path to generate TypeScript types
141+
142+
If you prefer more control over each step, you can use the individual commands (`init`, `features create`, `features types`) instead.
143+
144+
### `bucket login`
145+
146+
Log in to your Bucket account. This will authenticate your CLI for subsequent operations and store credentials securely.
147+
148+
```bash
149+
bucket login
150+
```
151+
152+
### `bucket logout`
153+
154+
Log out from your Bucket account, removing stored credentials.
155+
156+
```bash
157+
bucket logout
158+
```
159+
160+
### `bucket features`
161+
162+
Manage your Bucket features with the following subcommands.
163+
164+
#### `bucket features create [featureName]`
165+
166+
Create a new feature in your Bucket app. The command guides you through the feature creation process with interactive prompts if options are not provided.
167+
168+
```bash
169+
bucket features create "My Feature" [--key my-feature] [--app-id ap123456789] [--key-format custom]
170+
```
171+
172+
Options:
173+
174+
- `--key`: Specific key for the feature
175+
- `--app-id`: App ID to use
176+
- `--key-format`: Format for feature keys
177+
178+
#### `bucket features list`
179+
180+
List all features for the current app. This helps you visualize what features are available and their current configurations.
181+
182+
```bash
183+
bucket features list [--app-id ap123456789]
184+
```
185+
186+
Options:
187+
188+
- `--app-id`: App ID to use
189+
190+
#### `bucket features types`
191+
192+
Generate TypeScript types for your features. This ensures type safety when using Bucket features in your TypeScript/JavaScript applications.
193+
194+
```bash
195+
bucket features types [--app-id ap123456789] [--out gen/features.ts]
196+
```
197+
198+
Options:
199+
200+
- `--app-id`: App ID to use
201+
- `--out`: Path to generate TypeScript types
202+
203+
### `bucket apps`
204+
205+
Commands for managing Bucket apps.
206+
207+
## Global Options
208+
209+
These options can be used with any command:
210+
211+
- `--debug`: Enable debug mode for verbose output
212+
- `--base-url <url>`: Set the base URL for Bucket API
213+
- `--api-url <url>`: Set the API URL directly (overrides base URL)
214+
- `--help`: Display help information for a command
215+
216+
## Development
217+
218+
```bash
219+
# Build the CLI
220+
yarn build
221+
222+
# Run the CLI locally
223+
yarn bucket [command]
224+
225+
# Lint and format code
226+
yarn lint
227+
yarn format
228+
```
229+
230+
## Requirements
231+
232+
- Node.js >=18.0.0
233+
234+
## License
235+
236+
> MIT License
237+
> Copyright (c) 2025 Bucket ApS

packages/cli/commands/features.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export const listFeaturesAction = async () => {
8080
};
8181

8282
export const generateTypesAction = async () => {
83-
const { baseUrl, appId, typesPath } = configStore.getConfig();
83+
const { baseUrl, appId, typesOutput } = configStore.getConfig();
8484

8585
let spinner: Ora | undefined;
8686
let featureKeys: string[] = [];
@@ -103,9 +103,9 @@ export const generateTypesAction = async () => {
103103
spinner = ora("Generating feature types...").start();
104104
const types = genDTS(featureKeys);
105105
const projectPath = configStore.getProjectPath();
106-
const outPath = isAbsolute(typesPath)
107-
? typesPath
108-
: join(projectPath, typesPath);
106+
const outPath = isAbsolute(typesOutput)
107+
? typesOutput
108+
: join(projectPath, typesOutput);
109109
await mkdir(dirname(outPath), { recursive: true });
110110
await writeFile(outPath, types);
111111
spinner.succeed(
@@ -147,7 +147,7 @@ export function registerFeatureCommands(cli: Command) {
147147
// Update the config with the cli override values
148148
featuresCommand.hook("preAction", (_, command) => {
149149
const { appId, keyFormat, out } = command.opts();
150-
configStore.setConfig({ appId, keyFormat, typesPath: out });
150+
configStore.setConfig({ appId, keyFormat, typesOutput: out });
151151
});
152152

153153
cli.addCommand(featuresCommand);

packages/cli/commands/init.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import ora, { Ora } from "ora";
66

77
import { App, listApps } from "../services/bootstrap.js";
88
import { configStore } from "../stores/config.js";
9-
import { chalkBrand, DEFAULT_TYPES_PATH } from "../utils/constants.js";
9+
import { chalkBrand, DEFAULT_TYPES_OUTPUT } from "../utils/constants.js";
1010
import { handleError } from "../utils/errors.js";
1111
import { initOverrideOption } from "../utils/options.js";
1212

@@ -69,16 +69,16 @@ export const initAction = async (args: InitArgs = {}) => {
6969
apps.find((app) => app.id === appId)?.featureKeyFormat ?? "custom";
7070

7171
// Get types output path
72-
const typesPath = await input({
72+
const typesOutput = await input({
7373
message: "Where should we generate the types?",
74-
default: DEFAULT_TYPES_PATH,
74+
default: DEFAULT_TYPES_OUTPUT,
7575
});
7676

7777
// Update config
7878
configStore.setConfig({
7979
appId,
8080
keyFormat,
81-
typesPath,
81+
typesOutput,
8282
});
8383

8484
// Create config file

packages/cli/commands/new.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,6 @@ export function registerNewCommand(cli: Command) {
4646
// Update the config with the cli override values
4747
cli.hook("preAction", (command) => {
4848
const { appId, keyFormat, out } = command.opts();
49-
configStore.setConfig({ appId, keyFormat, typesPath: out });
49+
configStore.setConfig({ appId, keyFormat, typesOutput: out });
5050
});
5151
}

packages/cli/package.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
{
22
"name": "@bucketco/cli",
3-
"version": "0.0.1",
3+
"version": "0.1.0",
44
"packageManager": "yarn@4.1.1",
55
"description": "CLI for Bucket service",
66
"main": "./dist/index.js",
77
"type": "module",
8+
"license": "MIT",
9+
"author": "Bucket Co.",
10+
"homepage": "https://docs.bucket.co/",
11+
"repository": {
12+
"type": "git",
13+
"url": "https://github.com/bucketco/bucket-javascript-sdk.git"
14+
},
815
"engines": {
916
"node": ">=18.0.0"
1017
},
@@ -15,6 +22,9 @@
1522
"dist",
1623
"schema.json"
1724
],
25+
"exports": {
26+
".": "./dist/index.js"
27+
},
1828
"scripts": {
1929
"build": "tsc",
2030
"bucket": "yarn build && node dist/index.js",

packages/cli/schema.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"appId": {
1313
"type": "string"
1414
},
15-
"typesPath": {
15+
"typesOutput": {
1616
"type": "string"
1717
},
1818
"keyFormat": {

packages/cli/stores/config.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
CONFIG_FILE_NAME,
99
DEFAULT_API_URL,
1010
DEFAULT_BASE_URL,
11-
DEFAULT_TYPES_PATH,
11+
DEFAULT_TYPES_OUTPUT,
1212
SCHEMA_URL,
1313
} from "../utils/constants.js";
1414
import { ConfigValidationError, handleError } from "../utils/errors.js";
@@ -30,7 +30,7 @@ type Config = {
3030
baseUrl: string;
3131
apiUrl: string;
3232
appId: string | undefined;
33-
typesPath: string;
33+
typesOutput: string;
3434
keyFormat: KeyFormat;
3535
};
3636

@@ -39,7 +39,7 @@ const defaultConfig: Config = {
3939
baseUrl: DEFAULT_BASE_URL,
4040
apiUrl: DEFAULT_API_URL,
4141
appId: undefined,
42-
typesPath: DEFAULT_TYPES_PATH,
42+
typesOutput: DEFAULT_TYPES_OUTPUT,
4343
keyFormat: "custom",
4444
};
4545

packages/cli/utils/constants.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,16 @@
1-
import { createRequire } from "module";
21
import { join } from "path";
32
import chalk from "chalk";
43

5-
// https://github.com/nodejs/node/issues/51347#issuecomment-2111337854
6-
const packageJson = createRequire(import.meta.url)("../../package.json");
7-
84
export const CONFIG_FILE_NAME = "bucket.config.json";
95
export const AUTH_FILE = join(
106
process.env.HOME ?? process.env.USERPROFILE ?? "",
117
".bucket-auth",
128
);
13-
export const SCHEMA_URL = `https://unpkg.com/@bucketco/cli@${packageJson.version}/schema.json`;
9+
export const SCHEMA_URL = `https://unpkg.com/@bucketco/cli@latest/schema.json`;
1410

1511
export const DEFAULT_BASE_URL = "https://app.bucket.co";
1612
export const DEFAULT_API_URL = `${DEFAULT_BASE_URL}/api`;
17-
export const DEFAULT_TYPES_PATH = join("gen", "features.ts");
13+
export const DEFAULT_TYPES_OUTPUT = join("gen", "features.ts");
1814

1915
export const chalkBrand = chalk.hex("#847CFB");
2016

0 commit comments

Comments
 (0)