@onexapis/cli 1.1.44 → 1.1.45
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/dist/cli.js +189 -461
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +189 -461
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +38 -14
- package/dist/index.d.ts +38 -14
- package/dist/index.js +284 -443
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +284 -442
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -3
package/dist/cli.js
CHANGED
|
@@ -20,7 +20,6 @@ var inquirer = require('inquirer');
|
|
|
20
20
|
var archiver = require('archiver');
|
|
21
21
|
var FormData = require('form-data');
|
|
22
22
|
var fetch2 = require('node-fetch');
|
|
23
|
-
var clientS3 = require('@aws-sdk/client-s3');
|
|
24
23
|
var AdmZip = require('adm-zip');
|
|
25
24
|
var chokidar = require('chokidar');
|
|
26
25
|
var http = require('http');
|
|
@@ -3486,343 +3485,94 @@ async function deployCommand(options) {
|
|
|
3486
3485
|
|
|
3487
3486
|
// src/commands/upload.ts
|
|
3488
3487
|
init_logger();
|
|
3489
|
-
function
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
endpoint: endpointUrl,
|
|
3497
|
-
region: "us-east-1",
|
|
3498
|
-
credentials: {
|
|
3499
|
-
accessKeyId: process.env.MINIO_ACCESS_KEY || "minioadmin",
|
|
3500
|
-
secretAccessKey: process.env.MINIO_SECRET_KEY || "minioadmin"
|
|
3501
|
-
},
|
|
3502
|
-
forcePathStyle: true
|
|
3503
|
-
});
|
|
3504
|
-
}
|
|
3505
|
-
if (adapterMode === "local") {
|
|
3506
|
-
return new clientS3.S3Client({
|
|
3507
|
-
endpoint: "http://localhost:4569",
|
|
3508
|
-
region: "ap-southeast-1",
|
|
3509
|
-
credentials: {
|
|
3510
|
-
accessKeyId: "S3RVER",
|
|
3511
|
-
secretAccessKey: "S3RVER"
|
|
3512
|
-
},
|
|
3513
|
-
forcePathStyle: true
|
|
3514
|
-
});
|
|
3515
|
-
}
|
|
3516
|
-
return new clientS3.S3Client({
|
|
3517
|
-
region: process.env.AWS_REGION || "ap-southeast-1"
|
|
3518
|
-
});
|
|
3519
|
-
}
|
|
3520
|
-
function getBucketName(env) {
|
|
3521
|
-
if (process.env.BUCKET_NAME) {
|
|
3522
|
-
return process.env.BUCKET_NAME;
|
|
3523
|
-
}
|
|
3524
|
-
const environment = env || process.env.ENVIRONMENT || "staging";
|
|
3525
|
-
return environment === "production" ? "theme-s3-bucket" : "theme-s3-bucket";
|
|
3526
|
-
}
|
|
3527
|
-
async function findCompiledThemeDir(themeId, version2) {
|
|
3528
|
-
const searchPaths = [path9__default.default.resolve(process.cwd(), "dist")];
|
|
3529
|
-
for (const dir of searchPaths) {
|
|
3530
|
-
if (await fs__default.default.pathExists(dir)) {
|
|
3531
|
-
const hasManifest = await fs__default.default.pathExists(path9__default.default.join(dir, "manifest.json"));
|
|
3532
|
-
const hasThemeEntry = await fs__default.default.pathExists(path9__default.default.join(dir, "bundle-entry.js")) || await fs__default.default.pathExists(path9__default.default.join(dir, "theme.config.js")) || await fs__default.default.pathExists(path9__default.default.join(dir, "index.js"));
|
|
3533
|
-
if (hasManifest || hasThemeEntry) {
|
|
3534
|
-
return dir;
|
|
3535
|
-
}
|
|
3536
|
-
}
|
|
3537
|
-
}
|
|
3538
|
-
return null;
|
|
3539
|
-
}
|
|
3540
|
-
async function readManifest() {
|
|
3541
|
-
const manifestTsPath = path9__default.default.resolve(process.cwd(), "manifest.ts");
|
|
3542
|
-
if (await fs__default.default.pathExists(manifestTsPath)) {
|
|
3543
|
-
try {
|
|
3544
|
-
const module = await import(manifestTsPath);
|
|
3545
|
-
return module.default || module;
|
|
3546
|
-
} catch (error) {
|
|
3547
|
-
logger.warning("Failed to import manifest.ts, trying package.json");
|
|
3548
|
-
}
|
|
3549
|
-
}
|
|
3550
|
-
const packageJsonPath = path9__default.default.resolve(process.cwd(), "package.json");
|
|
3551
|
-
if (await fs__default.default.pathExists(packageJsonPath)) {
|
|
3552
|
-
const pkg = await fs__default.default.readJson(packageJsonPath);
|
|
3553
|
-
return {
|
|
3554
|
-
themeId: pkg.name?.replace("@onex-themes/", "") || "unknown",
|
|
3555
|
-
version: pkg.version || "1.0.0"
|
|
3556
|
-
};
|
|
3557
|
-
}
|
|
3558
|
-
throw new Error(
|
|
3559
|
-
"No manifest.ts or package.json found. Are you in a theme directory?"
|
|
3488
|
+
async function uploadCommand(_options) {
|
|
3489
|
+
logger.header("Upload Theme to S3 \u2014 DEPRECATED");
|
|
3490
|
+
console.log();
|
|
3491
|
+
console.log(
|
|
3492
|
+
chalk4__default.default.yellow.bold(
|
|
3493
|
+
"`onexthm upload` is deprecated and no longer functional."
|
|
3494
|
+
)
|
|
3560
3495
|
);
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
const output = fs__default.default.createWriteStream(outputPath);
|
|
3565
|
-
const archive = archiver__default.default("zip", { zlib: { level: 6 } });
|
|
3566
|
-
output.on("close", () => resolve());
|
|
3567
|
-
archive.on("error", (err) => reject(err));
|
|
3568
|
-
archive.pipe(output);
|
|
3569
|
-
archive.glob("**/*", {
|
|
3570
|
-
cwd: sourceDir,
|
|
3571
|
-
dot: true,
|
|
3572
|
-
ignore: excludePatterns
|
|
3573
|
-
});
|
|
3574
|
-
archive.finalize();
|
|
3575
|
-
});
|
|
3576
|
-
}
|
|
3577
|
-
async function findSourceDir(themeId, explicitDir) {
|
|
3578
|
-
if (explicitDir) {
|
|
3579
|
-
if (await fs__default.default.pathExists(explicitDir)) return explicitDir;
|
|
3580
|
-
return null;
|
|
3581
|
-
}
|
|
3582
|
-
const searchPaths = [
|
|
3583
|
-
process.cwd(),
|
|
3584
|
-
path9__default.default.resolve(process.cwd(), `../../themes/${themeId}`),
|
|
3585
|
-
path9__default.default.resolve(process.cwd(), `../themes/${themeId}`)
|
|
3586
|
-
];
|
|
3587
|
-
const markers = ["theme.config.ts", "bundle-entry.ts"];
|
|
3588
|
-
for (const dir of searchPaths) {
|
|
3589
|
-
for (const marker of markers) {
|
|
3590
|
-
if (await fs__default.default.pathExists(path9__default.default.join(dir, marker))) {
|
|
3591
|
-
return dir;
|
|
3592
|
-
}
|
|
3593
|
-
}
|
|
3594
|
-
}
|
|
3595
|
-
return null;
|
|
3596
|
-
}
|
|
3597
|
-
async function updateLatestPointer(s3Client, bucket, themeId, version2) {
|
|
3598
|
-
const latestData = {
|
|
3599
|
-
version: version2,
|
|
3600
|
-
uploadedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3601
|
-
};
|
|
3602
|
-
await s3Client.send(
|
|
3603
|
-
new clientS3.PutObjectCommand({
|
|
3604
|
-
Bucket: bucket,
|
|
3605
|
-
Key: `themes/${themeId}/latest.json`,
|
|
3606
|
-
Body: JSON.stringify(latestData, null, 2),
|
|
3607
|
-
ContentType: "application/json"
|
|
3608
|
-
})
|
|
3496
|
+
console.log();
|
|
3497
|
+
console.log(
|
|
3498
|
+
"The platform no longer exposes themes via direct S3 access, so this"
|
|
3609
3499
|
);
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
if (!compiledDir) {
|
|
3630
|
-
spinner.fail(
|
|
3631
|
-
chalk4__default.default.red(
|
|
3632
|
-
`Compiled theme not found for ${themeId}@${version2}. Run 'onexthm build' first.`
|
|
3633
|
-
)
|
|
3634
|
-
);
|
|
3635
|
-
logger.info(chalk4__default.default.gray(`Expected location:
|
|
3636
|
-
- ./dist/`));
|
|
3637
|
-
process.exit(1);
|
|
3638
|
-
}
|
|
3639
|
-
spinner.succeed(`Found compiled theme at: ${compiledDir}`);
|
|
3640
|
-
spinner.start("Creating bundle.zip...");
|
|
3641
|
-
const tmpDir = os__default.default.tmpdir();
|
|
3642
|
-
const bundleZipPath = path9__default.default.join(tmpDir, `${themeId}-${version2}-bundle.zip`);
|
|
3643
|
-
await createZipFromDir(compiledDir, bundleZipPath);
|
|
3644
|
-
const bundleZipBuffer = await fs__default.default.readFile(bundleZipPath);
|
|
3645
|
-
const bundleSizeMB = (bundleZipBuffer.length / 1024 / 1024).toFixed(2);
|
|
3646
|
-
spinner.succeed(`Created bundle.zip (${bundleSizeMB} MB)`);
|
|
3647
|
-
if (options.dryRun) {
|
|
3648
|
-
spinner.info(chalk4__default.default.yellow("Dry run mode \u2014 no files will be uploaded"));
|
|
3649
|
-
console.log();
|
|
3650
|
-
console.log(chalk4__default.default.gray(` bundle.zip: ${bundleSizeMB} MB`));
|
|
3651
|
-
console.log(
|
|
3652
|
-
chalk4__default.default.cyan(
|
|
3653
|
-
` S3 path: s3://${bucket}/themes/${themeId}/${version2}/bundle.zip`
|
|
3654
|
-
)
|
|
3655
|
-
);
|
|
3656
|
-
if (!options.skipSource) {
|
|
3657
|
-
const sourceDir = await findSourceDir(themeId, options.sourceDir);
|
|
3658
|
-
if (sourceDir) {
|
|
3659
|
-
console.log(chalk4__default.default.gray(` source dir: ${sourceDir}`));
|
|
3660
|
-
console.log(
|
|
3661
|
-
chalk4__default.default.cyan(
|
|
3662
|
-
` S3 path: s3://${bucket}/themes/${themeId}/${version2}/source.zip`
|
|
3663
|
-
)
|
|
3664
|
-
);
|
|
3665
|
-
} else {
|
|
3666
|
-
console.log(
|
|
3667
|
-
chalk4__default.default.yellow(" source dir: not found (source.zip will be skipped)")
|
|
3668
|
-
);
|
|
3669
|
-
}
|
|
3670
|
-
}
|
|
3671
|
-
console.log();
|
|
3672
|
-
await fs__default.default.remove(bundleZipPath);
|
|
3673
|
-
return;
|
|
3674
|
-
}
|
|
3675
|
-
spinner.start("Uploading bundle.zip to S3...");
|
|
3676
|
-
const bundleS3Key = `themes/${themeId}/${version2}/bundle.zip`;
|
|
3677
|
-
await s3Client.send(
|
|
3678
|
-
new clientS3.PutObjectCommand({
|
|
3679
|
-
Bucket: bucket,
|
|
3680
|
-
Key: bundleS3Key,
|
|
3681
|
-
Body: bundleZipBuffer,
|
|
3682
|
-
ContentType: "application/zip"
|
|
3683
|
-
})
|
|
3684
|
-
);
|
|
3685
|
-
spinner.succeed(
|
|
3686
|
-
`Uploaded bundle.zip ${chalk4__default.default.gray(`\u2192 s3://${bucket}/${bundleS3Key}`)}`
|
|
3687
|
-
);
|
|
3688
|
-
await fs__default.default.remove(bundleZipPath);
|
|
3689
|
-
let sourceUploaded = false;
|
|
3690
|
-
if (!options.skipSource) {
|
|
3691
|
-
spinner.start("Looking for source directory...");
|
|
3692
|
-
const sourceDir = await findSourceDir(themeId, options.sourceDir);
|
|
3693
|
-
if (sourceDir) {
|
|
3694
|
-
spinner.succeed(`Found source at: ${sourceDir}`);
|
|
3695
|
-
spinner.start("Creating source.zip...");
|
|
3696
|
-
const sourceZipPath = path9__default.default.join(
|
|
3697
|
-
tmpDir,
|
|
3698
|
-
`${themeId}-${version2}-source.zip`
|
|
3699
|
-
);
|
|
3700
|
-
await createZipFromDir(sourceDir, sourceZipPath, [
|
|
3701
|
-
"node_modules/**",
|
|
3702
|
-
"dist/**",
|
|
3703
|
-
".git/**",
|
|
3704
|
-
"*.zip",
|
|
3705
|
-
".next/**",
|
|
3706
|
-
".turbo/**"
|
|
3707
|
-
]);
|
|
3708
|
-
const sourceZipBuffer = await fs__default.default.readFile(sourceZipPath);
|
|
3709
|
-
const sourceSizeMB = (sourceZipBuffer.length / 1024 / 1024).toFixed(2);
|
|
3710
|
-
spinner.succeed(`Created source.zip (${sourceSizeMB} MB)`);
|
|
3711
|
-
spinner.start("Uploading source.zip to S3...");
|
|
3712
|
-
const sourceS3Key = `themes/${themeId}/${version2}/source.zip`;
|
|
3713
|
-
await s3Client.send(
|
|
3714
|
-
new clientS3.PutObjectCommand({
|
|
3715
|
-
Bucket: bucket,
|
|
3716
|
-
Key: sourceS3Key,
|
|
3717
|
-
Body: sourceZipBuffer,
|
|
3718
|
-
ContentType: "application/zip"
|
|
3719
|
-
})
|
|
3720
|
-
);
|
|
3721
|
-
spinner.succeed(
|
|
3722
|
-
`Uploaded source.zip ${chalk4__default.default.gray(`\u2192 s3://${bucket}/${sourceS3Key}`)}`
|
|
3723
|
-
);
|
|
3724
|
-
await fs__default.default.remove(sourceZipPath);
|
|
3725
|
-
sourceUploaded = true;
|
|
3726
|
-
} else {
|
|
3727
|
-
spinner.warn(
|
|
3728
|
-
chalk4__default.default.yellow("Source directory not found \u2014 skipping source.zip")
|
|
3729
|
-
);
|
|
3730
|
-
}
|
|
3731
|
-
}
|
|
3732
|
-
spinner.start("Updating latest.json pointer...");
|
|
3733
|
-
await updateLatestPointer(s3Client, bucket, themeId, version2);
|
|
3734
|
-
spinner.succeed("Updated latest.json pointer");
|
|
3735
|
-
console.log();
|
|
3736
|
-
logger.success(chalk4__default.default.green.bold("Theme uploaded successfully!"));
|
|
3737
|
-
console.log();
|
|
3738
|
-
console.log(
|
|
3739
|
-
chalk4__default.default.cyan(" Theme: ") + chalk4__default.default.white(`${themeId}@${version2}`)
|
|
3740
|
-
);
|
|
3741
|
-
console.log(chalk4__default.default.cyan(" Bucket: ") + chalk4__default.default.white(bucket));
|
|
3742
|
-
console.log(
|
|
3743
|
-
chalk4__default.default.cyan(" Files: ") + chalk4__default.default.white(`bundle.zip${sourceUploaded ? " + source.zip" : ""}`)
|
|
3744
|
-
);
|
|
3745
|
-
console.log(
|
|
3746
|
-
chalk4__default.default.cyan(" Path: ") + chalk4__default.default.gray(`s3://${bucket}/themes/${themeId}/${version2}/`)
|
|
3747
|
-
);
|
|
3748
|
-
console.log();
|
|
3749
|
-
} catch (error) {
|
|
3750
|
-
spinner.fail(chalk4__default.default.red(`Upload failed: ${error.message}`));
|
|
3751
|
-
logger.error(error.stack || error.message);
|
|
3752
|
-
process.exit(1);
|
|
3753
|
-
}
|
|
3500
|
+
console.log(
|
|
3501
|
+
"command can no longer reach the bucket. Use `onexthm publish` instead:"
|
|
3502
|
+
);
|
|
3503
|
+
console.log();
|
|
3504
|
+
console.log(chalk4__default.default.cyan(" cd themes/your-theme"));
|
|
3505
|
+
console.log(chalk4__default.default.cyan(" onexthm login # one-time, refreshes JWT"));
|
|
3506
|
+
console.log(
|
|
3507
|
+
chalk4__default.default.cyan(" onexthm publish # builds + uploads + confirms")
|
|
3508
|
+
);
|
|
3509
|
+
console.log();
|
|
3510
|
+
console.log(
|
|
3511
|
+
"`publish` does everything this command did (build, version bump,"
|
|
3512
|
+
);
|
|
3513
|
+
console.log(
|
|
3514
|
+
"bundle + source upload) plus content-hashed asset upload, security"
|
|
3515
|
+
);
|
|
3516
|
+
console.log("scanning, and atomic version registration in one step.");
|
|
3517
|
+
console.log();
|
|
3518
|
+
process.exit(1);
|
|
3754
3519
|
}
|
|
3755
3520
|
|
|
3756
3521
|
// src/commands/download.ts
|
|
3757
3522
|
init_logger();
|
|
3758
|
-
function
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
const endpoint = process.env.MINIO_ENDPOINT || "localhost:9000";
|
|
3762
|
-
const secure = process.env.MINIO_SECURE === "true";
|
|
3763
|
-
const endpointUrl = endpoint.startsWith("http") ? endpoint : `${secure ? "https" : "http"}://${endpoint}`;
|
|
3764
|
-
return new clientS3.S3Client({
|
|
3765
|
-
endpoint: endpointUrl,
|
|
3766
|
-
region: "us-east-1",
|
|
3767
|
-
credentials: {
|
|
3768
|
-
accessKeyId: process.env.MINIO_ACCESS_KEY || "minioadmin",
|
|
3769
|
-
secretAccessKey: process.env.MINIO_SECRET_KEY || "minioadmin"
|
|
3770
|
-
},
|
|
3771
|
-
forcePathStyle: true
|
|
3772
|
-
});
|
|
3773
|
-
}
|
|
3774
|
-
if (adapterMode === "local") {
|
|
3775
|
-
return new clientS3.S3Client({
|
|
3776
|
-
endpoint: "http://localhost:4569",
|
|
3777
|
-
region: "ap-southeast-1",
|
|
3778
|
-
credentials: {
|
|
3779
|
-
accessKeyId: "S3RVER",
|
|
3780
|
-
secretAccessKey: "S3RVER"
|
|
3781
|
-
},
|
|
3782
|
-
forcePathStyle: true
|
|
3783
|
-
});
|
|
3523
|
+
function unwrapEnvelope(raw) {
|
|
3524
|
+
if (raw && typeof raw === "object" && "statusCode" in raw && "body" in raw) {
|
|
3525
|
+
return raw.body;
|
|
3784
3526
|
}
|
|
3785
|
-
return
|
|
3786
|
-
region: process.env.AWS_REGION || "ap-southeast-1"
|
|
3787
|
-
});
|
|
3527
|
+
return raw;
|
|
3788
3528
|
}
|
|
3789
|
-
function
|
|
3790
|
-
|
|
3791
|
-
|
|
3529
|
+
async function resolveLatestVersion(apiUrl, themeId) {
|
|
3530
|
+
const url = `${apiUrl}/website-api/themes/${encodeURIComponent(themeId)}/versions`;
|
|
3531
|
+
let response;
|
|
3532
|
+
try {
|
|
3533
|
+
response = await fetch(url, { cache: "no-store" });
|
|
3534
|
+
} catch (err) {
|
|
3535
|
+
throw new Error(
|
|
3536
|
+
`Network error contacting ${url}: ${err instanceof Error ? err.message : "unknown"}`
|
|
3537
|
+
);
|
|
3792
3538
|
}
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
}
|
|
3796
|
-
|
|
3797
|
-
const chunks = [];
|
|
3798
|
-
for await (const chunk of stream) {
|
|
3799
|
-
chunks.push(Buffer.from(chunk));
|
|
3539
|
+
if (!response.ok) {
|
|
3540
|
+
throw new Error(
|
|
3541
|
+
`Version lookup failed for "${themeId}" (HTTP ${response.status})`
|
|
3542
|
+
);
|
|
3800
3543
|
}
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3544
|
+
const raw = await response.json();
|
|
3545
|
+
const data = unwrapEnvelope(raw);
|
|
3546
|
+
const latest = data?.latest_version;
|
|
3547
|
+
if (typeof latest !== "string" || latest.length === 0) {
|
|
3548
|
+
throw new Error(
|
|
3549
|
+
`Theme "${themeId}" has no published versions yet (no latest_version in response)`
|
|
3550
|
+
);
|
|
3807
3551
|
}
|
|
3808
|
-
return
|
|
3552
|
+
return latest;
|
|
3809
3553
|
}
|
|
3810
|
-
async function
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
Bucket: bucket,
|
|
3815
|
-
Key: `themes/${themeId}/latest.json`
|
|
3816
|
-
})
|
|
3817
|
-
);
|
|
3818
|
-
const body = await streamToString(response.Body);
|
|
3819
|
-
const data = JSON.parse(body);
|
|
3820
|
-
return data.version;
|
|
3821
|
-
} catch (error) {
|
|
3554
|
+
async function downloadBundleZip(apiUrl, themeId, version2) {
|
|
3555
|
+
const url = `${apiUrl}/website-api/themes/${encodeURIComponent(themeId)}/${encodeURIComponent(version2)}/download`;
|
|
3556
|
+
const response = await fetch(url);
|
|
3557
|
+
if (!response.ok) {
|
|
3822
3558
|
throw new Error(
|
|
3823
|
-
`
|
|
3559
|
+
`Bundle download failed for "${themeId}@${version2}" (HTTP ${response.status})`
|
|
3824
3560
|
);
|
|
3825
3561
|
}
|
|
3562
|
+
const contentType = response.headers.get("content-type") || "";
|
|
3563
|
+
if (contentType.includes("application/json")) {
|
|
3564
|
+
const raw = await response.json();
|
|
3565
|
+
const envelope = raw && typeof raw === "object" && "statusCode" in raw ? raw : { body: raw };
|
|
3566
|
+
const body = envelope.body;
|
|
3567
|
+
if (typeof body !== "string") {
|
|
3568
|
+
throw new Error(
|
|
3569
|
+
"Unexpected /download response shape: expected base64 string in body"
|
|
3570
|
+
);
|
|
3571
|
+
}
|
|
3572
|
+
return Buffer.from(body, "base64");
|
|
3573
|
+
}
|
|
3574
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
3575
|
+
return Buffer.from(arrayBuffer);
|
|
3826
3576
|
}
|
|
3827
3577
|
async function createCompatibilityFiles(outputDir, manifest) {
|
|
3828
3578
|
const entryFile = manifest.output?.entry || "bundle-entry.js";
|
|
@@ -3846,47 +3596,58 @@ export * from './bundle-entry.js';
|
|
|
3846
3596
|
const pkgJsonPath = path9__default.default.join(outputDir, "package.json");
|
|
3847
3597
|
await fs__default.default.writeFile(pkgJsonPath, '{\n "type": "module"\n}\n', "utf-8");
|
|
3848
3598
|
}
|
|
3849
|
-
function showDownloadFailureHelp(themeId,
|
|
3599
|
+
function showDownloadFailureHelp(themeId, apiUrl) {
|
|
3850
3600
|
console.log();
|
|
3851
3601
|
logger.error(chalk4__default.default.red.bold("Theme download failed"));
|
|
3852
3602
|
console.log();
|
|
3853
3603
|
console.log(chalk4__default.default.yellow("Possible reasons:"));
|
|
3854
|
-
console.log(
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
console.log(
|
|
3604
|
+
console.log(
|
|
3605
|
+
chalk4__default.default.gray(" 1. Theme has not been published yet (run `onexthm publish`)")
|
|
3606
|
+
);
|
|
3607
|
+
console.log(
|
|
3608
|
+
chalk4__default.default.gray(
|
|
3609
|
+
" 2. Theme ID is wrong (typo in --theme-id or THEME_ID env var)"
|
|
3610
|
+
)
|
|
3611
|
+
);
|
|
3612
|
+
console.log(
|
|
3613
|
+
chalk4__default.default.gray(" 3. API base URL is wrong or the website-api is unreachable")
|
|
3614
|
+
);
|
|
3858
3615
|
console.log();
|
|
3859
3616
|
console.log(chalk4__default.default.cyan.bold("To fix this:"));
|
|
3860
3617
|
console.log();
|
|
3861
|
-
console.log(chalk4__default.default.white("1.
|
|
3862
|
-
console.log(chalk4__default.default.gray(` cd themes/${themeId}`));
|
|
3863
|
-
console.log(chalk4__default.default.gray(" pnpm build"));
|
|
3864
|
-
console.log(chalk4__default.default.gray(" onexthm upload"));
|
|
3865
|
-
console.log();
|
|
3866
|
-
console.log(chalk4__default.default.white("2. Verify AWS credentials are set:"));
|
|
3618
|
+
console.log(chalk4__default.default.white("1. Verify the theme is published:"));
|
|
3867
3619
|
console.log(
|
|
3868
|
-
chalk4__default.default.gray(
|
|
3620
|
+
chalk4__default.default.gray(
|
|
3621
|
+
` curl -s ${apiUrl}/website-api/themes/${themeId}/versions | jq .latest_version`
|
|
3622
|
+
)
|
|
3869
3623
|
);
|
|
3870
|
-
console.log(chalk4__default.default.gray(" - Or use AWS_PROFILE=your-profile"));
|
|
3871
|
-
console.log(chalk4__default.default.gray(" - Set AWS_REGION (e.g., ap-southeast-1)"));
|
|
3872
3624
|
console.log();
|
|
3873
|
-
console.log(chalk4__default.default.white("
|
|
3874
|
-
console.log(chalk4__default.default.gray(` Current
|
|
3625
|
+
console.log(chalk4__default.default.white("2. Check API URL configuration:"));
|
|
3626
|
+
console.log(chalk4__default.default.gray(` Current API URL: ${apiUrl}`));
|
|
3875
3627
|
console.log(
|
|
3876
|
-
chalk4__default.default.gray("
|
|
3628
|
+
chalk4__default.default.gray(" Override with NEXT_PUBLIC_API_URL or ONEXTHM_API_URL")
|
|
3877
3629
|
);
|
|
3878
3630
|
console.log();
|
|
3879
|
-
console.log(chalk4__default.default.white("
|
|
3880
|
-
console.log(
|
|
3631
|
+
console.log(chalk4__default.default.white("3. Pin a specific version (CI/production):"));
|
|
3632
|
+
console.log(
|
|
3633
|
+
chalk4__default.default.gray(` THEME_VERSION=1.2.3 onexthm download --theme-id ${themeId}`)
|
|
3634
|
+
);
|
|
3881
3635
|
console.log();
|
|
3882
3636
|
}
|
|
3883
3637
|
async function downloadCommand(options) {
|
|
3884
|
-
logger.header("Download Theme
|
|
3638
|
+
logger.header("Download Theme");
|
|
3885
3639
|
const spinner = ora__default.default("Initializing download...").start();
|
|
3640
|
+
if (options.bucket || options.environment) {
|
|
3641
|
+
spinner.stop();
|
|
3642
|
+
logger.warning(
|
|
3643
|
+
"--bucket and --environment are deprecated and ignored. Themes are now served via HTTP from the website-api Lambda."
|
|
3644
|
+
);
|
|
3645
|
+
spinner.start();
|
|
3646
|
+
}
|
|
3647
|
+
const apiUrl = getApiUrl();
|
|
3886
3648
|
try {
|
|
3887
3649
|
const themeId = options.themeId || process.env.NEXT_PUBLIC_THEME_ID || process.env.THEME_ID;
|
|
3888
|
-
const
|
|
3889
|
-
const bucket = options.bucket || getBucketName2(options.environment);
|
|
3650
|
+
const requestedVersion = options.version || process.env.THEME_VERSION || "latest";
|
|
3890
3651
|
const outputDir = options.output || "./active-theme";
|
|
3891
3652
|
if (!themeId) {
|
|
3892
3653
|
spinner.fail(
|
|
@@ -3896,12 +3657,10 @@ async function downloadCommand(options) {
|
|
|
3896
3657
|
);
|
|
3897
3658
|
process.exit(1);
|
|
3898
3659
|
}
|
|
3899
|
-
spinner.text = `
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
spinner.text = "Resolving latest version...";
|
|
3904
|
-
resolvedVersion = await resolveLatestVersion(s3Client, bucket, themeId);
|
|
3660
|
+
spinner.text = `Resolving ${themeId}@${requestedVersion}...`;
|
|
3661
|
+
let resolvedVersion = requestedVersion;
|
|
3662
|
+
if (requestedVersion === "latest") {
|
|
3663
|
+
resolvedVersion = await resolveLatestVersion(apiUrl, themeId);
|
|
3905
3664
|
spinner.succeed(
|
|
3906
3665
|
`Resolved latest version: ${chalk4__default.default.cyan(resolvedVersion)}`
|
|
3907
3666
|
);
|
|
@@ -3911,24 +3670,19 @@ async function downloadCommand(options) {
|
|
|
3911
3670
|
chalk4__default.default.yellow(
|
|
3912
3671
|
`
|
|
3913
3672
|
Warning: Resolved "latest" to ${resolvedVersion} in CI environment.
|
|
3914
|
-
For
|
|
3673
|
+
For reproducible builds, pin to a specific version:
|
|
3915
3674
|
THEME_VERSION=${resolvedVersion}
|
|
3916
3675
|
`
|
|
3917
3676
|
)
|
|
3918
3677
|
);
|
|
3919
3678
|
}
|
|
3679
|
+
} else {
|
|
3680
|
+
spinner.succeed(`Using version: ${chalk4__default.default.cyan(resolvedVersion)}`);
|
|
3920
3681
|
}
|
|
3921
3682
|
spinner.start(
|
|
3922
3683
|
`Downloading bundle.zip for ${themeId}@${resolvedVersion}...`
|
|
3923
3684
|
);
|
|
3924
|
-
const
|
|
3925
|
-
const response = await s3Client.send(
|
|
3926
|
-
new clientS3.GetObjectCommand({
|
|
3927
|
-
Bucket: bucket,
|
|
3928
|
-
Key: s3Key
|
|
3929
|
-
})
|
|
3930
|
-
);
|
|
3931
|
-
const zipBuffer = await streamToBuffer(response.Body);
|
|
3685
|
+
const zipBuffer = await downloadBundleZip(apiUrl, themeId, resolvedVersion);
|
|
3932
3686
|
const sizeMB = (zipBuffer.length / 1024 / 1024).toFixed(2);
|
|
3933
3687
|
spinner.succeed(`Downloaded bundle.zip (${sizeMB} MB)`);
|
|
3934
3688
|
spinner.start("Extracting bundle...");
|
|
@@ -3947,7 +3701,7 @@ async function downloadCommand(options) {
|
|
|
3947
3701
|
console.log(
|
|
3948
3702
|
chalk4__default.default.cyan(" Theme: ") + chalk4__default.default.white(`${themeId}@${resolvedVersion}`)
|
|
3949
3703
|
);
|
|
3950
|
-
console.log(chalk4__default.default.cyan("
|
|
3704
|
+
console.log(chalk4__default.default.cyan(" Source: ") + chalk4__default.default.white(apiUrl));
|
|
3951
3705
|
console.log(chalk4__default.default.cyan(" Output: ") + chalk4__default.default.white(outputDir));
|
|
3952
3706
|
console.log(chalk4__default.default.cyan(" Files: ") + chalk4__default.default.white(entries.length));
|
|
3953
3707
|
if (manifest.counts) {
|
|
@@ -3959,82 +3713,70 @@ async function downloadCommand(options) {
|
|
|
3959
3713
|
} catch (error) {
|
|
3960
3714
|
spinner.fail(chalk4__default.default.red("Download failed"));
|
|
3961
3715
|
logger.error(error.message);
|
|
3962
|
-
const themeId = options.themeId || process.env.NEXT_PUBLIC_THEME_ID || "unknown";
|
|
3963
|
-
|
|
3964
|
-
showDownloadFailureHelp(themeId, bucket);
|
|
3716
|
+
const themeId = options.themeId || process.env.NEXT_PUBLIC_THEME_ID || process.env.THEME_ID || "unknown";
|
|
3717
|
+
showDownloadFailureHelp(themeId, apiUrl);
|
|
3965
3718
|
process.exit(1);
|
|
3966
3719
|
}
|
|
3967
3720
|
}
|
|
3968
3721
|
|
|
3969
3722
|
// src/commands/clone.ts
|
|
3970
3723
|
init_logger();
|
|
3971
|
-
function
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
const endpoint = process.env.MINIO_ENDPOINT || "localhost:9000";
|
|
3975
|
-
const secure = process.env.MINIO_SECURE === "true";
|
|
3976
|
-
const endpointUrl = endpoint.startsWith("http") ? endpoint : `${secure ? "https" : "http"}://${endpoint}`;
|
|
3977
|
-
return new clientS3.S3Client({
|
|
3978
|
-
endpoint: endpointUrl,
|
|
3979
|
-
region: "us-east-1",
|
|
3980
|
-
credentials: {
|
|
3981
|
-
accessKeyId: process.env.MINIO_ACCESS_KEY || "minioadmin",
|
|
3982
|
-
secretAccessKey: process.env.MINIO_SECRET_KEY || "minioadmin"
|
|
3983
|
-
},
|
|
3984
|
-
forcePathStyle: true
|
|
3985
|
-
});
|
|
3986
|
-
}
|
|
3987
|
-
if (adapterMode === "local") {
|
|
3988
|
-
return new clientS3.S3Client({
|
|
3989
|
-
endpoint: "http://localhost:4569",
|
|
3990
|
-
region: "ap-southeast-1",
|
|
3991
|
-
credentials: {
|
|
3992
|
-
accessKeyId: "S3RVER",
|
|
3993
|
-
secretAccessKey: "S3RVER"
|
|
3994
|
-
},
|
|
3995
|
-
forcePathStyle: true
|
|
3996
|
-
});
|
|
3724
|
+
function unwrapEnvelope2(raw) {
|
|
3725
|
+
if (raw && typeof raw === "object" && "statusCode" in raw && "body" in raw) {
|
|
3726
|
+
return raw.body;
|
|
3997
3727
|
}
|
|
3998
|
-
return
|
|
3999
|
-
region: process.env.AWS_REGION || "ap-southeast-1"
|
|
4000
|
-
});
|
|
3728
|
+
return raw;
|
|
4001
3729
|
}
|
|
4002
|
-
function
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
async function streamToString2(stream) {
|
|
4010
|
-
const chunks = [];
|
|
4011
|
-
for await (const chunk of stream) {
|
|
4012
|
-
chunks.push(Buffer.from(chunk));
|
|
3730
|
+
async function resolveLatestVersion2(apiUrl, themeId) {
|
|
3731
|
+
const url = `${apiUrl}/website-api/themes/${encodeURIComponent(themeId)}/versions`;
|
|
3732
|
+
const response = await fetch(url, { cache: "no-store" });
|
|
3733
|
+
if (!response.ok) {
|
|
3734
|
+
throw new Error(
|
|
3735
|
+
`Version lookup failed for "${themeId}" (HTTP ${response.status})`
|
|
3736
|
+
);
|
|
4013
3737
|
}
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
chunks.push(Buffer.from(chunk));
|
|
3738
|
+
const raw = await response.json();
|
|
3739
|
+
const data = unwrapEnvelope2(raw);
|
|
3740
|
+
const latest = data?.latest_version;
|
|
3741
|
+
if (typeof latest !== "string" || latest.length === 0) {
|
|
3742
|
+
throw new Error(`Theme "${themeId}" has no published versions yet`);
|
|
4020
3743
|
}
|
|
4021
|
-
return
|
|
3744
|
+
return latest;
|
|
4022
3745
|
}
|
|
4023
|
-
async function
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
|
|
3746
|
+
async function fetchSourceZip(apiUrl, themeId, version2) {
|
|
3747
|
+
const url = `${apiUrl}/website-api/themes/${encodeURIComponent(themeId)}/source?version=${encodeURIComponent(version2)}`;
|
|
3748
|
+
const response = await authenticatedFetch(url, {
|
|
3749
|
+
method: "GET"
|
|
3750
|
+
});
|
|
3751
|
+
if (!response.ok) {
|
|
3752
|
+
if (response.status === 404) {
|
|
3753
|
+
throw new Error(
|
|
3754
|
+
`Source not found for ${themeId}@${version2}. The theme may not have been published with source upload enabled.`
|
|
3755
|
+
);
|
|
3756
|
+
}
|
|
3757
|
+
if (response.status === 401 || response.status === 403) {
|
|
3758
|
+
throw new Error(
|
|
3759
|
+
`Not authorized to download source for "${themeId}". Run \`onexthm login\` first.`
|
|
3760
|
+
);
|
|
3761
|
+
}
|
|
3762
|
+
throw new Error(
|
|
3763
|
+
`Source URL request failed for "${themeId}@${version2}" (HTTP ${response.status})`
|
|
4030
3764
|
);
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
3765
|
+
}
|
|
3766
|
+
const raw = await response.json();
|
|
3767
|
+
const data = unwrapEnvelope2(raw);
|
|
3768
|
+
const presignedUrl = data?.download_url;
|
|
3769
|
+
if (typeof presignedUrl !== "string" || presignedUrl.length === 0) {
|
|
3770
|
+
throw new Error("Unexpected /source response shape: missing download_url");
|
|
3771
|
+
}
|
|
3772
|
+
const zipResponse = await fetch(presignedUrl);
|
|
3773
|
+
if (!zipResponse.ok) {
|
|
4034
3774
|
throw new Error(
|
|
4035
|
-
`
|
|
3775
|
+
`Presigned source download failed (HTTP ${zipResponse.status})`
|
|
4036
3776
|
);
|
|
4037
3777
|
}
|
|
3778
|
+
const arrayBuffer = await zipResponse.arrayBuffer();
|
|
3779
|
+
return Buffer.from(arrayBuffer);
|
|
4038
3780
|
}
|
|
4039
3781
|
function runInstall(cwd) {
|
|
4040
3782
|
return new Promise((resolve) => {
|
|
@@ -4133,15 +3875,24 @@ async function renameTheme(themeDir, oldName, newName) {
|
|
|
4133
3875
|
}
|
|
4134
3876
|
async function cloneCommand(themeName, options) {
|
|
4135
3877
|
logger.header("Clone Theme Source");
|
|
3878
|
+
if (options.bucket || options.environment) {
|
|
3879
|
+
logger.warning(
|
|
3880
|
+
"--bucket and --environment are deprecated and ignored. Source is now fetched via HTTP from the website-api Lambda."
|
|
3881
|
+
);
|
|
3882
|
+
}
|
|
3883
|
+
const tokens = await getValidTokens();
|
|
3884
|
+
if (!tokens) {
|
|
3885
|
+
logger.error("Not logged in. Run: onexthm login");
|
|
3886
|
+
process.exit(1);
|
|
3887
|
+
}
|
|
4136
3888
|
let newName = options.name;
|
|
4137
3889
|
if (!newName) {
|
|
4138
3890
|
newName = await promptThemeName(themeName);
|
|
4139
3891
|
}
|
|
4140
3892
|
const spinner = ora__default.default("Initializing clone...").start();
|
|
4141
3893
|
try {
|
|
4142
|
-
const
|
|
3894
|
+
const apiUrl = getApiUrl();
|
|
4143
3895
|
const outputDir = options.output || path9__default.default.resolve(process.cwd(), newName);
|
|
4144
|
-
const s3Client = getS3Client3();
|
|
4145
3896
|
if (await fs__default.default.pathExists(outputDir)) {
|
|
4146
3897
|
spinner.fail(chalk4__default.default.red(`Directory already exists: ${outputDir}`));
|
|
4147
3898
|
logger.info(
|
|
@@ -4154,28 +3905,20 @@ async function cloneCommand(themeName, options) {
|
|
|
4154
3905
|
let version2 = options.version || "latest";
|
|
4155
3906
|
if (version2 === "latest") {
|
|
4156
3907
|
spinner.text = "Resolving latest version...";
|
|
4157
|
-
version2 = await resolveLatestVersion2(
|
|
3908
|
+
version2 = await resolveLatestVersion2(apiUrl, themeName);
|
|
4158
3909
|
spinner.succeed(`Resolved latest version: ${chalk4__default.default.cyan(version2)}`);
|
|
4159
3910
|
}
|
|
4160
3911
|
spinner.start(`Downloading source.zip for ${themeName}@${version2}...`);
|
|
4161
|
-
const s3Key = `themes/${themeName}/${version2}/source.zip`;
|
|
4162
3912
|
let zipBuffer;
|
|
4163
3913
|
try {
|
|
4164
|
-
|
|
4165
|
-
new clientS3.GetObjectCommand({
|
|
4166
|
-
Bucket: bucket,
|
|
4167
|
-
Key: s3Key
|
|
4168
|
-
})
|
|
4169
|
-
);
|
|
4170
|
-
zipBuffer = await streamToBuffer2(response.Body);
|
|
3914
|
+
zipBuffer = await fetchSourceZip(apiUrl, themeName, version2);
|
|
4171
3915
|
} catch (error) {
|
|
4172
|
-
spinner.fail(chalk4__default.default.red(
|
|
3916
|
+
spinner.fail(chalk4__default.default.red(error.message));
|
|
4173
3917
|
console.log();
|
|
4174
3918
|
console.log(
|
|
4175
|
-
chalk4__default.default.
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
chalk4__default.default.gray(`Upload source with: onexthm upload --theme ${themeName}`)
|
|
3919
|
+
chalk4__default.default.gray(
|
|
3920
|
+
`Verify the theme is published: curl -s ${apiUrl}/website-api/themes/${themeName}/versions`
|
|
3921
|
+
)
|
|
4179
3922
|
);
|
|
4180
3923
|
console.log();
|
|
4181
3924
|
process.exit(1);
|
|
@@ -4358,10 +4101,7 @@ function createDevServer(options) {
|
|
|
4358
4101
|
return;
|
|
4359
4102
|
}
|
|
4360
4103
|
if (segments.length > 1) {
|
|
4361
|
-
const fallbackPath = path9__default.default.join(
|
|
4362
|
-
assetsBase,
|
|
4363
|
-
segments.slice(1).join("/")
|
|
4364
|
-
);
|
|
4104
|
+
const fallbackPath = path9__default.default.join(assetsBase, segments.slice(1).join("/"));
|
|
4365
4105
|
if (fallbackPath.startsWith(assetsBase) && fs3__default.default.existsSync(fallbackPath)) {
|
|
4366
4106
|
serveFile(res, fallbackPath);
|
|
4367
4107
|
return;
|
|
@@ -5299,11 +5039,11 @@ Or use the --bump flag:
|
|
|
5299
5039
|
logger.success(`\u2713 Theme "${themeId}" v${version2} published!`);
|
|
5300
5040
|
}
|
|
5301
5041
|
async function createZip(sourceDir, outputPath, exclude) {
|
|
5302
|
-
const
|
|
5042
|
+
const archiver2 = (await import('archiver')).default;
|
|
5303
5043
|
const { createWriteStream } = await import('fs');
|
|
5304
5044
|
return new Promise((resolve, reject) => {
|
|
5305
5045
|
const output = createWriteStream(outputPath);
|
|
5306
|
-
const archive =
|
|
5046
|
+
const archive = archiver2("zip", { zlib: { level: 9 } });
|
|
5307
5047
|
output.on("close", resolve);
|
|
5308
5048
|
archive.on("error", reject);
|
|
5309
5049
|
archive.pipe(output);
|
|
@@ -5366,29 +5106,17 @@ program.command("deploy").description("Upload theme package to API server").opti
|
|
|
5366
5106
|
"-e, --environment <env>",
|
|
5367
5107
|
"Environment (production, staging, development)"
|
|
5368
5108
|
).action(deployCommand);
|
|
5369
|
-
program.command("upload").description("
|
|
5370
|
-
|
|
5371
|
-
"Environment (staging|production)",
|
|
5372
|
-
"staging"
|
|
5373
|
-
).option("--dry-run", "Show what would be uploaded without uploading").option("--skip-source", "Skip uploading source.zip").option("--source-dir <dir>", "Source directory path").action(uploadCommand);
|
|
5374
|
-
program.command("download").description("Download theme from S3 bucket").option("-t, --theme-id <id>", "Theme ID to download").option(
|
|
5109
|
+
program.command("upload").description("[deprecated] use `onexthm publish` instead").option("-t, --theme <theme>", "[deprecated] ignored").option("-b, --bucket <name>", "[deprecated] ignored").option("-v, --version <version>", "[deprecated] ignored").option("-e, --environment <env>", "[deprecated] ignored").option("--dry-run", "[deprecated] ignored").option("--skip-source", "[deprecated] ignored").option("--source-dir <dir>", "[deprecated] ignored").action(uploadCommand);
|
|
5110
|
+
program.command("download").description("Download a published theme via the website-api").option("-t, --theme-id <id>", "Theme ID to download").option(
|
|
5375
5111
|
"-v, --version <version>",
|
|
5376
5112
|
"Theme version (default: latest)",
|
|
5377
5113
|
"latest"
|
|
5378
|
-
).option("-b, --bucket <name>", "
|
|
5379
|
-
|
|
5380
|
-
"Environment (staging|production)",
|
|
5381
|
-
"staging"
|
|
5382
|
-
).option("-o, --output <dir>", "Output directory", "./active-theme").action(downloadCommand);
|
|
5383
|
-
program.command("clone").description("Clone theme source code from S3").argument("<theme-name>", "Theme to clone").option(
|
|
5114
|
+
).option("-b, --bucket <name>", "[deprecated] ignored").option("-e, --environment <env>", "[deprecated] ignored").option("-o, --output <dir>", "Output directory", "./active-theme").action(downloadCommand);
|
|
5115
|
+
program.command("clone").description("Clone theme source code via the website-api").argument("<theme-name>", "Theme to clone").option(
|
|
5384
5116
|
"-v, --version <version>",
|
|
5385
5117
|
"Theme version (default: latest)",
|
|
5386
5118
|
"latest"
|
|
5387
|
-
).option("-n, --name <name>", "New theme name (skips interactive prompt)").option("-o, --output <dir>", "Output directory").option("-b, --bucket <name>", "
|
|
5388
|
-
"-e, --environment <env>",
|
|
5389
|
-
"Environment (staging|production)",
|
|
5390
|
-
"staging"
|
|
5391
|
-
).option("--no-install", "Skip running pnpm install after clone").action(cloneCommand);
|
|
5119
|
+
).option("-n, --name <name>", "New theme name (skips interactive prompt)").option("-o, --output <dir>", "Output directory").option("-b, --bucket <name>", "[deprecated] ignored").option("-e, --environment <env>", "[deprecated] ignored").option("--no-install", "Skip running pnpm install after clone").action(cloneCommand);
|
|
5392
5120
|
program.command("config").description("Configure OneX CLI credentials (AWS, API keys)").action(configCommand);
|
|
5393
5121
|
program.command("login").description("Login to OneX platform").action(loginCommand);
|
|
5394
5122
|
program.command("logout").description("Logout from OneX platform").action(logoutCommand);
|