@onexapis/cli 1.1.63 → 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/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 AUTH_FILE = path8.join(AUTH_DIR, "auth.json");
1554
- function getApiUrl() {
1555
- return process.env.ONEXTHM_API_URL || "https://platform-dev.onexeos.com";
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
- async function saveAuthTokens(tokens) {
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(AUTH_FILE, encrypted, "utf-8");
1583
+ await fs.writeFile(getAuthFile(env), encrypted, "utf-8");
1563
1584
  }
1564
- function loadAuthTokens() {
1585
+ function loadAuthTokens(env = "dev") {
1565
1586
  try {
1566
- if (!fs.existsSync(AUTH_FILE)) return null;
1567
- const encrypted = fs.readFileSync(AUTH_FILE, "utf-8");
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(AUTH_FILE);
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("Not logged in. Run: onexthm login");
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 || options.environment) {
3046
+ if (options.bucket) {
3022
3047
  spinner.stop();
3023
3048
  logger.warning(
3024
- "--bucket and --environment are deprecated and ignored. Themes are now served via HTTP from the website-api Lambda."
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
- if (options.bucket || options.environment) {
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 and --environment are deprecated and ignored. Source is now fetched via HTTP from the website-api Lambda."
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("Not logged in. Run: onexthm login");
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
- "NEXT_PUBLIC_API_URL=https://platform-dev.onexeos.com",
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));