@onexapis/cli 1.1.43 → 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 +361 -469
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +361 -469
- 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/index.js
CHANGED
|
@@ -14,8 +14,6 @@ var inquirer = require('inquirer');
|
|
|
14
14
|
var fs = require('fs-extra');
|
|
15
15
|
var ejs = require('ejs');
|
|
16
16
|
var os = require('os');
|
|
17
|
-
var clientS3 = require('@aws-sdk/client-s3');
|
|
18
|
-
var archiver = require('archiver');
|
|
19
17
|
var AdmZip = require('adm-zip');
|
|
20
18
|
|
|
21
19
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
@@ -50,7 +48,6 @@ var inquirer__default = /*#__PURE__*/_interopDefault(inquirer);
|
|
|
50
48
|
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
51
49
|
var ejs__default = /*#__PURE__*/_interopDefault(ejs);
|
|
52
50
|
var os__default = /*#__PURE__*/_interopDefault(os);
|
|
53
|
-
var archiver__default = /*#__PURE__*/_interopDefault(archiver);
|
|
54
51
|
var AdmZip__default = /*#__PURE__*/_interopDefault(AdmZip);
|
|
55
52
|
|
|
56
53
|
var __defProp = Object.defineProperty;
|
|
@@ -1360,8 +1357,8 @@ function validateThemeName(name) {
|
|
|
1360
1357
|
return /^[a-z][a-z0-9-]*$/.test(name);
|
|
1361
1358
|
}
|
|
1362
1359
|
function pathExists(filePath) {
|
|
1363
|
-
const
|
|
1364
|
-
return
|
|
1360
|
+
const fs11 = __require("fs-extra");
|
|
1361
|
+
return fs11.existsSync(filePath);
|
|
1365
1362
|
}
|
|
1366
1363
|
function validateCategory(category) {
|
|
1367
1364
|
const validCategories = [
|
|
@@ -1543,10 +1540,110 @@ async function installDependencies(projectPath, packageManager = "npm") {
|
|
|
1543
1540
|
});
|
|
1544
1541
|
}
|
|
1545
1542
|
var AUTH_DIR = path8__default.default.join(os__default.default.homedir(), ".onexthm");
|
|
1546
|
-
path8__default.default.join(AUTH_DIR, "auth.json");
|
|
1543
|
+
var AUTH_FILE = path8__default.default.join(AUTH_DIR, "auth.json");
|
|
1547
1544
|
function getApiUrl() {
|
|
1548
1545
|
return process.env.ONEXTHM_API_URL || process.env.NEXT_PUBLIC_API_URL || "https://platform-dev.onexeos.com";
|
|
1549
1546
|
}
|
|
1547
|
+
async function saveAuthTokens(tokens) {
|
|
1548
|
+
await fs__default.default.ensureDir(AUTH_DIR);
|
|
1549
|
+
const key = getMachineKey();
|
|
1550
|
+
const data = JSON.stringify(tokens);
|
|
1551
|
+
const encrypted = encrypt(data, key);
|
|
1552
|
+
await fs__default.default.writeFile(AUTH_FILE, encrypted, "utf-8");
|
|
1553
|
+
}
|
|
1554
|
+
function loadAuthTokens() {
|
|
1555
|
+
try {
|
|
1556
|
+
if (!fs__default.default.existsSync(AUTH_FILE)) return null;
|
|
1557
|
+
const encrypted = fs__default.default.readFileSync(AUTH_FILE, "utf-8");
|
|
1558
|
+
const key = getMachineKey();
|
|
1559
|
+
const data = decrypt(encrypted, key);
|
|
1560
|
+
return JSON.parse(data);
|
|
1561
|
+
} catch {
|
|
1562
|
+
return null;
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
async function clearAuthTokens() {
|
|
1566
|
+
try {
|
|
1567
|
+
await fs__default.default.remove(AUTH_FILE);
|
|
1568
|
+
} catch {
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
function isTokenExpired(tokens) {
|
|
1572
|
+
return Date.now() / 1e3 > tokens.expiresAt - 60;
|
|
1573
|
+
}
|
|
1574
|
+
async function getValidTokens() {
|
|
1575
|
+
const tokens = loadAuthTokens();
|
|
1576
|
+
if (!tokens) return null;
|
|
1577
|
+
if (!isTokenExpired(tokens)) return tokens;
|
|
1578
|
+
try {
|
|
1579
|
+
const apiUrl = getApiUrl();
|
|
1580
|
+
const response = await fetch(`${apiUrl}/auth/refresh`, {
|
|
1581
|
+
method: "POST",
|
|
1582
|
+
headers: { "Content-Type": "application/json" },
|
|
1583
|
+
body: JSON.stringify({ refresh_token: tokens.refreshToken })
|
|
1584
|
+
});
|
|
1585
|
+
if (!response.ok) {
|
|
1586
|
+
await clearAuthTokens();
|
|
1587
|
+
return null;
|
|
1588
|
+
}
|
|
1589
|
+
const data = await response.json();
|
|
1590
|
+
const body = data.statusCode ? data.body : data;
|
|
1591
|
+
const refreshed = {
|
|
1592
|
+
...tokens,
|
|
1593
|
+
accessToken: body.AccessToken || tokens.accessToken,
|
|
1594
|
+
idToken: body.IdToken || tokens.idToken,
|
|
1595
|
+
expiresAt: Math.floor(Date.now() / 1e3) + (body.ExpiresIn || 3600)
|
|
1596
|
+
};
|
|
1597
|
+
await saveAuthTokens(refreshed);
|
|
1598
|
+
return refreshed;
|
|
1599
|
+
} catch {
|
|
1600
|
+
await clearAuthTokens();
|
|
1601
|
+
return null;
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
async function authenticatedFetch(url, init) {
|
|
1605
|
+
const tokens = await getValidTokens();
|
|
1606
|
+
if (!tokens) {
|
|
1607
|
+
throw new Error("Not logged in. Run: onexthm login");
|
|
1608
|
+
}
|
|
1609
|
+
const headers = new Headers(init?.headers);
|
|
1610
|
+
headers.set("Authorization", `Bearer ${tokens.idToken}`);
|
|
1611
|
+
headers.set("Content-Type", "application/json");
|
|
1612
|
+
return fetch(url, { ...init, headers });
|
|
1613
|
+
}
|
|
1614
|
+
function getMachineKey() {
|
|
1615
|
+
let seed;
|
|
1616
|
+
if (process.platform === "darwin") {
|
|
1617
|
+
seed = `onexthm:${os__default.default.hostname()}:${os__default.default.userInfo().username}`;
|
|
1618
|
+
} else if (process.platform === "linux") {
|
|
1619
|
+
try {
|
|
1620
|
+
seed = `onexthm:${fs__default.default.readFileSync("/etc/machine-id", "utf-8").trim()}`;
|
|
1621
|
+
} catch {
|
|
1622
|
+
seed = `onexthm:${os__default.default.hostname()}:${os__default.default.userInfo().username}`;
|
|
1623
|
+
}
|
|
1624
|
+
} else {
|
|
1625
|
+
seed = `onexthm:${os__default.default.hostname()}:${os__default.default.userInfo().username}`;
|
|
1626
|
+
}
|
|
1627
|
+
return crypto__default.default.createHash("sha256").update(seed).digest();
|
|
1628
|
+
}
|
|
1629
|
+
function encrypt(text, key) {
|
|
1630
|
+
const iv = crypto__default.default.randomBytes(16);
|
|
1631
|
+
const cipher = crypto__default.default.createCipheriv("aes-256-gcm", key, iv);
|
|
1632
|
+
let encrypted = cipher.update(text, "utf-8", "hex");
|
|
1633
|
+
encrypted += cipher.final("hex");
|
|
1634
|
+
const tag = cipher.getAuthTag();
|
|
1635
|
+
return `${iv.toString("hex")}:${tag.toString("hex")}:${encrypted}`;
|
|
1636
|
+
}
|
|
1637
|
+
function decrypt(text, key) {
|
|
1638
|
+
const [ivHex, tagHex, encrypted] = text.split(":");
|
|
1639
|
+
const iv = Buffer.from(ivHex, "hex");
|
|
1640
|
+
const tag = Buffer.from(tagHex, "hex");
|
|
1641
|
+
const decipher = crypto__default.default.createDecipheriv("aes-256-gcm", key, iv);
|
|
1642
|
+
decipher.setAuthTag(tag);
|
|
1643
|
+
let decrypted = decipher.update(encrypted, "hex", "utf-8");
|
|
1644
|
+
decrypted += decipher.final("utf-8");
|
|
1645
|
+
return decrypted;
|
|
1646
|
+
}
|
|
1550
1647
|
|
|
1551
1648
|
// src/commands/init.ts
|
|
1552
1649
|
async function initCommand(projectName, options = {}) {
|
|
@@ -2755,343 +2852,94 @@ function runCommand(command, args, cwd) {
|
|
|
2755
2852
|
|
|
2756
2853
|
// src/commands/upload.ts
|
|
2757
2854
|
init_logger();
|
|
2758
|
-
function
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
endpoint: endpointUrl,
|
|
2766
|
-
region: "us-east-1",
|
|
2767
|
-
credentials: {
|
|
2768
|
-
accessKeyId: process.env.MINIO_ACCESS_KEY || "minioadmin",
|
|
2769
|
-
secretAccessKey: process.env.MINIO_SECRET_KEY || "minioadmin"
|
|
2770
|
-
},
|
|
2771
|
-
forcePathStyle: true
|
|
2772
|
-
});
|
|
2773
|
-
}
|
|
2774
|
-
if (adapterMode === "local") {
|
|
2775
|
-
return new clientS3.S3Client({
|
|
2776
|
-
endpoint: "http://localhost:4569",
|
|
2777
|
-
region: "ap-southeast-1",
|
|
2778
|
-
credentials: {
|
|
2779
|
-
accessKeyId: "S3RVER",
|
|
2780
|
-
secretAccessKey: "S3RVER"
|
|
2781
|
-
},
|
|
2782
|
-
forcePathStyle: true
|
|
2783
|
-
});
|
|
2784
|
-
}
|
|
2785
|
-
return new clientS3.S3Client({
|
|
2786
|
-
region: process.env.AWS_REGION || "ap-southeast-1"
|
|
2787
|
-
});
|
|
2788
|
-
}
|
|
2789
|
-
function getBucketName(env) {
|
|
2790
|
-
if (process.env.BUCKET_NAME) {
|
|
2791
|
-
return process.env.BUCKET_NAME;
|
|
2792
|
-
}
|
|
2793
|
-
const environment = env || process.env.ENVIRONMENT || "staging";
|
|
2794
|
-
return environment === "production" ? "theme-s3-bucket" : "theme-s3-bucket";
|
|
2795
|
-
}
|
|
2796
|
-
async function findCompiledThemeDir(themeId, version) {
|
|
2797
|
-
const searchPaths = [path8__default.default.resolve(process.cwd(), "dist")];
|
|
2798
|
-
for (const dir of searchPaths) {
|
|
2799
|
-
if (await fs__default.default.pathExists(dir)) {
|
|
2800
|
-
const hasManifest = await fs__default.default.pathExists(path8__default.default.join(dir, "manifest.json"));
|
|
2801
|
-
const hasThemeEntry = await fs__default.default.pathExists(path8__default.default.join(dir, "bundle-entry.js")) || await fs__default.default.pathExists(path8__default.default.join(dir, "theme.config.js")) || await fs__default.default.pathExists(path8__default.default.join(dir, "index.js"));
|
|
2802
|
-
if (hasManifest || hasThemeEntry) {
|
|
2803
|
-
return dir;
|
|
2804
|
-
}
|
|
2805
|
-
}
|
|
2806
|
-
}
|
|
2807
|
-
return null;
|
|
2808
|
-
}
|
|
2809
|
-
async function readManifest() {
|
|
2810
|
-
const manifestTsPath = path8__default.default.resolve(process.cwd(), "manifest.ts");
|
|
2811
|
-
if (await fs__default.default.pathExists(manifestTsPath)) {
|
|
2812
|
-
try {
|
|
2813
|
-
const module = await import(manifestTsPath);
|
|
2814
|
-
return module.default || module;
|
|
2815
|
-
} catch (error) {
|
|
2816
|
-
exports.logger.warning("Failed to import manifest.ts, trying package.json");
|
|
2817
|
-
}
|
|
2818
|
-
}
|
|
2819
|
-
const packageJsonPath = path8__default.default.resolve(process.cwd(), "package.json");
|
|
2820
|
-
if (await fs__default.default.pathExists(packageJsonPath)) {
|
|
2821
|
-
const pkg = await fs__default.default.readJson(packageJsonPath);
|
|
2822
|
-
return {
|
|
2823
|
-
themeId: pkg.name?.replace("@onex-themes/", "") || "unknown",
|
|
2824
|
-
version: pkg.version || "1.0.0"
|
|
2825
|
-
};
|
|
2826
|
-
}
|
|
2827
|
-
throw new Error(
|
|
2828
|
-
"No manifest.ts or package.json found. Are you in a theme directory?"
|
|
2855
|
+
async function uploadCommand(_options) {
|
|
2856
|
+
exports.logger.header("Upload Theme to S3 \u2014 DEPRECATED");
|
|
2857
|
+
console.log();
|
|
2858
|
+
console.log(
|
|
2859
|
+
chalk4__default.default.yellow.bold(
|
|
2860
|
+
"`onexthm upload` is deprecated and no longer functional."
|
|
2861
|
+
)
|
|
2829
2862
|
);
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
const output = fs__default.default.createWriteStream(outputPath);
|
|
2834
|
-
const archive = archiver__default.default("zip", { zlib: { level: 6 } });
|
|
2835
|
-
output.on("close", () => resolve());
|
|
2836
|
-
archive.on("error", (err) => reject(err));
|
|
2837
|
-
archive.pipe(output);
|
|
2838
|
-
archive.glob("**/*", {
|
|
2839
|
-
cwd: sourceDir,
|
|
2840
|
-
dot: true,
|
|
2841
|
-
ignore: excludePatterns
|
|
2842
|
-
});
|
|
2843
|
-
archive.finalize();
|
|
2844
|
-
});
|
|
2845
|
-
}
|
|
2846
|
-
async function findSourceDir(themeId, explicitDir) {
|
|
2847
|
-
if (explicitDir) {
|
|
2848
|
-
if (await fs__default.default.pathExists(explicitDir)) return explicitDir;
|
|
2849
|
-
return null;
|
|
2850
|
-
}
|
|
2851
|
-
const searchPaths = [
|
|
2852
|
-
process.cwd(),
|
|
2853
|
-
path8__default.default.resolve(process.cwd(), `../../themes/${themeId}`),
|
|
2854
|
-
path8__default.default.resolve(process.cwd(), `../themes/${themeId}`)
|
|
2855
|
-
];
|
|
2856
|
-
const markers = ["theme.config.ts", "bundle-entry.ts"];
|
|
2857
|
-
for (const dir of searchPaths) {
|
|
2858
|
-
for (const marker of markers) {
|
|
2859
|
-
if (await fs__default.default.pathExists(path8__default.default.join(dir, marker))) {
|
|
2860
|
-
return dir;
|
|
2861
|
-
}
|
|
2862
|
-
}
|
|
2863
|
-
}
|
|
2864
|
-
return null;
|
|
2865
|
-
}
|
|
2866
|
-
async function updateLatestPointer(s3Client, bucket, themeId, version) {
|
|
2867
|
-
const latestData = {
|
|
2868
|
-
version,
|
|
2869
|
-
uploadedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2870
|
-
};
|
|
2871
|
-
await s3Client.send(
|
|
2872
|
-
new clientS3.PutObjectCommand({
|
|
2873
|
-
Bucket: bucket,
|
|
2874
|
-
Key: `themes/${themeId}/latest.json`,
|
|
2875
|
-
Body: JSON.stringify(latestData, null, 2),
|
|
2876
|
-
ContentType: "application/json"
|
|
2877
|
-
})
|
|
2863
|
+
console.log();
|
|
2864
|
+
console.log(
|
|
2865
|
+
"The platform no longer exposes themes via direct S3 access, so this"
|
|
2878
2866
|
);
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
if (!compiledDir) {
|
|
2899
|
-
spinner.fail(
|
|
2900
|
-
chalk4__default.default.red(
|
|
2901
|
-
`Compiled theme not found for ${themeId}@${version}. Run 'onexthm build' first.`
|
|
2902
|
-
)
|
|
2903
|
-
);
|
|
2904
|
-
exports.logger.info(chalk4__default.default.gray(`Expected location:
|
|
2905
|
-
- ./dist/`));
|
|
2906
|
-
process.exit(1);
|
|
2907
|
-
}
|
|
2908
|
-
spinner.succeed(`Found compiled theme at: ${compiledDir}`);
|
|
2909
|
-
spinner.start("Creating bundle.zip...");
|
|
2910
|
-
const tmpDir = os__default.default.tmpdir();
|
|
2911
|
-
const bundleZipPath = path8__default.default.join(tmpDir, `${themeId}-${version}-bundle.zip`);
|
|
2912
|
-
await createZipFromDir(compiledDir, bundleZipPath);
|
|
2913
|
-
const bundleZipBuffer = await fs__default.default.readFile(bundleZipPath);
|
|
2914
|
-
const bundleSizeMB = (bundleZipBuffer.length / 1024 / 1024).toFixed(2);
|
|
2915
|
-
spinner.succeed(`Created bundle.zip (${bundleSizeMB} MB)`);
|
|
2916
|
-
if (options.dryRun) {
|
|
2917
|
-
spinner.info(chalk4__default.default.yellow("Dry run mode \u2014 no files will be uploaded"));
|
|
2918
|
-
console.log();
|
|
2919
|
-
console.log(chalk4__default.default.gray(` bundle.zip: ${bundleSizeMB} MB`));
|
|
2920
|
-
console.log(
|
|
2921
|
-
chalk4__default.default.cyan(
|
|
2922
|
-
` S3 path: s3://${bucket}/themes/${themeId}/${version}/bundle.zip`
|
|
2923
|
-
)
|
|
2924
|
-
);
|
|
2925
|
-
if (!options.skipSource) {
|
|
2926
|
-
const sourceDir = await findSourceDir(themeId, options.sourceDir);
|
|
2927
|
-
if (sourceDir) {
|
|
2928
|
-
console.log(chalk4__default.default.gray(` source dir: ${sourceDir}`));
|
|
2929
|
-
console.log(
|
|
2930
|
-
chalk4__default.default.cyan(
|
|
2931
|
-
` S3 path: s3://${bucket}/themes/${themeId}/${version}/source.zip`
|
|
2932
|
-
)
|
|
2933
|
-
);
|
|
2934
|
-
} else {
|
|
2935
|
-
console.log(
|
|
2936
|
-
chalk4__default.default.yellow(" source dir: not found (source.zip will be skipped)")
|
|
2937
|
-
);
|
|
2938
|
-
}
|
|
2939
|
-
}
|
|
2940
|
-
console.log();
|
|
2941
|
-
await fs__default.default.remove(bundleZipPath);
|
|
2942
|
-
return;
|
|
2943
|
-
}
|
|
2944
|
-
spinner.start("Uploading bundle.zip to S3...");
|
|
2945
|
-
const bundleS3Key = `themes/${themeId}/${version}/bundle.zip`;
|
|
2946
|
-
await s3Client.send(
|
|
2947
|
-
new clientS3.PutObjectCommand({
|
|
2948
|
-
Bucket: bucket,
|
|
2949
|
-
Key: bundleS3Key,
|
|
2950
|
-
Body: bundleZipBuffer,
|
|
2951
|
-
ContentType: "application/zip"
|
|
2952
|
-
})
|
|
2953
|
-
);
|
|
2954
|
-
spinner.succeed(
|
|
2955
|
-
`Uploaded bundle.zip ${chalk4__default.default.gray(`\u2192 s3://${bucket}/${bundleS3Key}`)}`
|
|
2956
|
-
);
|
|
2957
|
-
await fs__default.default.remove(bundleZipPath);
|
|
2958
|
-
let sourceUploaded = false;
|
|
2959
|
-
if (!options.skipSource) {
|
|
2960
|
-
spinner.start("Looking for source directory...");
|
|
2961
|
-
const sourceDir = await findSourceDir(themeId, options.sourceDir);
|
|
2962
|
-
if (sourceDir) {
|
|
2963
|
-
spinner.succeed(`Found source at: ${sourceDir}`);
|
|
2964
|
-
spinner.start("Creating source.zip...");
|
|
2965
|
-
const sourceZipPath = path8__default.default.join(
|
|
2966
|
-
tmpDir,
|
|
2967
|
-
`${themeId}-${version}-source.zip`
|
|
2968
|
-
);
|
|
2969
|
-
await createZipFromDir(sourceDir, sourceZipPath, [
|
|
2970
|
-
"node_modules/**",
|
|
2971
|
-
"dist/**",
|
|
2972
|
-
".git/**",
|
|
2973
|
-
"*.zip",
|
|
2974
|
-
".next/**",
|
|
2975
|
-
".turbo/**"
|
|
2976
|
-
]);
|
|
2977
|
-
const sourceZipBuffer = await fs__default.default.readFile(sourceZipPath);
|
|
2978
|
-
const sourceSizeMB = (sourceZipBuffer.length / 1024 / 1024).toFixed(2);
|
|
2979
|
-
spinner.succeed(`Created source.zip (${sourceSizeMB} MB)`);
|
|
2980
|
-
spinner.start("Uploading source.zip to S3...");
|
|
2981
|
-
const sourceS3Key = `themes/${themeId}/${version}/source.zip`;
|
|
2982
|
-
await s3Client.send(
|
|
2983
|
-
new clientS3.PutObjectCommand({
|
|
2984
|
-
Bucket: bucket,
|
|
2985
|
-
Key: sourceS3Key,
|
|
2986
|
-
Body: sourceZipBuffer,
|
|
2987
|
-
ContentType: "application/zip"
|
|
2988
|
-
})
|
|
2989
|
-
);
|
|
2990
|
-
spinner.succeed(
|
|
2991
|
-
`Uploaded source.zip ${chalk4__default.default.gray(`\u2192 s3://${bucket}/${sourceS3Key}`)}`
|
|
2992
|
-
);
|
|
2993
|
-
await fs__default.default.remove(sourceZipPath);
|
|
2994
|
-
sourceUploaded = true;
|
|
2995
|
-
} else {
|
|
2996
|
-
spinner.warn(
|
|
2997
|
-
chalk4__default.default.yellow("Source directory not found \u2014 skipping source.zip")
|
|
2998
|
-
);
|
|
2999
|
-
}
|
|
3000
|
-
}
|
|
3001
|
-
spinner.start("Updating latest.json pointer...");
|
|
3002
|
-
await updateLatestPointer(s3Client, bucket, themeId, version);
|
|
3003
|
-
spinner.succeed("Updated latest.json pointer");
|
|
3004
|
-
console.log();
|
|
3005
|
-
exports.logger.success(chalk4__default.default.green.bold("Theme uploaded successfully!"));
|
|
3006
|
-
console.log();
|
|
3007
|
-
console.log(
|
|
3008
|
-
chalk4__default.default.cyan(" Theme: ") + chalk4__default.default.white(`${themeId}@${version}`)
|
|
3009
|
-
);
|
|
3010
|
-
console.log(chalk4__default.default.cyan(" Bucket: ") + chalk4__default.default.white(bucket));
|
|
3011
|
-
console.log(
|
|
3012
|
-
chalk4__default.default.cyan(" Files: ") + chalk4__default.default.white(`bundle.zip${sourceUploaded ? " + source.zip" : ""}`)
|
|
3013
|
-
);
|
|
3014
|
-
console.log(
|
|
3015
|
-
chalk4__default.default.cyan(" Path: ") + chalk4__default.default.gray(`s3://${bucket}/themes/${themeId}/${version}/`)
|
|
3016
|
-
);
|
|
3017
|
-
console.log();
|
|
3018
|
-
} catch (error) {
|
|
3019
|
-
spinner.fail(chalk4__default.default.red(`Upload failed: ${error.message}`));
|
|
3020
|
-
exports.logger.error(error.stack || error.message);
|
|
3021
|
-
process.exit(1);
|
|
3022
|
-
}
|
|
2867
|
+
console.log(
|
|
2868
|
+
"command can no longer reach the bucket. Use `onexthm publish` instead:"
|
|
2869
|
+
);
|
|
2870
|
+
console.log();
|
|
2871
|
+
console.log(chalk4__default.default.cyan(" cd themes/your-theme"));
|
|
2872
|
+
console.log(chalk4__default.default.cyan(" onexthm login # one-time, refreshes JWT"));
|
|
2873
|
+
console.log(
|
|
2874
|
+
chalk4__default.default.cyan(" onexthm publish # builds + uploads + confirms")
|
|
2875
|
+
);
|
|
2876
|
+
console.log();
|
|
2877
|
+
console.log(
|
|
2878
|
+
"`publish` does everything this command did (build, version bump,"
|
|
2879
|
+
);
|
|
2880
|
+
console.log(
|
|
2881
|
+
"bundle + source upload) plus content-hashed asset upload, security"
|
|
2882
|
+
);
|
|
2883
|
+
console.log("scanning, and atomic version registration in one step.");
|
|
2884
|
+
console.log();
|
|
2885
|
+
process.exit(1);
|
|
3023
2886
|
}
|
|
3024
2887
|
|
|
3025
2888
|
// src/commands/download.ts
|
|
3026
2889
|
init_logger();
|
|
3027
|
-
function
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
const endpoint = process.env.MINIO_ENDPOINT || "localhost:9000";
|
|
3031
|
-
const secure = process.env.MINIO_SECURE === "true";
|
|
3032
|
-
const endpointUrl = endpoint.startsWith("http") ? endpoint : `${secure ? "https" : "http"}://${endpoint}`;
|
|
3033
|
-
return new clientS3.S3Client({
|
|
3034
|
-
endpoint: endpointUrl,
|
|
3035
|
-
region: "us-east-1",
|
|
3036
|
-
credentials: {
|
|
3037
|
-
accessKeyId: process.env.MINIO_ACCESS_KEY || "minioadmin",
|
|
3038
|
-
secretAccessKey: process.env.MINIO_SECRET_KEY || "minioadmin"
|
|
3039
|
-
},
|
|
3040
|
-
forcePathStyle: true
|
|
3041
|
-
});
|
|
3042
|
-
}
|
|
3043
|
-
if (adapterMode === "local") {
|
|
3044
|
-
return new clientS3.S3Client({
|
|
3045
|
-
endpoint: "http://localhost:4569",
|
|
3046
|
-
region: "ap-southeast-1",
|
|
3047
|
-
credentials: {
|
|
3048
|
-
accessKeyId: "S3RVER",
|
|
3049
|
-
secretAccessKey: "S3RVER"
|
|
3050
|
-
},
|
|
3051
|
-
forcePathStyle: true
|
|
3052
|
-
});
|
|
2890
|
+
function unwrapEnvelope(raw) {
|
|
2891
|
+
if (raw && typeof raw === "object" && "statusCode" in raw && "body" in raw) {
|
|
2892
|
+
return raw.body;
|
|
3053
2893
|
}
|
|
3054
|
-
return
|
|
3055
|
-
region: process.env.AWS_REGION || "ap-southeast-1"
|
|
3056
|
-
});
|
|
2894
|
+
return raw;
|
|
3057
2895
|
}
|
|
3058
|
-
function
|
|
3059
|
-
|
|
3060
|
-
|
|
2896
|
+
async function resolveLatestVersion(apiUrl, themeId) {
|
|
2897
|
+
const url = `${apiUrl}/website-api/themes/${encodeURIComponent(themeId)}/versions`;
|
|
2898
|
+
let response;
|
|
2899
|
+
try {
|
|
2900
|
+
response = await fetch(url, { cache: "no-store" });
|
|
2901
|
+
} catch (err) {
|
|
2902
|
+
throw new Error(
|
|
2903
|
+
`Network error contacting ${url}: ${err instanceof Error ? err.message : "unknown"}`
|
|
2904
|
+
);
|
|
3061
2905
|
}
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
}
|
|
3065
|
-
|
|
3066
|
-
const chunks = [];
|
|
3067
|
-
for await (const chunk of stream) {
|
|
3068
|
-
chunks.push(Buffer.from(chunk));
|
|
2906
|
+
if (!response.ok) {
|
|
2907
|
+
throw new Error(
|
|
2908
|
+
`Version lookup failed for "${themeId}" (HTTP ${response.status})`
|
|
2909
|
+
);
|
|
3069
2910
|
}
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
2911
|
+
const raw = await response.json();
|
|
2912
|
+
const data = unwrapEnvelope(raw);
|
|
2913
|
+
const latest = data?.latest_version;
|
|
2914
|
+
if (typeof latest !== "string" || latest.length === 0) {
|
|
2915
|
+
throw new Error(
|
|
2916
|
+
`Theme "${themeId}" has no published versions yet (no latest_version in response)`
|
|
2917
|
+
);
|
|
3076
2918
|
}
|
|
3077
|
-
return
|
|
2919
|
+
return latest;
|
|
3078
2920
|
}
|
|
3079
|
-
async function
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
Bucket: bucket,
|
|
3084
|
-
Key: `themes/${themeId}/latest.json`
|
|
3085
|
-
})
|
|
3086
|
-
);
|
|
3087
|
-
const body = await streamToString(response.Body);
|
|
3088
|
-
const data = JSON.parse(body);
|
|
3089
|
-
return data.version;
|
|
3090
|
-
} catch (error) {
|
|
2921
|
+
async function downloadBundleZip(apiUrl, themeId, version) {
|
|
2922
|
+
const url = `${apiUrl}/website-api/themes/${encodeURIComponent(themeId)}/${encodeURIComponent(version)}/download`;
|
|
2923
|
+
const response = await fetch(url);
|
|
2924
|
+
if (!response.ok) {
|
|
3091
2925
|
throw new Error(
|
|
3092
|
-
`
|
|
2926
|
+
`Bundle download failed for "${themeId}@${version}" (HTTP ${response.status})`
|
|
3093
2927
|
);
|
|
3094
2928
|
}
|
|
2929
|
+
const contentType = response.headers.get("content-type") || "";
|
|
2930
|
+
if (contentType.includes("application/json")) {
|
|
2931
|
+
const raw = await response.json();
|
|
2932
|
+
const envelope = raw && typeof raw === "object" && "statusCode" in raw ? raw : { body: raw };
|
|
2933
|
+
const body = envelope.body;
|
|
2934
|
+
if (typeof body !== "string") {
|
|
2935
|
+
throw new Error(
|
|
2936
|
+
"Unexpected /download response shape: expected base64 string in body"
|
|
2937
|
+
);
|
|
2938
|
+
}
|
|
2939
|
+
return Buffer.from(body, "base64");
|
|
2940
|
+
}
|
|
2941
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
2942
|
+
return Buffer.from(arrayBuffer);
|
|
3095
2943
|
}
|
|
3096
2944
|
async function createCompatibilityFiles(outputDir, manifest) {
|
|
3097
2945
|
const entryFile = manifest.output?.entry || "bundle-entry.js";
|
|
@@ -3115,47 +2963,58 @@ export * from './bundle-entry.js';
|
|
|
3115
2963
|
const pkgJsonPath = path8__default.default.join(outputDir, "package.json");
|
|
3116
2964
|
await fs__default.default.writeFile(pkgJsonPath, '{\n "type": "module"\n}\n', "utf-8");
|
|
3117
2965
|
}
|
|
3118
|
-
function showDownloadFailureHelp(themeId,
|
|
2966
|
+
function showDownloadFailureHelp(themeId, apiUrl) {
|
|
3119
2967
|
console.log();
|
|
3120
2968
|
exports.logger.error(chalk4__default.default.red.bold("Theme download failed"));
|
|
3121
2969
|
console.log();
|
|
3122
2970
|
console.log(chalk4__default.default.yellow("Possible reasons:"));
|
|
3123
|
-
console.log(
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
console.log(
|
|
2971
|
+
console.log(
|
|
2972
|
+
chalk4__default.default.gray(" 1. Theme has not been published yet (run `onexthm publish`)")
|
|
2973
|
+
);
|
|
2974
|
+
console.log(
|
|
2975
|
+
chalk4__default.default.gray(
|
|
2976
|
+
" 2. Theme ID is wrong (typo in --theme-id or THEME_ID env var)"
|
|
2977
|
+
)
|
|
2978
|
+
);
|
|
2979
|
+
console.log(
|
|
2980
|
+
chalk4__default.default.gray(" 3. API base URL is wrong or the website-api is unreachable")
|
|
2981
|
+
);
|
|
3127
2982
|
console.log();
|
|
3128
2983
|
console.log(chalk4__default.default.cyan.bold("To fix this:"));
|
|
3129
2984
|
console.log();
|
|
3130
|
-
console.log(chalk4__default.default.white("1.
|
|
3131
|
-
console.log(chalk4__default.default.gray(` cd themes/${themeId}`));
|
|
3132
|
-
console.log(chalk4__default.default.gray(" pnpm build"));
|
|
3133
|
-
console.log(chalk4__default.default.gray(" onexthm upload"));
|
|
3134
|
-
console.log();
|
|
3135
|
-
console.log(chalk4__default.default.white("2. Verify AWS credentials are set:"));
|
|
2985
|
+
console.log(chalk4__default.default.white("1. Verify the theme is published:"));
|
|
3136
2986
|
console.log(
|
|
3137
|
-
chalk4__default.default.gray(
|
|
2987
|
+
chalk4__default.default.gray(
|
|
2988
|
+
` curl -s ${apiUrl}/website-api/themes/${themeId}/versions | jq .latest_version`
|
|
2989
|
+
)
|
|
3138
2990
|
);
|
|
3139
|
-
console.log(chalk4__default.default.gray(" - Or use AWS_PROFILE=your-profile"));
|
|
3140
|
-
console.log(chalk4__default.default.gray(" - Set AWS_REGION (e.g., ap-southeast-1)"));
|
|
3141
2991
|
console.log();
|
|
3142
|
-
console.log(chalk4__default.default.white("
|
|
3143
|
-
console.log(chalk4__default.default.gray(` Current
|
|
2992
|
+
console.log(chalk4__default.default.white("2. Check API URL configuration:"));
|
|
2993
|
+
console.log(chalk4__default.default.gray(` Current API URL: ${apiUrl}`));
|
|
3144
2994
|
console.log(
|
|
3145
|
-
chalk4__default.default.gray("
|
|
2995
|
+
chalk4__default.default.gray(" Override with NEXT_PUBLIC_API_URL or ONEXTHM_API_URL")
|
|
3146
2996
|
);
|
|
3147
2997
|
console.log();
|
|
3148
|
-
console.log(chalk4__default.default.white("
|
|
3149
|
-
console.log(
|
|
2998
|
+
console.log(chalk4__default.default.white("3. Pin a specific version (CI/production):"));
|
|
2999
|
+
console.log(
|
|
3000
|
+
chalk4__default.default.gray(` THEME_VERSION=1.2.3 onexthm download --theme-id ${themeId}`)
|
|
3001
|
+
);
|
|
3150
3002
|
console.log();
|
|
3151
3003
|
}
|
|
3152
3004
|
async function downloadCommand(options) {
|
|
3153
|
-
exports.logger.header("Download Theme
|
|
3005
|
+
exports.logger.header("Download Theme");
|
|
3154
3006
|
const spinner = ora__default.default("Initializing download...").start();
|
|
3007
|
+
if (options.bucket || options.environment) {
|
|
3008
|
+
spinner.stop();
|
|
3009
|
+
exports.logger.warning(
|
|
3010
|
+
"--bucket and --environment are deprecated and ignored. Themes are now served via HTTP from the website-api Lambda."
|
|
3011
|
+
);
|
|
3012
|
+
spinner.start();
|
|
3013
|
+
}
|
|
3014
|
+
const apiUrl = getApiUrl();
|
|
3155
3015
|
try {
|
|
3156
3016
|
const themeId = options.themeId || process.env.NEXT_PUBLIC_THEME_ID || process.env.THEME_ID;
|
|
3157
|
-
const
|
|
3158
|
-
const bucket = options.bucket || getBucketName2(options.environment);
|
|
3017
|
+
const requestedVersion = options.version || process.env.THEME_VERSION || "latest";
|
|
3159
3018
|
const outputDir = options.output || "./active-theme";
|
|
3160
3019
|
if (!themeId) {
|
|
3161
3020
|
spinner.fail(
|
|
@@ -3165,12 +3024,10 @@ async function downloadCommand(options) {
|
|
|
3165
3024
|
);
|
|
3166
3025
|
process.exit(1);
|
|
3167
3026
|
}
|
|
3168
|
-
spinner.text = `
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
spinner.text = "Resolving latest version...";
|
|
3173
|
-
resolvedVersion = await resolveLatestVersion(s3Client, bucket, themeId);
|
|
3027
|
+
spinner.text = `Resolving ${themeId}@${requestedVersion}...`;
|
|
3028
|
+
let resolvedVersion = requestedVersion;
|
|
3029
|
+
if (requestedVersion === "latest") {
|
|
3030
|
+
resolvedVersion = await resolveLatestVersion(apiUrl, themeId);
|
|
3174
3031
|
spinner.succeed(
|
|
3175
3032
|
`Resolved latest version: ${chalk4__default.default.cyan(resolvedVersion)}`
|
|
3176
3033
|
);
|
|
@@ -3180,24 +3037,19 @@ async function downloadCommand(options) {
|
|
|
3180
3037
|
chalk4__default.default.yellow(
|
|
3181
3038
|
`
|
|
3182
3039
|
Warning: Resolved "latest" to ${resolvedVersion} in CI environment.
|
|
3183
|
-
For
|
|
3040
|
+
For reproducible builds, pin to a specific version:
|
|
3184
3041
|
THEME_VERSION=${resolvedVersion}
|
|
3185
3042
|
`
|
|
3186
3043
|
)
|
|
3187
3044
|
);
|
|
3188
3045
|
}
|
|
3046
|
+
} else {
|
|
3047
|
+
spinner.succeed(`Using version: ${chalk4__default.default.cyan(resolvedVersion)}`);
|
|
3189
3048
|
}
|
|
3190
3049
|
spinner.start(
|
|
3191
3050
|
`Downloading bundle.zip for ${themeId}@${resolvedVersion}...`
|
|
3192
3051
|
);
|
|
3193
|
-
const
|
|
3194
|
-
const response = await s3Client.send(
|
|
3195
|
-
new clientS3.GetObjectCommand({
|
|
3196
|
-
Bucket: bucket,
|
|
3197
|
-
Key: s3Key
|
|
3198
|
-
})
|
|
3199
|
-
);
|
|
3200
|
-
const zipBuffer = await streamToBuffer(response.Body);
|
|
3052
|
+
const zipBuffer = await downloadBundleZip(apiUrl, themeId, resolvedVersion);
|
|
3201
3053
|
const sizeMB = (zipBuffer.length / 1024 / 1024).toFixed(2);
|
|
3202
3054
|
spinner.succeed(`Downloaded bundle.zip (${sizeMB} MB)`);
|
|
3203
3055
|
spinner.start("Extracting bundle...");
|
|
@@ -3216,7 +3068,7 @@ async function downloadCommand(options) {
|
|
|
3216
3068
|
console.log(
|
|
3217
3069
|
chalk4__default.default.cyan(" Theme: ") + chalk4__default.default.white(`${themeId}@${resolvedVersion}`)
|
|
3218
3070
|
);
|
|
3219
|
-
console.log(chalk4__default.default.cyan("
|
|
3071
|
+
console.log(chalk4__default.default.cyan(" Source: ") + chalk4__default.default.white(apiUrl));
|
|
3220
3072
|
console.log(chalk4__default.default.cyan(" Output: ") + chalk4__default.default.white(outputDir));
|
|
3221
3073
|
console.log(chalk4__default.default.cyan(" Files: ") + chalk4__default.default.white(entries.length));
|
|
3222
3074
|
if (manifest.counts) {
|
|
@@ -3228,82 +3080,70 @@ async function downloadCommand(options) {
|
|
|
3228
3080
|
} catch (error) {
|
|
3229
3081
|
spinner.fail(chalk4__default.default.red("Download failed"));
|
|
3230
3082
|
exports.logger.error(error.message);
|
|
3231
|
-
const themeId = options.themeId || process.env.NEXT_PUBLIC_THEME_ID || "unknown";
|
|
3232
|
-
|
|
3233
|
-
showDownloadFailureHelp(themeId, bucket);
|
|
3083
|
+
const themeId = options.themeId || process.env.NEXT_PUBLIC_THEME_ID || process.env.THEME_ID || "unknown";
|
|
3084
|
+
showDownloadFailureHelp(themeId, apiUrl);
|
|
3234
3085
|
process.exit(1);
|
|
3235
3086
|
}
|
|
3236
3087
|
}
|
|
3237
3088
|
|
|
3238
3089
|
// src/commands/clone.ts
|
|
3239
3090
|
init_logger();
|
|
3240
|
-
function
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
const endpoint = process.env.MINIO_ENDPOINT || "localhost:9000";
|
|
3244
|
-
const secure = process.env.MINIO_SECURE === "true";
|
|
3245
|
-
const endpointUrl = endpoint.startsWith("http") ? endpoint : `${secure ? "https" : "http"}://${endpoint}`;
|
|
3246
|
-
return new clientS3.S3Client({
|
|
3247
|
-
endpoint: endpointUrl,
|
|
3248
|
-
region: "us-east-1",
|
|
3249
|
-
credentials: {
|
|
3250
|
-
accessKeyId: process.env.MINIO_ACCESS_KEY || "minioadmin",
|
|
3251
|
-
secretAccessKey: process.env.MINIO_SECRET_KEY || "minioadmin"
|
|
3252
|
-
},
|
|
3253
|
-
forcePathStyle: true
|
|
3254
|
-
});
|
|
3255
|
-
}
|
|
3256
|
-
if (adapterMode === "local") {
|
|
3257
|
-
return new clientS3.S3Client({
|
|
3258
|
-
endpoint: "http://localhost:4569",
|
|
3259
|
-
region: "ap-southeast-1",
|
|
3260
|
-
credentials: {
|
|
3261
|
-
accessKeyId: "S3RVER",
|
|
3262
|
-
secretAccessKey: "S3RVER"
|
|
3263
|
-
},
|
|
3264
|
-
forcePathStyle: true
|
|
3265
|
-
});
|
|
3266
|
-
}
|
|
3267
|
-
return new clientS3.S3Client({
|
|
3268
|
-
region: process.env.AWS_REGION || "ap-southeast-1"
|
|
3269
|
-
});
|
|
3270
|
-
}
|
|
3271
|
-
function getBucketName3(env) {
|
|
3272
|
-
if (process.env.BUCKET_NAME) {
|
|
3273
|
-
return process.env.BUCKET_NAME;
|
|
3091
|
+
function unwrapEnvelope2(raw) {
|
|
3092
|
+
if (raw && typeof raw === "object" && "statusCode" in raw && "body" in raw) {
|
|
3093
|
+
return raw.body;
|
|
3274
3094
|
}
|
|
3275
|
-
|
|
3276
|
-
return environment === "production" ? "theme-s3-bucket" : "theme-s3-bucket";
|
|
3095
|
+
return raw;
|
|
3277
3096
|
}
|
|
3278
|
-
async function
|
|
3279
|
-
const
|
|
3280
|
-
|
|
3281
|
-
|
|
3097
|
+
async function resolveLatestVersion2(apiUrl, themeId) {
|
|
3098
|
+
const url = `${apiUrl}/website-api/themes/${encodeURIComponent(themeId)}/versions`;
|
|
3099
|
+
const response = await fetch(url, { cache: "no-store" });
|
|
3100
|
+
if (!response.ok) {
|
|
3101
|
+
throw new Error(
|
|
3102
|
+
`Version lookup failed for "${themeId}" (HTTP ${response.status})`
|
|
3103
|
+
);
|
|
3282
3104
|
}
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
chunks.push(Buffer.from(chunk));
|
|
3105
|
+
const raw = await response.json();
|
|
3106
|
+
const data = unwrapEnvelope2(raw);
|
|
3107
|
+
const latest = data?.latest_version;
|
|
3108
|
+
if (typeof latest !== "string" || latest.length === 0) {
|
|
3109
|
+
throw new Error(`Theme "${themeId}" has no published versions yet`);
|
|
3289
3110
|
}
|
|
3290
|
-
return
|
|
3111
|
+
return latest;
|
|
3291
3112
|
}
|
|
3292
|
-
async function
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3113
|
+
async function fetchSourceZip(apiUrl, themeId, version) {
|
|
3114
|
+
const url = `${apiUrl}/website-api/themes/${encodeURIComponent(themeId)}/source?version=${encodeURIComponent(version)}`;
|
|
3115
|
+
const response = await authenticatedFetch(url, {
|
|
3116
|
+
method: "GET"
|
|
3117
|
+
});
|
|
3118
|
+
if (!response.ok) {
|
|
3119
|
+
if (response.status === 404) {
|
|
3120
|
+
throw new Error(
|
|
3121
|
+
`Source not found for ${themeId}@${version}. The theme may not have been published with source upload enabled.`
|
|
3122
|
+
);
|
|
3123
|
+
}
|
|
3124
|
+
if (response.status === 401 || response.status === 403) {
|
|
3125
|
+
throw new Error(
|
|
3126
|
+
`Not authorized to download source for "${themeId}". Run \`onexthm login\` first.`
|
|
3127
|
+
);
|
|
3128
|
+
}
|
|
3129
|
+
throw new Error(
|
|
3130
|
+
`Source URL request failed for "${themeId}@${version}" (HTTP ${response.status})`
|
|
3299
3131
|
);
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3132
|
+
}
|
|
3133
|
+
const raw = await response.json();
|
|
3134
|
+
const data = unwrapEnvelope2(raw);
|
|
3135
|
+
const presignedUrl = data?.download_url;
|
|
3136
|
+
if (typeof presignedUrl !== "string" || presignedUrl.length === 0) {
|
|
3137
|
+
throw new Error("Unexpected /source response shape: missing download_url");
|
|
3138
|
+
}
|
|
3139
|
+
const zipResponse = await fetch(presignedUrl);
|
|
3140
|
+
if (!zipResponse.ok) {
|
|
3303
3141
|
throw new Error(
|
|
3304
|
-
`
|
|
3142
|
+
`Presigned source download failed (HTTP ${zipResponse.status})`
|
|
3305
3143
|
);
|
|
3306
3144
|
}
|
|
3145
|
+
const arrayBuffer = await zipResponse.arrayBuffer();
|
|
3146
|
+
return Buffer.from(arrayBuffer);
|
|
3307
3147
|
}
|
|
3308
3148
|
function runInstall(cwd) {
|
|
3309
3149
|
return new Promise((resolve) => {
|
|
@@ -3402,15 +3242,24 @@ async function renameTheme(themeDir, oldName, newName) {
|
|
|
3402
3242
|
}
|
|
3403
3243
|
async function cloneCommand(themeName, options) {
|
|
3404
3244
|
exports.logger.header("Clone Theme Source");
|
|
3245
|
+
if (options.bucket || options.environment) {
|
|
3246
|
+
exports.logger.warning(
|
|
3247
|
+
"--bucket and --environment are deprecated and ignored. Source is now fetched via HTTP from the website-api Lambda."
|
|
3248
|
+
);
|
|
3249
|
+
}
|
|
3250
|
+
const tokens = await getValidTokens();
|
|
3251
|
+
if (!tokens) {
|
|
3252
|
+
exports.logger.error("Not logged in. Run: onexthm login");
|
|
3253
|
+
process.exit(1);
|
|
3254
|
+
}
|
|
3405
3255
|
let newName = options.name;
|
|
3406
3256
|
if (!newName) {
|
|
3407
3257
|
newName = await promptThemeName(themeName);
|
|
3408
3258
|
}
|
|
3409
3259
|
const spinner = ora__default.default("Initializing clone...").start();
|
|
3410
3260
|
try {
|
|
3411
|
-
const
|
|
3261
|
+
const apiUrl = getApiUrl();
|
|
3412
3262
|
const outputDir = options.output || path8__default.default.resolve(process.cwd(), newName);
|
|
3413
|
-
const s3Client = getS3Client3();
|
|
3414
3263
|
if (await fs__default.default.pathExists(outputDir)) {
|
|
3415
3264
|
spinner.fail(chalk4__default.default.red(`Directory already exists: ${outputDir}`));
|
|
3416
3265
|
exports.logger.info(
|
|
@@ -3423,28 +3272,20 @@ async function cloneCommand(themeName, options) {
|
|
|
3423
3272
|
let version = options.version || "latest";
|
|
3424
3273
|
if (version === "latest") {
|
|
3425
3274
|
spinner.text = "Resolving latest version...";
|
|
3426
|
-
version = await resolveLatestVersion2(
|
|
3275
|
+
version = await resolveLatestVersion2(apiUrl, themeName);
|
|
3427
3276
|
spinner.succeed(`Resolved latest version: ${chalk4__default.default.cyan(version)}`);
|
|
3428
3277
|
}
|
|
3429
3278
|
spinner.start(`Downloading source.zip for ${themeName}@${version}...`);
|
|
3430
|
-
const s3Key = `themes/${themeName}/${version}/source.zip`;
|
|
3431
3279
|
let zipBuffer;
|
|
3432
3280
|
try {
|
|
3433
|
-
|
|
3434
|
-
new clientS3.GetObjectCommand({
|
|
3435
|
-
Bucket: bucket,
|
|
3436
|
-
Key: s3Key
|
|
3437
|
-
})
|
|
3438
|
-
);
|
|
3439
|
-
zipBuffer = await streamToBuffer2(response.Body);
|
|
3281
|
+
zipBuffer = await fetchSourceZip(apiUrl, themeName, version);
|
|
3440
3282
|
} catch (error) {
|
|
3441
|
-
spinner.fail(chalk4__default.default.red(
|
|
3283
|
+
spinner.fail(chalk4__default.default.red(error.message));
|
|
3442
3284
|
console.log();
|
|
3443
3285
|
console.log(
|
|
3444
|
-
chalk4__default.default.
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
chalk4__default.default.gray(`Upload source with: onexthm upload --theme ${themeName}`)
|
|
3286
|
+
chalk4__default.default.gray(
|
|
3287
|
+
`Verify the theme is published: curl -s ${apiUrl}/website-api/themes/${themeName}/versions`
|
|
3288
|
+
)
|
|
3448
3289
|
);
|
|
3449
3290
|
console.log();
|
|
3450
3291
|
process.exit(1);
|