@onexapis/cli 1.1.8 → 1.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -19,28 +19,26 @@ Requires Node.js >= 18.
19
19
  ## Quick Start
20
20
 
21
21
  ```bash
22
- # Create a new theme project
23
- onex init my-theme
24
-
25
- # List all themes, sections, blocks, and components
26
- onex list
27
-
28
- # Create a section in a theme
29
- onex create:section hero --theme simple
22
+ # 1. Configure credentials (one-time setup)
23
+ onex config
30
24
 
31
- # Validate theme structure
32
- onex validate --theme simple
33
-
34
- # Build a theme
35
- onex build --theme simple
36
-
37
- # Upload to S3
38
- onex upload --theme simple
25
+ # 2. Create a new theme project
26
+ onex init my-theme
39
27
 
40
- # Clone a theme from S3
28
+ # Or clone an existing theme
41
29
  onex clone simple
42
30
  ```
43
31
 
32
+ ```bash
33
+ # Other useful commands
34
+ onex list # List themes, sections, blocks
35
+ onex create:section hero --theme simple # Scaffold a section
36
+ onex validate --theme simple # Validate theme structure
37
+ onex build --theme simple # Build a theme
38
+ onex upload --theme simple # Upload to S3
39
+ onex clone simple # Clone a theme from S3
40
+ ```
41
+
44
42
  ## Commands
45
43
 
46
44
  ### `onex init [project-name]`
@@ -199,54 +197,68 @@ Download a compiled theme from S3.
199
197
 
200
198
  Clone theme source code from S3.
201
199
 
202
- | Option | Description |
203
- | ------------------------- | --------------------------------------- |
204
- | `-v, --version <version>` | Theme version (default: `latest`) |
205
- | `-o, --output <dir>` | Output directory |
206
- | `-b, --bucket <name>` | S3 bucket name |
207
- | `-e, --environment <env>` | Environment (`staging` or `production`) |
208
- | `--no-install` | Skip running `pnpm install` after clone |
200
+ | Option | Description |
201
+ | ------------------------- | ----------------------------------------- |
202
+ | `-v, --version <version>` | Theme version (default: `latest`) |
203
+ | `-n, --name <name>` | New theme name (skips interactive prompt) |
204
+ | `-o, --output <dir>` | Output directory |
205
+ | `-b, --bucket <name>` | S3 bucket name |
206
+ | `-e, --environment <env>` | Environment (`staging` or `production`) |
207
+ | `--no-install` | Skip running `pnpm install` after clone |
209
208
 
210
209
  ```bash
211
210
  onex clone simple
211
+ onex clone simple -n my-store
212
212
  onex clone simple -v 1.0.0 -o ./my-clone --no-install
213
213
  ```
214
214
 
215
- ## S3 Configuration
216
-
217
- The `upload`, `download`, and `clone` commands use S3 for storage. The CLI automatically loads env files in this order (first found wins):
215
+ ### `onex config`
218
216
 
219
- 1. **Project-level**: `.env.local` and `.env` at the project root
220
- 2. **Global**: `~/.onex/.env` (works from any directory)
221
-
222
- ### Project config (recommended for teams)
217
+ Interactive setup for CLI credentials. Saves configuration to `~/.onex/.env` so S3 commands (`clone`, `upload`, `download`) work from any directory.
223
218
 
224
219
  ```bash
225
- # .env.local (at project root — shared with the team via .env.example)
226
- BUCKET_NAME=my-bucket
227
- AWS_REGION=ap-southeast-1
228
- AWS_ACCESS_KEY_ID=your-access-key
229
- AWS_SECRET_ACCESS_KEY=your-secret-key
220
+ onex config
230
221
  ```
231
222
 
232
- ### Global config (for personal use / running outside a project)
223
+ Prompts for:
224
+
225
+ | Key | Description | Required |
226
+ | ------------------------ | --------------------- | -------- |
227
+ | `AWS_ACCESS_KEY_ID` | AWS Access Key ID | Yes |
228
+ | `AWS_SECRET_ACCESS_KEY` | AWS Secret Access Key | Yes |
229
+ | `AWS_REGION` | AWS Region | No |
230
+ | `BUCKET_NAME` | S3 Bucket Name | No |
231
+ | `NEXT_PUBLIC_API_URL` | API URL | No |
232
+ | `NEXT_PUBLIC_COMPANY_ID` | Company ID | No |
233
+
234
+ Run this once after installing the CLI. Re-run anytime to update values.
235
+
236
+ ## S3 Configuration
237
+
238
+ The `upload`, `download`, and `clone` commands use S3 for storage.
239
+
240
+ ### Recommended: use `onex config`
233
241
 
234
242
  ```bash
235
- # ~/.onex/.env
236
- BUCKET_NAME=my-bucket
237
- AWS_REGION=ap-southeast-1
238
- AWS_ACCESS_KEY_ID=your-access-key
239
- AWS_SECRET_ACCESS_KEY=your-secret-key
243
+ # One-time setup — saves credentials to ~/.onex/.env
244
+ onex config
240
245
  ```
241
246
 
242
- Then all S3 commands just work without extra flags:
247
+ After running `onex config`, all S3 commands work from any directory:
243
248
 
244
249
  ```bash
250
+ onex clone simple # works anywhere
245
251
  onex upload --theme simple # picks up config automatically
246
- onex clone simple # works from any directory
247
252
  onex download -t simple # same
248
253
  ```
249
254
 
255
+ ### Manual configuration
256
+
257
+ The CLI loads env files in this order (first found wins):
258
+
259
+ 1. **Project-level**: `.env.local` and `.env` at the project root
260
+ 2. **Global**: `~/.onex/.env` (set by `onex config`, or create manually)
261
+
250
262
  ### Adapter Modes
251
263
 
252
264
  ```bash
@@ -315,7 +327,8 @@ packages/cli/
315
327
  │ │ ├── deploy.ts # Deploy to API server
316
328
  │ │ ├── upload.ts # Upload to S3
317
329
  │ │ ├── download.ts # Download from S3
318
- │ │ └── clone.ts # Clone source from S3
330
+ │ │ ├── clone.ts # Clone source from S3
331
+ │ │ └── config.ts # CLI credential setup
319
332
  │ └── utils/
320
333
  │ ├── logger.ts # Console output utilities
321
334
  │ ├── file-helpers.ts # File operations & project detection
package/dist/cli.js CHANGED
@@ -3438,8 +3438,8 @@ function runInstall(cwd) {
3438
3438
  });
3439
3439
  }
3440
3440
  async function promptThemeName(originalName) {
3441
- const { default: inquirer5 } = await import('inquirer');
3442
- const { themeName } = await inquirer5.prompt([
3441
+ const { default: inquirer6 } = await import('inquirer');
3442
+ const { themeName } = await inquirer6.prompt([
3443
3443
  {
3444
3444
  type: "input",
3445
3445
  name: "themeName",
@@ -3881,6 +3881,149 @@ async function devCommand(options) {
3881
3881
  });
3882
3882
  }
3883
3883
 
3884
+ // src/commands/config.ts
3885
+ init_logger();
3886
+ var CONFIG_DIR = path8__default.default.join(os__default.default.homedir(), ".onex");
3887
+ var CONFIG_FILE = path8__default.default.join(CONFIG_DIR, ".env");
3888
+ var CONFIG_ENTRIES = [
3889
+ {
3890
+ key: "AWS_ACCESS_KEY_ID",
3891
+ label: "AWS Access Key ID",
3892
+ required: true
3893
+ },
3894
+ {
3895
+ key: "AWS_SECRET_ACCESS_KEY",
3896
+ label: "AWS Secret Access Key",
3897
+ required: true,
3898
+ secret: true
3899
+ },
3900
+ {
3901
+ key: "AWS_REGION",
3902
+ label: "AWS Region",
3903
+ required: false,
3904
+ defaultValue: "ap-southeast-1"
3905
+ },
3906
+ {
3907
+ key: "BUCKET_NAME",
3908
+ label: "S3 Bucket Name",
3909
+ required: false,
3910
+ defaultValue: "theme-s3-bucket"
3911
+ },
3912
+ {
3913
+ key: "NEXT_PUBLIC_API_URL",
3914
+ label: "API URL",
3915
+ required: false,
3916
+ defaultValue: "https://api-dev.onexeos.com"
3917
+ },
3918
+ {
3919
+ key: "NEXT_PUBLIC_COMPANY_ID",
3920
+ label: "Company ID",
3921
+ required: false
3922
+ }
3923
+ ];
3924
+ function parseEnvFile(content) {
3925
+ const result = {};
3926
+ for (const line of content.split("\n")) {
3927
+ const trimmed = line.trim();
3928
+ if (!trimmed || trimmed.startsWith("#")) continue;
3929
+ const eqIndex = trimmed.indexOf("=");
3930
+ if (eqIndex === -1) continue;
3931
+ const key = trimmed.slice(0, eqIndex).trim();
3932
+ const value = trimmed.slice(eqIndex + 1).trim();
3933
+ result[key] = value;
3934
+ }
3935
+ return result;
3936
+ }
3937
+ function serializeEnv(values) {
3938
+ const lines = [
3939
+ "# OneX CLI Configuration",
3940
+ "# Generated by: onex config",
3941
+ ""
3942
+ ];
3943
+ lines.push("# AWS / S3 Configuration");
3944
+ for (const key of [
3945
+ "AWS_ACCESS_KEY_ID",
3946
+ "AWS_SECRET_ACCESS_KEY",
3947
+ "AWS_REGION",
3948
+ "BUCKET_NAME"
3949
+ ]) {
3950
+ if (values[key]) lines.push(`${key}=${values[key]}`);
3951
+ }
3952
+ lines.push("");
3953
+ lines.push("# API Configuration");
3954
+ for (const key of ["NEXT_PUBLIC_API_URL", "NEXT_PUBLIC_COMPANY_ID"]) {
3955
+ if (values[key]) lines.push(`${key}=${values[key]}`);
3956
+ }
3957
+ const knownKeys = new Set(CONFIG_ENTRIES.map((e) => e.key));
3958
+ const extraKeys = Object.keys(values).filter((k) => !knownKeys.has(k));
3959
+ if (extraKeys.length > 0) {
3960
+ lines.push("");
3961
+ lines.push("# Other");
3962
+ for (const key of extraKeys) {
3963
+ lines.push(`${key}=${values[key]}`);
3964
+ }
3965
+ }
3966
+ lines.push("");
3967
+ return lines.join("\n");
3968
+ }
3969
+ async function configCommand() {
3970
+ logger.header("OneX CLI Configuration");
3971
+ let existing = {};
3972
+ try {
3973
+ const content = await fs__default.default.readFile(CONFIG_FILE, "utf-8");
3974
+ existing = parseEnvFile(content);
3975
+ logger.info(`Existing config found at: ${CONFIG_FILE}`);
3976
+ logger.newLine();
3977
+ } catch {
3978
+ logger.info("No existing config found. Let's set one up.");
3979
+ logger.newLine();
3980
+ }
3981
+ const answers = {};
3982
+ for (const entry of CONFIG_ENTRIES) {
3983
+ const currentValue = existing[entry.key] || "";
3984
+ const defaultVal = currentValue || entry.defaultValue || "";
3985
+ const displayDefault = entry.secret && currentValue ? currentValue.slice(0, 4) + "****" + currentValue.slice(-4) : defaultVal;
3986
+ const { value } = await inquirer__default.default.prompt([
3987
+ {
3988
+ type: entry.secret ? "password" : "input",
3989
+ name: "value",
3990
+ message: `${entry.label}${entry.required ? " (required)" : ""}:`,
3991
+ default: entry.secret ? void 0 : defaultVal,
3992
+ ...entry.secret && currentValue ? {
3993
+ suffix: ` (current: ${displayDefault}, press Enter to keep)`
3994
+ } : {},
3995
+ validate: (input) => {
3996
+ if (entry.required && !input && !currentValue) {
3997
+ return `${entry.label} is required`;
3998
+ }
3999
+ return true;
4000
+ }
4001
+ }
4002
+ ]);
4003
+ answers[entry.key] = value || currentValue;
4004
+ }
4005
+ const merged = { ...existing, ...answers };
4006
+ for (const key of Object.keys(merged)) {
4007
+ if (!merged[key]) delete merged[key];
4008
+ }
4009
+ await fs__default.default.ensureDir(CONFIG_DIR);
4010
+ await fs__default.default.writeFile(CONFIG_FILE, serializeEnv(merged));
4011
+ logger.newLine();
4012
+ logger.success(`Config saved to: ${CONFIG_FILE}`);
4013
+ logger.newLine();
4014
+ logger.section("Configured values:");
4015
+ for (const entry of CONFIG_ENTRIES) {
4016
+ const val = merged[entry.key];
4017
+ if (!val) continue;
4018
+ const display = entry.secret ? val.slice(0, 4) + "****" + val.slice(-4) : val;
4019
+ logger.log(` ${entry.label}: ${display}`);
4020
+ }
4021
+ logger.newLine();
4022
+ logger.info(
4023
+ "These credentials are stored globally and used by clone, upload, and download commands."
4024
+ );
4025
+ }
4026
+
3884
4027
  // src/cli.ts
3885
4028
  try {
3886
4029
  const projectRoot = getProjectRoot();
@@ -3948,6 +4091,7 @@ program.command("clone").description("Clone theme source code from S3").argument
3948
4091
  "Environment (staging|production)",
3949
4092
  "staging"
3950
4093
  ).option("--no-install", "Skip running pnpm install after clone").action(cloneCommand);
4094
+ program.command("config").description("Configure OneX CLI credentials (AWS, API keys)").action(configCommand);
3951
4095
  program.configureOutput({
3952
4096
  writeErr: (str) => process.stderr.write(chalk4__default.default.red(str))
3953
4097
  });