@onexapis/cli 1.1.64 → 1.1.65
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 +267 -105
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +267 -105
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +10 -17
- package/dist/index.d.ts +10 -17
- package/dist/index.js +67 -39
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +67 -39
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/templates/default/.env.example +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1550,21 +1550,43 @@ async function installDependencies(projectPath, packageManager = "npm") {
|
|
|
1550
1550
|
});
|
|
1551
1551
|
}
|
|
1552
1552
|
var AUTH_DIR = path8.join(os.homedir(), ".onexthm");
|
|
1553
|
-
var
|
|
1554
|
-
|
|
1555
|
-
|
|
1553
|
+
var ENV_URLS = {
|
|
1554
|
+
dev: "https://platform-dev.onexeos.com",
|
|
1555
|
+
prod: "https://platform-staging.onexeos.com"
|
|
1556
|
+
};
|
|
1557
|
+
function getAuthFile(env = "dev") {
|
|
1558
|
+
const newFile = path8.join(AUTH_DIR, `auth-${env}.json`);
|
|
1559
|
+
if (env === "dev") {
|
|
1560
|
+
const legacyFile = path8.join(AUTH_DIR, "auth.json");
|
|
1561
|
+
if (fs.existsSync(legacyFile) && !fs.existsSync(newFile)) {
|
|
1562
|
+
try {
|
|
1563
|
+
fs.moveSync(legacyFile, newFile);
|
|
1564
|
+
} catch {
|
|
1565
|
+
try {
|
|
1566
|
+
fs.copySync(legacyFile, newFile);
|
|
1567
|
+
fs.removeSync(legacyFile);
|
|
1568
|
+
} catch {
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
return newFile;
|
|
1556
1574
|
}
|
|
1557
|
-
|
|
1575
|
+
function getApiUrl(env = "dev") {
|
|
1576
|
+
return process.env.ONEXTHM_API_URL || ENV_URLS[env];
|
|
1577
|
+
}
|
|
1578
|
+
async function saveAuthTokens(tokens, env = "dev") {
|
|
1558
1579
|
await fs.ensureDir(AUTH_DIR);
|
|
1559
1580
|
const key = getMachineKey();
|
|
1560
1581
|
const data = JSON.stringify(tokens);
|
|
1561
1582
|
const encrypted = encrypt(data, key);
|
|
1562
|
-
await fs.writeFile(
|
|
1583
|
+
await fs.writeFile(getAuthFile(env), encrypted, "utf-8");
|
|
1563
1584
|
}
|
|
1564
|
-
function loadAuthTokens() {
|
|
1585
|
+
function loadAuthTokens(env = "dev") {
|
|
1565
1586
|
try {
|
|
1566
|
-
|
|
1567
|
-
|
|
1587
|
+
const file = getAuthFile(env);
|
|
1588
|
+
if (!fs.existsSync(file)) return null;
|
|
1589
|
+
const encrypted = fs.readFileSync(file, "utf-8");
|
|
1568
1590
|
const key = getMachineKey();
|
|
1569
1591
|
const data = decrypt(encrypted, key);
|
|
1570
1592
|
return JSON.parse(data);
|
|
@@ -1572,34 +1594,34 @@ function loadAuthTokens() {
|
|
|
1572
1594
|
return null;
|
|
1573
1595
|
}
|
|
1574
1596
|
}
|
|
1575
|
-
async function clearAuthTokens() {
|
|
1597
|
+
async function clearAuthTokens(env = "dev") {
|
|
1576
1598
|
try {
|
|
1577
|
-
await fs.remove(
|
|
1599
|
+
await fs.remove(getAuthFile(env));
|
|
1578
1600
|
} catch {
|
|
1579
1601
|
}
|
|
1580
1602
|
}
|
|
1581
1603
|
function isTokenExpired(tokens) {
|
|
1582
1604
|
return Date.now() / 1e3 > tokens.expiresAt - 300;
|
|
1583
1605
|
}
|
|
1584
|
-
async function getValidTokens() {
|
|
1585
|
-
const tokens = loadAuthTokens();
|
|
1606
|
+
async function getValidTokens(env = "dev") {
|
|
1607
|
+
const tokens = loadAuthTokens(env);
|
|
1586
1608
|
if (!tokens) return null;
|
|
1587
1609
|
if (!isTokenExpired(tokens)) return tokens;
|
|
1588
1610
|
try {
|
|
1589
|
-
const apiUrl = getApiUrl();
|
|
1611
|
+
const apiUrl = getApiUrl(env);
|
|
1590
1612
|
const response = await fetch(`${apiUrl}/auth/refresh`, {
|
|
1591
1613
|
method: "POST",
|
|
1592
1614
|
headers: { "Content-Type": "application/json" },
|
|
1593
1615
|
body: JSON.stringify({ refresh_token: tokens.refreshToken })
|
|
1594
1616
|
});
|
|
1595
1617
|
if (!response.ok) {
|
|
1596
|
-
await clearAuthTokens();
|
|
1618
|
+
await clearAuthTokens(env);
|
|
1597
1619
|
return null;
|
|
1598
1620
|
}
|
|
1599
1621
|
const data = await response.json();
|
|
1600
1622
|
const body = data.statusCode ? data.body : data;
|
|
1601
1623
|
if (!body.IdToken) {
|
|
1602
|
-
await clearAuthTokens();
|
|
1624
|
+
await clearAuthTokens(env);
|
|
1603
1625
|
return null;
|
|
1604
1626
|
}
|
|
1605
1627
|
const refreshed = {
|
|
@@ -1608,17 +1630,19 @@ async function getValidTokens() {
|
|
|
1608
1630
|
idToken: body.IdToken,
|
|
1609
1631
|
expiresAt: Math.floor(Date.now() / 1e3) + (body.ExpiresIn || 3600)
|
|
1610
1632
|
};
|
|
1611
|
-
await saveAuthTokens(refreshed);
|
|
1633
|
+
await saveAuthTokens(refreshed, env);
|
|
1612
1634
|
return refreshed;
|
|
1613
1635
|
} catch {
|
|
1614
|
-
await clearAuthTokens();
|
|
1636
|
+
await clearAuthTokens(env);
|
|
1615
1637
|
return null;
|
|
1616
1638
|
}
|
|
1617
1639
|
}
|
|
1618
|
-
async function authenticatedFetch(url, init) {
|
|
1619
|
-
const tokens = await getValidTokens();
|
|
1640
|
+
async function authenticatedFetch(url, init, env = "dev") {
|
|
1641
|
+
const tokens = await getValidTokens(env);
|
|
1620
1642
|
if (!tokens) {
|
|
1621
|
-
throw new Error(
|
|
1643
|
+
throw new Error(
|
|
1644
|
+
`Not logged in to ${env} environment. Run: onexthm login --env ${env}`
|
|
1645
|
+
);
|
|
1622
1646
|
}
|
|
1623
1647
|
const headers = new Headers(init?.headers);
|
|
1624
1648
|
headers.set("Authorization", `Bearer ${tokens.idToken}`);
|
|
@@ -1693,7 +1717,7 @@ async function initCommand(projectName, options = {}) {
|
|
|
1693
1717
|
}
|
|
1694
1718
|
if (!options.yes) {
|
|
1695
1719
|
try {
|
|
1696
|
-
const apiUrl = getApiUrl();
|
|
1720
|
+
const apiUrl = getApiUrl(options.env ?? "dev");
|
|
1697
1721
|
const controller = new AbortController();
|
|
1698
1722
|
const timeout = setTimeout(() => controller.abort(), 3e3);
|
|
1699
1723
|
const response = await fetch(
|
|
@@ -3005,9 +3029,7 @@ function showDownloadFailureHelp(themeId, apiUrl) {
|
|
|
3005
3029
|
console.log();
|
|
3006
3030
|
console.log(chalk4.white("2. Check API URL configuration:"));
|
|
3007
3031
|
console.log(chalk4.gray(` Current API URL: ${apiUrl}`));
|
|
3008
|
-
console.log(
|
|
3009
|
-
chalk4.gray(" Override with NEXT_PUBLIC_API_URL or ONEXTHM_API_URL")
|
|
3010
|
-
);
|
|
3032
|
+
console.log(chalk4.gray(" Override with ONEXTHM_API_URL env var if needed"));
|
|
3011
3033
|
console.log();
|
|
3012
3034
|
console.log(chalk4.white("3. Pin a specific version (CI/production):"));
|
|
3013
3035
|
console.log(
|
|
@@ -3017,15 +3039,17 @@ function showDownloadFailureHelp(themeId, apiUrl) {
|
|
|
3017
3039
|
}
|
|
3018
3040
|
async function downloadCommand(options) {
|
|
3019
3041
|
logger.header("Download Theme");
|
|
3042
|
+
const env = options.env ?? "dev";
|
|
3043
|
+
const apiUrl = getApiUrl(env);
|
|
3044
|
+
logger.info(`Environment: ${env} (${apiUrl})`);
|
|
3020
3045
|
const spinner = ora("Initializing download...").start();
|
|
3021
|
-
if (options.bucket
|
|
3046
|
+
if (options.bucket) {
|
|
3022
3047
|
spinner.stop();
|
|
3023
3048
|
logger.warning(
|
|
3024
|
-
"--bucket
|
|
3049
|
+
"--bucket is deprecated and ignored. Themes are now served via HTTP from the website-api Lambda."
|
|
3025
3050
|
);
|
|
3026
3051
|
spinner.start();
|
|
3027
3052
|
}
|
|
3028
|
-
const apiUrl = getApiUrl();
|
|
3029
3053
|
try {
|
|
3030
3054
|
const themeId = options.themeId || process.env.NEXT_PUBLIC_THEME_ID || process.env.THEME_ID;
|
|
3031
3055
|
const requestedVersion = options.version || process.env.THEME_VERSION || "latest";
|
|
@@ -3082,6 +3106,7 @@ async function downloadCommand(options) {
|
|
|
3082
3106
|
console.log(
|
|
3083
3107
|
chalk4.cyan(" Theme: ") + chalk4.white(`${themeId}@${resolvedVersion}`)
|
|
3084
3108
|
);
|
|
3109
|
+
console.log(chalk4.cyan(" Env: ") + chalk4.white(env));
|
|
3085
3110
|
console.log(chalk4.cyan(" Source: ") + chalk4.white(apiUrl));
|
|
3086
3111
|
console.log(chalk4.cyan(" Output: ") + chalk4.white(outputDir));
|
|
3087
3112
|
console.log(chalk4.cyan(" Files: ") + chalk4.white(entries.length));
|
|
@@ -3124,11 +3149,9 @@ async function resolveLatestVersion2(apiUrl, themeId) {
|
|
|
3124
3149
|
}
|
|
3125
3150
|
return latest;
|
|
3126
3151
|
}
|
|
3127
|
-
async function fetchSourceZip(apiUrl, themeId, version) {
|
|
3152
|
+
async function fetchSourceZip(apiUrl, themeId, version, env) {
|
|
3128
3153
|
const url = `${apiUrl}/website-api/themes/${encodeURIComponent(themeId)}/source?version=${encodeURIComponent(version)}`;
|
|
3129
|
-
const response = await authenticatedFetch(url, {
|
|
3130
|
-
method: "GET"
|
|
3131
|
-
});
|
|
3154
|
+
const response = await authenticatedFetch(url, { method: "GET" }, env);
|
|
3132
3155
|
if (!response.ok) {
|
|
3133
3156
|
if (response.status === 404) {
|
|
3134
3157
|
throw new Error(
|
|
@@ -3137,7 +3160,7 @@ async function fetchSourceZip(apiUrl, themeId, version) {
|
|
|
3137
3160
|
}
|
|
3138
3161
|
if (response.status === 401 || response.status === 403) {
|
|
3139
3162
|
throw new Error(
|
|
3140
|
-
`Not authorized to download source for "${themeId}". Run \`onexthm login\` first.`
|
|
3163
|
+
`Not authorized to download source for "${themeId}". Run \`onexthm login --env ${env}\` first.`
|
|
3141
3164
|
);
|
|
3142
3165
|
}
|
|
3143
3166
|
throw new Error(
|
|
@@ -3256,14 +3279,19 @@ async function renameTheme(themeDir, oldName, newName) {
|
|
|
3256
3279
|
}
|
|
3257
3280
|
async function cloneCommand(themeName, options) {
|
|
3258
3281
|
logger.header("Clone Theme Source");
|
|
3259
|
-
|
|
3282
|
+
const env = options.env ?? "dev";
|
|
3283
|
+
const apiUrl = getApiUrl(env);
|
|
3284
|
+
logger.info(`Environment: ${env} (${apiUrl})`);
|
|
3285
|
+
if (options.bucket) {
|
|
3260
3286
|
logger.warning(
|
|
3261
|
-
"--bucket
|
|
3287
|
+
"--bucket is deprecated and ignored. Source is now fetched via HTTP from the website-api Lambda."
|
|
3262
3288
|
);
|
|
3263
3289
|
}
|
|
3264
|
-
const tokens = await getValidTokens();
|
|
3290
|
+
const tokens = await getValidTokens(env);
|
|
3265
3291
|
if (!tokens) {
|
|
3266
|
-
logger.error(
|
|
3292
|
+
logger.error(
|
|
3293
|
+
`Not logged in to ${env} environment. Run: onexthm login --env ${env}`
|
|
3294
|
+
);
|
|
3267
3295
|
process.exit(1);
|
|
3268
3296
|
}
|
|
3269
3297
|
let newName = options.name;
|
|
@@ -3272,7 +3300,6 @@ async function cloneCommand(themeName, options) {
|
|
|
3272
3300
|
}
|
|
3273
3301
|
const spinner = ora("Initializing clone...").start();
|
|
3274
3302
|
try {
|
|
3275
|
-
const apiUrl = getApiUrl();
|
|
3276
3303
|
const outputDir = options.output || path8.resolve(process.cwd(), newName);
|
|
3277
3304
|
if (await fs.pathExists(outputDir)) {
|
|
3278
3305
|
spinner.fail(chalk4.red(`Directory already exists: ${outputDir}`));
|
|
@@ -3292,7 +3319,7 @@ async function cloneCommand(themeName, options) {
|
|
|
3292
3319
|
spinner.start(`Downloading source.zip for ${themeName}@${version}...`);
|
|
3293
3320
|
let zipBuffer;
|
|
3294
3321
|
try {
|
|
3295
|
-
zipBuffer = await fetchSourceZip(apiUrl, themeName, version);
|
|
3322
|
+
zipBuffer = await fetchSourceZip(apiUrl, themeName, version, env);
|
|
3296
3323
|
} catch (error) {
|
|
3297
3324
|
spinner.fail(chalk4.red(error.message));
|
|
3298
3325
|
console.log();
|
|
@@ -3326,7 +3353,7 @@ async function cloneCommand(themeName, options) {
|
|
|
3326
3353
|
[
|
|
3327
3354
|
"# API Configuration (enables real data in preview)",
|
|
3328
3355
|
"# Get your Company ID from the OneX dashboard",
|
|
3329
|
-
|
|
3356
|
+
`NEXT_PUBLIC_API_URL=${apiUrl}`,
|
|
3330
3357
|
"NEXT_PUBLIC_COMPANY_ID=",
|
|
3331
3358
|
""
|
|
3332
3359
|
].join("\n")
|
|
@@ -3379,6 +3406,7 @@ async function cloneCommand(themeName, options) {
|
|
|
3379
3406
|
console.log(
|
|
3380
3407
|
chalk4.cyan(" Source: ") + chalk4.gray(`${themeName}@${version}`)
|
|
3381
3408
|
);
|
|
3409
|
+
console.log(chalk4.cyan(" Env: ") + chalk4.white(env));
|
|
3382
3410
|
console.log(chalk4.cyan(" Theme: ") + chalk4.white(newName));
|
|
3383
3411
|
console.log(chalk4.cyan(" Location: ") + chalk4.white(outputDir));
|
|
3384
3412
|
console.log(chalk4.cyan(" Files: ") + chalk4.white(entries.length));
|