@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 +58 -45
- package/dist/cli.js +146 -2
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +146 -2
- package/dist/cli.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,28 +19,26 @@ Requires Node.js >= 18.
|
|
|
19
19
|
## Quick Start
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
#
|
|
23
|
-
onex
|
|
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
|
-
#
|
|
32
|
-
onex
|
|
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
|
-
#
|
|
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
|
-
| `-
|
|
206
|
-
| `-
|
|
207
|
-
| `-
|
|
208
|
-
|
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
│ │
|
|
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:
|
|
3442
|
-
const { themeName } = await
|
|
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
|
});
|