@onexapis/cli 1.1.37 → 1.1.39

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.
Files changed (34) hide show
  1. package/dist/cli.js +639 -401
  2. package/dist/cli.js.map +1 -1
  3. package/dist/cli.mjs +633 -396
  4. package/dist/cli.mjs.map +1 -1
  5. package/dist/index.js +255 -203
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +252 -200
  8. package/dist/index.mjs.map +1 -1
  9. package/package.json +6 -4
  10. package/templates/default/CLAUDE.md +334 -1
  11. package/templates/default/esbuild.config.js +20 -0
  12. package/templates/default/pages/about.ts +2 -2
  13. package/templates/default/pages/forgot-password.ts +1 -3
  14. package/templates/default/pages/home.ts +4 -4
  15. package/templates/default/pages/login.ts +1 -3
  16. package/templates/default/pages/profile.ts +2 -2
  17. package/templates/default/pages/register.ts +1 -3
  18. package/templates/default/pages/showcase.ts +7 -7
  19. package/templates/default/pages/verify-code.ts +1 -3
  20. package/templates/default/sections/about/about.schema.ts +1 -1
  21. package/templates/default/sections/auth-forgot-password/auth-forgot-password.schema.ts +1 -1
  22. package/templates/default/sections/auth-login/auth-login.schema.ts +1 -1
  23. package/templates/default/sections/auth-register/auth-register.schema.ts +1 -1
  24. package/templates/default/sections/auth-verify-code/auth-verify-code.schema.ts +1 -1
  25. package/templates/default/sections/cta/cta.schema.ts +1 -1
  26. package/templates/default/sections/features/features.schema.ts +1 -1
  27. package/templates/default/sections/footer/footer.schema.ts +1 -1
  28. package/templates/default/sections/gallery/gallery.schema.ts +1 -1
  29. package/templates/default/sections/header/header.schema.ts +1 -1
  30. package/templates/default/sections/hero/hero.schema.ts +1 -1
  31. package/templates/default/sections/profile/profile.schema.ts +1 -1
  32. package/templates/default/sections/stats/stats.schema.ts +1 -1
  33. package/templates/default/sections/testimonials/testimonials.schema.ts +1 -1
  34. package/templates/default/theme.layout.ts +18 -0
package/dist/index.mjs CHANGED
@@ -1,18 +1,18 @@
1
1
  import chalk4 from 'chalk';
2
2
  import ora from 'ora';
3
3
  import * as esbuild from 'esbuild';
4
- import path7 from 'path';
5
- import fs6 from 'fs/promises';
4
+ import path8 from 'path';
5
+ import fs7 from 'fs/promises';
6
6
  import crypto from 'crypto';
7
7
  import { glob } from 'glob';
8
8
  import { createRequire } from 'module';
9
- import fs2 from 'fs';
9
+ import fs3 from 'fs';
10
10
  import { execSync, spawn } from 'child_process';
11
11
  import inquirer from 'inquirer';
12
12
  import fs from 'fs-extra';
13
13
  import ejs from 'ejs';
14
- import { PutObjectCommand, GetObjectCommand, S3Client } from '@aws-sdk/client-s3';
15
14
  import os from 'os';
15
+ import { PutObjectCommand, GetObjectCommand, S3Client } from '@aws-sdk/client-s3';
16
16
  import archiver from 'archiver';
17
17
  import AdmZip from 'adm-zip';
18
18
 
@@ -102,8 +102,8 @@ async function generateThemeCSS(themePath, outDir) {
102
102
  const tailwindcss = (await import('tailwindcss')).default;
103
103
  const tailwindConfig = {
104
104
  content: [
105
- path7.join(themePath, "sections/**/*.{ts,tsx}"),
106
- path7.join(themePath, "components/**/*.{ts,tsx}")
105
+ path8.join(themePath, "sections/**/*.{ts,tsx}"),
106
+ path8.join(themePath, "components/**/*.{ts,tsx}")
107
107
  ],
108
108
  theme: { extend: {} },
109
109
  plugins: []
@@ -113,7 +113,7 @@ async function generateThemeCSS(themePath, outDir) {
113
113
  inputCSS,
114
114
  { from: void 0 }
115
115
  );
116
- await fs6.writeFile(path7.join(outDir, "bundle.css"), result.css);
116
+ await fs7.writeFile(path8.join(outDir, "bundle.css"), result.css);
117
117
  logger.info("Generated bundle.css");
118
118
  } catch (err) {
119
119
  logger.warning(
@@ -124,12 +124,12 @@ async function generateThemeCSS(themePath, outDir) {
124
124
  async function resolveNodeModulesFile(startDir, relativePath) {
125
125
  let dir = startDir;
126
126
  while (true) {
127
- const candidate = path7.join(dir, "node_modules", relativePath);
127
+ const candidate = path8.join(dir, "node_modules", relativePath);
128
128
  try {
129
- await fs6.access(candidate);
129
+ await fs7.access(candidate);
130
130
  return candidate;
131
131
  } catch {
132
- const parent = path7.dirname(dir);
132
+ const parent = path8.dirname(dir);
133
133
  if (parent === dir) break;
134
134
  dir = parent;
135
135
  }
@@ -153,7 +153,7 @@ async function scanImportsFromPackage(sourceDir, packageName) {
153
153
  });
154
154
  for (const file of sourceFiles) {
155
155
  try {
156
- const content = await fs6.readFile(path7.join(sourceDir, file), "utf-8");
156
+ const content = await fs7.readFile(path8.join(sourceDir, file), "utf-8");
157
157
  for (const match of content.matchAll(namespaceImportRegex)) {
158
158
  const subpath = match[1] ? match[1].slice(1) : "";
159
159
  if (!result[subpath]) result[subpath] = /* @__PURE__ */ new Set();
@@ -207,17 +207,17 @@ function createCoreGlobalPlugin(themePath) {
207
207
  const distFileName = subpath ? `${subpath}.mjs` : "index.mjs";
208
208
  let distPath = await resolveNodeModulesFile(
209
209
  themePath,
210
- path7.join("@onexapis", "core", "dist", distFileName)
210
+ path8.join("@onexapis", "core", "dist", distFileName)
211
211
  );
212
212
  if (!distPath) {
213
213
  distPath = await resolveNodeModulesFile(
214
214
  __dirname,
215
- path7.join("@onexapis", "core", "dist", distFileName)
215
+ path8.join("@onexapis", "core", "dist", distFileName)
216
216
  );
217
217
  }
218
218
  try {
219
219
  if (!distPath) throw new Error("not found");
220
- const distContent = await fs6.readFile(distPath, "utf-8");
220
+ const distContent = await fs7.readFile(distPath, "utf-8");
221
221
  const exportMatches = distContent.matchAll(/export\s*\{([^}]+)\}/g);
222
222
  for (const m of exportMatches) {
223
223
  const names = m[1].split(",").map((n) => {
@@ -446,7 +446,7 @@ async function generateThemeData(themePath, outputDir, themeId) {
446
446
  const pages = {};
447
447
  for (const ext of [".ts", ".js"]) {
448
448
  try {
449
- const mod = await jiti.import(path7.join(themePath, `theme.config${ext}`));
449
+ const mod = await jiti.import(path8.join(themePath, `theme.config${ext}`));
450
450
  themeConfig = mod.default || mod;
451
451
  break;
452
452
  } catch {
@@ -454,20 +454,20 @@ async function generateThemeData(themePath, outputDir, themeId) {
454
454
  }
455
455
  for (const ext of [".ts", ".js"]) {
456
456
  try {
457
- const mod = await jiti.import(path7.join(themePath, `theme.layout${ext}`));
457
+ const mod = await jiti.import(path8.join(themePath, `theme.layout${ext}`));
458
458
  layoutConfig = mod.default || mod;
459
459
  break;
460
460
  } catch {
461
461
  }
462
462
  }
463
463
  const schemas = {};
464
- const sectionsDir = path7.join(themePath, "sections");
464
+ const sectionsDir = path8.join(themePath, "sections");
465
465
  try {
466
- const sectionDirs = await fs6.readdir(sectionsDir);
466
+ const sectionDirs = await fs7.readdir(sectionsDir);
467
467
  for (const dir of sectionDirs) {
468
- const schemaFile = path7.join(sectionsDir, dir, `${dir}.schema.ts`);
468
+ const schemaFile = path8.join(sectionsDir, dir, `${dir}.schema.ts`);
469
469
  try {
470
- await fs6.access(schemaFile);
470
+ await fs7.access(schemaFile);
471
471
  const mod = await jiti.import(schemaFile);
472
472
  for (const [key, value] of Object.entries(mod)) {
473
473
  if (key.endsWith("Schema") && value && typeof value === "object" && value.type) {
@@ -479,14 +479,14 @@ async function generateThemeData(themePath, outputDir, themeId) {
479
479
  }
480
480
  } catch {
481
481
  }
482
- const pagesDir = path7.join(themePath, "pages");
482
+ const pagesDir = path8.join(themePath, "pages");
483
483
  try {
484
- const files = await fs6.readdir(pagesDir);
484
+ const files = await fs7.readdir(pagesDir);
485
485
  for (const file of files) {
486
486
  if (!file.match(/\.(ts|js)$/)) continue;
487
487
  const name = file.replace(/\.(ts|js)$/, "");
488
488
  try {
489
- const mod = await jiti.import(path7.join(pagesDir, file));
489
+ const mod = await jiti.import(path8.join(pagesDir, file));
490
490
  const config = mod.default || mod;
491
491
  const sections = (config.sections || []).map((section) => {
492
492
  const schema = schemas[section.type];
@@ -514,8 +514,8 @@ async function generateThemeData(themePath, outputDir, themeId) {
514
514
  }
515
515
  } catch {
516
516
  }
517
- await fs6.writeFile(
518
- path7.join(outputDir, "theme-data.json"),
517
+ await fs7.writeFile(
518
+ path8.join(outputDir, "theme-data.json"),
519
519
  JSON.stringify(
520
520
  {
521
521
  themeId,
@@ -538,36 +538,36 @@ async function generateThemeData(themePath, outputDir, themeId) {
538
538
  logger.info(`Generated theme-data.json (${Object.keys(pages).length} pages)`);
539
539
  }
540
540
  async function contentHashEntry(outputDir) {
541
- const entryPath = path7.join(outputDir, "bundle-entry.js");
542
- const mapPath = path7.join(outputDir, "bundle-entry.js.map");
541
+ const entryPath = path8.join(outputDir, "bundle-entry.js");
542
+ const mapPath = path8.join(outputDir, "bundle-entry.js.map");
543
543
  const oldFiles = await glob("bundle-entry-*.js*", { cwd: outputDir });
544
544
  for (const f of oldFiles) {
545
- await fs6.unlink(path7.join(outputDir, f));
545
+ await fs7.unlink(path8.join(outputDir, f));
546
546
  }
547
547
  let entryContent;
548
548
  try {
549
- entryContent = await fs6.readFile(entryPath, "utf-8");
549
+ entryContent = await fs7.readFile(entryPath, "utf-8");
550
550
  } catch {
551
- const indexPath = path7.join(outputDir, "index.js");
551
+ const indexPath = path8.join(outputDir, "index.js");
552
552
  try {
553
- entryContent = await fs6.readFile(indexPath, "utf-8");
553
+ entryContent = await fs7.readFile(indexPath, "utf-8");
554
554
  } catch {
555
555
  logger.warning("No entry file found in output, skipping content hash");
556
556
  return;
557
557
  }
558
558
  const hash2 = crypto.createHash("sha256").update(entryContent).digest("hex").slice(0, 8);
559
559
  const hashedName2 = `bundle-entry-${hash2}.js`;
560
- const indexMapPath = path7.join(outputDir, "index.js.map");
560
+ const indexMapPath = path8.join(outputDir, "index.js.map");
561
561
  const hashedMapName2 = `bundle-entry-${hash2}.js.map`;
562
562
  entryContent = entryContent.replace(
563
563
  /\/\/# sourceMappingURL=index\.js\.map/,
564
564
  `//# sourceMappingURL=${hashedMapName2}`
565
565
  );
566
- await fs6.writeFile(path7.join(outputDir, hashedName2), entryContent);
567
- await fs6.unlink(indexPath);
566
+ await fs7.writeFile(path8.join(outputDir, hashedName2), entryContent);
567
+ await fs7.unlink(indexPath);
568
568
  try {
569
- await fs6.access(indexMapPath);
570
- await fs6.rename(indexMapPath, path7.join(outputDir, hashedMapName2));
569
+ await fs7.access(indexMapPath);
570
+ await fs7.rename(indexMapPath, path8.join(outputDir, hashedMapName2));
571
571
  } catch {
572
572
  }
573
573
  logger.info(`Entry hashed: ${hashedName2}`);
@@ -580,11 +580,11 @@ async function contentHashEntry(outputDir) {
580
580
  /\/\/# sourceMappingURL=bundle-entry\.js\.map/,
581
581
  `//# sourceMappingURL=${hashedMapName}`
582
582
  );
583
- await fs6.writeFile(path7.join(outputDir, hashedName), entryContent);
584
- await fs6.unlink(entryPath);
583
+ await fs7.writeFile(path8.join(outputDir, hashedName), entryContent);
584
+ await fs7.unlink(entryPath);
585
585
  try {
586
- await fs6.access(mapPath);
587
- await fs6.rename(mapPath, path7.join(outputDir, hashedMapName));
586
+ await fs7.access(mapPath);
587
+ await fs7.rename(mapPath, path8.join(outputDir, hashedMapName));
588
588
  } catch {
589
589
  }
590
590
  logger.info(`Entry hashed: ${hashedName}`);
@@ -596,7 +596,7 @@ async function extractDataRequirements(themePath) {
596
596
  const requirements = {};
597
597
  for (const file of schemaFiles) {
598
598
  try {
599
- const mod = await jiti.import(path7.join(themePath, file));
599
+ const mod = await jiti.import(path8.join(themePath, file));
600
600
  const exports$1 = mod;
601
601
  for (const value of Object.values(exports$1)) {
602
602
  if (value && typeof value === "object" && typeof value.type === "string" && value.dataRequirements && typeof value.dataRequirements === "object") {
@@ -615,8 +615,8 @@ async function generateManifest(themeName, themePath, outputDir) {
615
615
  let version = "1.0.0";
616
616
  let themeId = themeName;
617
617
  try {
618
- const pkgContent = await fs6.readFile(
619
- path7.join(themePath, "package.json"),
618
+ const pkgContent = await fs7.readFile(
619
+ path8.join(themePath, "package.json"),
620
620
  "utf-8"
621
621
  );
622
622
  const pkg = JSON.parse(pkgContent);
@@ -634,7 +634,7 @@ async function generateManifest(themeName, themePath, outputDir) {
634
634
  const dataRequirements = await extractDataRequirements(themePath);
635
635
  let hasThemeConfig = false;
636
636
  try {
637
- await fs6.access(path7.join(themePath, "theme.config.ts"));
637
+ await fs7.access(path8.join(themePath, "theme.config.ts"));
638
638
  hasThemeConfig = true;
639
639
  } catch {
640
640
  }
@@ -675,24 +675,24 @@ async function generateManifest(themeName, themePath, outputDir) {
675
675
  // Section data requirements for server-side prefetching (keyed by section type)
676
676
  dataRequirements
677
677
  };
678
- await fs6.writeFile(
679
- path7.join(outputDir, "manifest.json"),
678
+ await fs7.writeFile(
679
+ path8.join(outputDir, "manifest.json"),
680
680
  JSON.stringify(manifest, null, 2)
681
681
  );
682
682
  }
683
683
  async function compileStandaloneTheme(themePath, themeName) {
684
- const outputDir = path7.join(themePath, "dist");
685
- const bundleEntry = path7.join(themePath, "bundle-entry.ts");
686
- const indexEntry = path7.join(themePath, "index.ts");
684
+ const outputDir = path8.join(themePath, "dist");
685
+ const bundleEntry = path8.join(themePath, "bundle-entry.ts");
686
+ const indexEntry = path8.join(themePath, "index.ts");
687
687
  let entryPoint = indexEntry;
688
688
  try {
689
- await fs6.access(bundleEntry);
689
+ await fs7.access(bundleEntry);
690
690
  entryPoint = bundleEntry;
691
691
  } catch {
692
692
  }
693
- const shimPath = path7.join(outputDir, ".process-shim.js");
694
- await fs6.mkdir(outputDir, { recursive: true });
695
- await fs6.writeFile(shimPath, PROCESS_SHIM);
693
+ const shimPath = path8.join(outputDir, ".process-shim.js");
694
+ await fs7.mkdir(outputDir, { recursive: true });
695
+ await fs7.writeFile(shimPath, PROCESS_SHIM);
696
696
  const buildOptions = {
697
697
  entryPoints: [entryPoint],
698
698
  bundle: true,
@@ -742,7 +742,7 @@ async function compileStandaloneTheme(themePath, themeName) {
742
742
  try {
743
743
  const result = await esbuild.build(buildOptions);
744
744
  try {
745
- await fs6.unlink(shimPath);
745
+ await fs7.unlink(shimPath);
746
746
  } catch {
747
747
  }
748
748
  await contentHashEntry(outputDir);
@@ -761,7 +761,7 @@ async function compileStandaloneTheme(themePath, themeName) {
761
761
  return true;
762
762
  } catch (error) {
763
763
  try {
764
- await fs6.unlink(shimPath);
764
+ await fs7.unlink(shimPath);
765
765
  } catch {
766
766
  }
767
767
  logger.error(`esbuild compilation failed: ${error}`);
@@ -769,18 +769,18 @@ async function compileStandaloneTheme(themePath, themeName) {
769
769
  }
770
770
  }
771
771
  async function compileStandaloneThemeDev(themePath, themeName) {
772
- const outputDir = path7.join(themePath, "dist");
773
- const bundleEntry = path7.join(themePath, "bundle-entry.ts");
774
- const indexEntry = path7.join(themePath, "index.ts");
772
+ const outputDir = path8.join(themePath, "dist");
773
+ const bundleEntry = path8.join(themePath, "bundle-entry.ts");
774
+ const indexEntry = path8.join(themePath, "index.ts");
775
775
  let entryPoint = indexEntry;
776
776
  try {
777
- await fs6.access(bundleEntry);
777
+ await fs7.access(bundleEntry);
778
778
  entryPoint = bundleEntry;
779
779
  } catch {
780
780
  }
781
- const shimPath = path7.join(outputDir, ".process-shim.js");
782
- await fs6.mkdir(outputDir, { recursive: true });
783
- await fs6.writeFile(shimPath, PROCESS_SHIM);
781
+ const shimPath = path8.join(outputDir, ".process-shim.js");
782
+ await fs7.mkdir(outputDir, { recursive: true });
783
+ await fs7.writeFile(shimPath, PROCESS_SHIM);
784
784
  const buildOptions = {
785
785
  entryPoints: [entryPoint],
786
786
  bundle: true,
@@ -833,18 +833,18 @@ async function compileStandaloneThemeDev(themePath, themeName) {
833
833
  return { context: context2, outputDir };
834
834
  }
835
835
  async function compilePreviewRuntime(themePath) {
836
- const outputDir = path7.join(themePath, "dist");
837
- await fs6.mkdir(outputDir, { recursive: true });
838
- const outputPath = path7.join(outputDir, "preview-runtime.js");
836
+ const outputDir = path8.join(themePath, "dist");
837
+ await fs7.mkdir(outputDir, { recursive: true });
838
+ const outputPath = path8.join(outputDir, "preview-runtime.js");
839
839
  const locations = [
840
- path7.join(__dirname, "..", "preview", "preview-app.tsx"),
841
- path7.join(__dirname, "preview", "preview-app.tsx"),
842
- path7.join(__dirname, "..", "..", "src", "preview", "preview-app.tsx")
840
+ path8.join(__dirname, "..", "preview", "preview-app.tsx"),
841
+ path8.join(__dirname, "preview", "preview-app.tsx"),
842
+ path8.join(__dirname, "..", "..", "src", "preview", "preview-app.tsx")
843
843
  ];
844
844
  let previewEntryPath = null;
845
845
  for (const loc of locations) {
846
846
  try {
847
- await fs6.access(loc);
847
+ await fs7.access(loc);
848
848
  previewEntryPath = loc;
849
849
  break;
850
850
  } catch {
@@ -927,10 +927,10 @@ ${locations.join("\n")}`
927
927
  if (!lucideScanned) {
928
928
  lucideScanned = true;
929
929
  const coreSrcCandidates = [
930
- path7.join(themePath, "node_modules", "@onexapis", "core", "src"),
931
- path7.join(themePath, "..", "..", "packages", "core", "src"),
930
+ path8.join(themePath, "node_modules", "@onexapis", "core", "src"),
931
+ path8.join(themePath, "..", "..", "packages", "core", "src"),
932
932
  // monorepo sibling
933
- path7.join(
933
+ path8.join(
934
934
  __dirname,
935
935
  "..",
936
936
  "..",
@@ -945,7 +945,7 @@ ${locations.join("\n")}`
945
945
  let coreSourceDir = null;
946
946
  for (const candidate of coreSrcCandidates) {
947
947
  try {
948
- await fs6.access(candidate);
948
+ await fs7.access(candidate);
949
949
  coreSourceDir = candidate;
950
950
  break;
951
951
  } catch {
@@ -964,21 +964,21 @@ ${locations.join("\n")}`
964
964
  }
965
965
  } else {
966
966
  const coreDistCandidates = [
967
- path7.join(themePath, "node_modules", "@onexapis", "core", "dist")
967
+ path8.join(themePath, "node_modules", "@onexapis", "core", "dist")
968
968
  ];
969
969
  const resolvedDist = await resolveNodeModulesFile(
970
970
  __dirname,
971
- path7.join("@onexapis", "core", "dist")
971
+ path8.join("@onexapis", "core", "dist")
972
972
  );
973
973
  if (resolvedDist) coreDistCandidates.push(resolvedDist);
974
974
  for (const candidate of coreDistCandidates) {
975
975
  try {
976
- await fs6.access(candidate);
976
+ await fs7.access(candidate);
977
977
  const mjsFiles = await glob("*.mjs", { cwd: candidate });
978
978
  const importRegex = /import\s*\{([^}]+)\}\s*from\s*["']lucide-react["']/g;
979
979
  for (const file of mjsFiles) {
980
- const content = await fs6.readFile(
981
- path7.join(candidate, file),
980
+ const content = await fs7.readFile(
981
+ path8.join(candidate, file),
982
982
  "utf-8"
983
983
  );
984
984
  for (const match of content.matchAll(importRegex)) {
@@ -1033,7 +1033,7 @@ export default new Proxy({}, { get: (_, name) => name === '__esModule' ? true :
1033
1033
  const req = createRequire(import.meta.url || __filename);
1034
1034
  const cjsPath = req.resolve("framer-motion");
1035
1035
  const pkgDir = cjsPath.replace(/[/\\]dist[/\\].*$/, "");
1036
- const esmEntry = path7.join(pkgDir, "dist", "es", "index.mjs");
1036
+ const esmEntry = path8.join(pkgDir, "dist", "es", "index.mjs");
1037
1037
  const { existsSync } = await import('fs');
1038
1038
  if (existsSync(esmEntry)) {
1039
1039
  return { path: esmEntry, namespace: "file" };
@@ -1132,8 +1132,8 @@ export function headers() { return new Headers(); }
1132
1132
  });
1133
1133
  }
1134
1134
  };
1135
- const shimPath = path7.join(outputDir, ".process-shim-preview.js");
1136
- await fs6.writeFile(shimPath, PROCESS_SHIM);
1135
+ const shimPath = path8.join(outputDir, ".process-shim-preview.js");
1136
+ await fs7.writeFile(shimPath, PROCESS_SHIM);
1137
1137
  await esbuild.build({
1138
1138
  entryPoints: [previewEntryPath],
1139
1139
  bundle: true,
@@ -1168,7 +1168,7 @@ export function headers() { return new Headers(); }
1168
1168
  }
1169
1169
  });
1170
1170
  try {
1171
- await fs6.unlink(shimPath);
1171
+ await fs7.unlink(shimPath);
1172
1172
  } catch {
1173
1173
  }
1174
1174
  return outputPath;
@@ -1315,8 +1315,8 @@ function validateThemeName(name) {
1315
1315
  return /^[a-z][a-z0-9-]*$/.test(name);
1316
1316
  }
1317
1317
  function pathExists(filePath) {
1318
- const fs11 = __require("fs-extra");
1319
- return fs11.existsSync(filePath);
1318
+ const fs12 = __require("fs-extra");
1319
+ return fs12.existsSync(filePath);
1320
1320
  }
1321
1321
  function validateCategory(category) {
1322
1322
  const validCategories = [
@@ -1357,18 +1357,18 @@ async function renderTemplate(templatePath, data) {
1357
1357
  return ejs.render(template, data);
1358
1358
  }
1359
1359
  async function writeFile(filePath, content) {
1360
- await fs.ensureDir(path7.dirname(filePath));
1360
+ await fs.ensureDir(path8.dirname(filePath));
1361
1361
  await fs.writeFile(filePath, content, "utf-8");
1362
1362
  }
1363
1363
  function getTemplatesDir() {
1364
1364
  const locations = [
1365
- path7.join(__dirname, "../../templates"),
1365
+ path8.join(__dirname, "../../templates"),
1366
1366
  // Development
1367
- path7.join(__dirname, "../templates"),
1367
+ path8.join(__dirname, "../templates"),
1368
1368
  // Production (dist/)
1369
- path7.join(process.cwd(), "templates"),
1369
+ path8.join(process.cwd(), "templates"),
1370
1370
  // Fallback
1371
- path7.join(process.cwd(), "packages/cli/templates")
1371
+ path8.join(process.cwd(), "packages/cli/templates")
1372
1372
  // Monorepo
1373
1373
  ];
1374
1374
  for (const location of locations) {
@@ -1380,7 +1380,7 @@ function getTemplatesDir() {
1380
1380
  }
1381
1381
  async function copyTemplate(templateName, targetDir, data) {
1382
1382
  const templatesDir = getTemplatesDir();
1383
- const templateDir = path7.join(templatesDir, templateName);
1383
+ const templateDir = path8.join(templatesDir, templateName);
1384
1384
  if (!fs.existsSync(templateDir)) {
1385
1385
  throw new Error(
1386
1386
  `Template "${templateName}" not found at ${templateDir}. Available templates: ${fs.readdirSync(templatesDir).join(", ")}`
@@ -1389,8 +1389,8 @@ async function copyTemplate(templateName, targetDir, data) {
1389
1389
  await fs.ensureDir(targetDir);
1390
1390
  const files = await fs.readdir(templateDir);
1391
1391
  for (const file of files) {
1392
- const templatePath = path7.join(templateDir, file);
1393
- const targetPath = path7.join(targetDir, file);
1392
+ const templatePath = path8.join(templateDir, file);
1393
+ const targetPath = path8.join(targetDir, file);
1394
1394
  const stat = await fs.stat(templatePath);
1395
1395
  if (stat.isDirectory()) {
1396
1396
  await copyTemplateDir(templatePath, targetPath, data);
@@ -1407,8 +1407,8 @@ async function copyTemplateDir(templateDir, targetDir, data) {
1407
1407
  await fs.ensureDir(targetDir);
1408
1408
  const files = await fs.readdir(templateDir);
1409
1409
  for (const file of files) {
1410
- const templatePath = path7.join(templateDir, file);
1411
- const targetPath = path7.join(targetDir, file);
1410
+ const templatePath = path8.join(templateDir, file);
1411
+ const targetPath = path8.join(targetDir, file);
1412
1412
  const stat = await fs.stat(templatePath);
1413
1413
  if (stat.isDirectory()) {
1414
1414
  await copyTemplateDir(templatePath, targetPath, data);
@@ -1423,32 +1423,32 @@ async function copyTemplateDir(templateDir, targetDir, data) {
1423
1423
  }
1424
1424
  function getProjectRoot() {
1425
1425
  let currentDir = process.cwd();
1426
- while (currentDir !== path7.parse(currentDir).root) {
1427
- const packageJsonPath = path7.join(currentDir, "package.json");
1426
+ while (currentDir !== path8.parse(currentDir).root) {
1427
+ const packageJsonPath = path8.join(currentDir, "package.json");
1428
1428
  if (fs.existsSync(packageJsonPath)) {
1429
1429
  const packageJson = fs.readJsonSync(packageJsonPath);
1430
- if (packageJson.workspaces || fs.existsSync(path7.join(currentDir, "src/themes")) || fs.existsSync(path7.join(currentDir, "themes"))) {
1430
+ if (packageJson.workspaces || fs.existsSync(path8.join(currentDir, "src/themes")) || fs.existsSync(path8.join(currentDir, "themes"))) {
1431
1431
  return currentDir;
1432
1432
  }
1433
1433
  }
1434
- currentDir = path7.dirname(currentDir);
1434
+ currentDir = path8.dirname(currentDir);
1435
1435
  }
1436
1436
  return process.cwd();
1437
1437
  }
1438
1438
  function getThemesDir() {
1439
1439
  const root = getProjectRoot();
1440
- if (fs.existsSync(path7.join(root, "themes")))
1441
- return path7.join(root, "themes");
1442
- if (fs.existsSync(path7.join(root, "src/themes")))
1443
- return path7.join(root, "src/themes");
1444
- return path7.dirname(root);
1440
+ if (fs.existsSync(path8.join(root, "themes")))
1441
+ return path8.join(root, "themes");
1442
+ if (fs.existsSync(path8.join(root, "src/themes")))
1443
+ return path8.join(root, "src/themes");
1444
+ return path8.dirname(root);
1445
1445
  }
1446
1446
  function getFeaturesDir() {
1447
- return path7.join(getProjectRoot(), "src/features");
1447
+ return path8.join(getProjectRoot(), "src/features");
1448
1448
  }
1449
1449
  function isOneXProject() {
1450
1450
  const root = getProjectRoot();
1451
- return fs.existsSync(path7.join(root, "themes")) || fs.existsSync(path7.join(root, "src/themes")) || fs.existsSync(path7.join(root, "theme.config.ts")) || fs.existsSync(path7.join(root, "bundle-entry.ts"));
1451
+ return fs.existsSync(path8.join(root, "themes")) || fs.existsSync(path8.join(root, "src/themes")) || fs.existsSync(path8.join(root, "theme.config.ts")) || fs.existsSync(path8.join(root, "bundle-entry.ts"));
1452
1452
  }
1453
1453
  function ensureOneXProject() {
1454
1454
  if (!isOneXProject()) {
@@ -1464,13 +1464,13 @@ function listThemes() {
1464
1464
  return [];
1465
1465
  }
1466
1466
  return fs.readdirSync(themesDir).filter((name) => {
1467
- const themePath = path7.join(themesDir, name);
1468
- return fs.statSync(themePath).isDirectory() && (fs.existsSync(path7.join(themePath, "theme.config.ts")) || fs.existsSync(path7.join(themePath, "bundle-entry.ts")) || fs.existsSync(path7.join(themePath, "manifest.ts")));
1467
+ const themePath = path8.join(themesDir, name);
1468
+ return fs.statSync(themePath).isDirectory() && (fs.existsSync(path8.join(themePath, "theme.config.ts")) || fs.existsSync(path8.join(themePath, "bundle-entry.ts")) || fs.existsSync(path8.join(themePath, "manifest.ts")));
1469
1469
  });
1470
1470
  }
1471
1471
  function themeExists(themeName) {
1472
- const themePath = path7.join(getThemesDir(), themeName);
1473
- return fs.existsSync(themePath) && (fs.existsSync(path7.join(themePath, "theme.config.ts")) || fs.existsSync(path7.join(themePath, "bundle-entry.ts")) || fs.existsSync(path7.join(themePath, "manifest.ts")));
1472
+ const themePath = path8.join(getThemesDir(), themeName);
1473
+ return fs.existsSync(themePath) && (fs.existsSync(path8.join(themePath, "theme.config.ts")) || fs.existsSync(path8.join(themePath, "bundle-entry.ts")) || fs.existsSync(path8.join(themePath, "manifest.ts")));
1474
1474
  }
1475
1475
  function detectPackageManager() {
1476
1476
  const userAgent = process.env.npm_config_user_agent || "";
@@ -1478,9 +1478,9 @@ function detectPackageManager() {
1478
1478
  if (userAgent.includes("yarn")) return "yarn";
1479
1479
  if (userAgent.includes("bun")) return "bun";
1480
1480
  const cwd = process.cwd();
1481
- if (fs.existsSync(path7.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
1482
- if (fs.existsSync(path7.join(cwd, "yarn.lock"))) return "yarn";
1483
- if (fs.existsSync(path7.join(cwd, "bun.lockb"))) return "bun";
1481
+ if (fs.existsSync(path8.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
1482
+ if (fs.existsSync(path8.join(cwd, "yarn.lock"))) return "yarn";
1483
+ if (fs.existsSync(path8.join(cwd, "bun.lockb"))) return "bun";
1484
1484
  return "npm";
1485
1485
  }
1486
1486
  async function installDependencies(projectPath, packageManager = "npm") {
@@ -1497,6 +1497,11 @@ async function installDependencies(projectPath, packageManager = "npm") {
1497
1497
  }
1498
1498
  });
1499
1499
  }
1500
+ var AUTH_DIR = path8.join(os.homedir(), ".onexthm");
1501
+ path8.join(AUTH_DIR, "auth.json");
1502
+ function getApiUrl() {
1503
+ return process.env.ONEXTHM_API_URL || process.env.NEXT_PUBLIC_API_URL || "https://platform-dev.onexeos.com";
1504
+ }
1500
1505
 
1501
1506
  // src/commands/init.ts
1502
1507
  async function initCommand(projectName, options = {}) {
@@ -1514,7 +1519,7 @@ async function initCommand(projectName, options = {}) {
1514
1519
  if (!validateThemeName(kebabName)) {
1515
1520
  return "Invalid project name. Use lowercase letters, numbers, and hyphens only.";
1516
1521
  }
1517
- if (fs2.existsSync(path7.join(process.cwd(), kebabName))) {
1522
+ if (fs3.existsSync(path8.join(process.cwd(), kebabName))) {
1518
1523
  return `Directory "${kebabName}" already exists`;
1519
1524
  }
1520
1525
  return true;
@@ -1525,11 +1530,46 @@ async function initCommand(projectName, options = {}) {
1525
1530
  } else {
1526
1531
  name = toKebabCase(projectName);
1527
1532
  }
1528
- const projectPath = path7.join(process.cwd(), name);
1529
- if (fs2.existsSync(projectPath)) {
1533
+ const projectPath = path8.join(process.cwd(), name);
1534
+ if (fs3.existsSync(projectPath)) {
1530
1535
  logger.error(`Directory "${name}" already exists.`);
1531
1536
  process.exit(1);
1532
1537
  }
1538
+ if (!options.yes) {
1539
+ try {
1540
+ const apiUrl = getApiUrl();
1541
+ const controller = new AbortController();
1542
+ const timeout = setTimeout(() => controller.abort(), 3e3);
1543
+ const response = await fetch(
1544
+ `${apiUrl}/website-api/themes/${encodeURIComponent(name)}/exists`,
1545
+ { signal: controller.signal }
1546
+ );
1547
+ clearTimeout(timeout);
1548
+ if (response.ok) {
1549
+ const data2 = await response.json();
1550
+ const body = data2.statusCode ? data2.body : data2;
1551
+ if (body.exists && body.owner === "other") {
1552
+ logger.warning(
1553
+ `Theme ID "${name}" is already registered by another developer.
1554
+ You can still create this locally, but publishing will fail.
1555
+ Consider using a different name.`
1556
+ );
1557
+ const { proceed } = await inquirer.prompt([
1558
+ {
1559
+ type: "confirm",
1560
+ name: "proceed",
1561
+ message: "Continue anyway?",
1562
+ default: false
1563
+ }
1564
+ ]);
1565
+ if (!proceed) {
1566
+ process.exit(0);
1567
+ }
1568
+ }
1569
+ }
1570
+ } catch {
1571
+ }
1572
+ }
1533
1573
  let displayName;
1534
1574
  let description;
1535
1575
  let author;
@@ -1597,7 +1637,7 @@ async function initCommand(projectName, options = {}) {
1597
1637
  }
1598
1638
  logger.startSpinner("Creating project structure...");
1599
1639
  try {
1600
- fs2.mkdirSync(projectPath, { recursive: true });
1640
+ fs3.mkdirSync(projectPath, { recursive: true });
1601
1641
  await copyTemplate(template, projectPath, data);
1602
1642
  await renameThemeInFiles(
1603
1643
  projectPath,
@@ -1606,9 +1646,9 @@ async function initCommand(projectName, options = {}) {
1606
1646
  description,
1607
1647
  author
1608
1648
  );
1609
- const mcpJsonPath = path7.join(projectPath, ".mcp.json");
1610
- if (fs2.existsSync(mcpJsonPath)) {
1611
- let mcpContent = fs2.readFileSync(mcpJsonPath, "utf-8");
1649
+ const mcpJsonPath = path8.join(projectPath, ".mcp.json");
1650
+ if (fs3.existsSync(mcpJsonPath)) {
1651
+ let mcpContent = fs3.readFileSync(mcpJsonPath, "utf-8");
1612
1652
  if (figmaApiKey) {
1613
1653
  mcpContent = mcpContent.replace("__FIGMA_API_KEY__", figmaApiKey);
1614
1654
  } else {
@@ -1619,7 +1659,7 @@ async function initCommand(projectName, options = {}) {
1619
1659
  } catch {
1620
1660
  }
1621
1661
  }
1622
- fs2.writeFileSync(mcpJsonPath, mcpContent, "utf-8");
1662
+ fs3.writeFileSync(mcpJsonPath, mcpContent, "utf-8");
1623
1663
  }
1624
1664
  logger.stopSpinner(true, "Project structure created!");
1625
1665
  if (options.git) {
@@ -1679,16 +1719,16 @@ async function initCommand(projectName, options = {}) {
1679
1719
  logger.error(
1680
1720
  error instanceof Error ? error.message : "Unknown error occurred"
1681
1721
  );
1682
- if (fs2.existsSync(projectPath)) {
1683
- fs2.rmSync(projectPath, { recursive: true, force: true });
1722
+ if (fs3.existsSync(projectPath)) {
1723
+ fs3.rmSync(projectPath, { recursive: true, force: true });
1684
1724
  }
1685
1725
  process.exit(1);
1686
1726
  }
1687
1727
  }
1688
1728
  async function renameThemeInFiles(projectPath, themeName, displayName, description, author) {
1689
- const configPath = path7.join(projectPath, "theme.config.ts");
1690
- if (fs2.existsSync(configPath)) {
1691
- let content = fs2.readFileSync(configPath, "utf-8");
1729
+ const configPath = path8.join(projectPath, "theme.config.ts");
1730
+ if (fs3.existsSync(configPath)) {
1731
+ let content = fs3.readFileSync(configPath, "utf-8");
1692
1732
  content = content.replace(
1693
1733
  /name: "My Simple Theme"/,
1694
1734
  `name: "${displayName}"`
@@ -1697,11 +1737,11 @@ async function renameThemeInFiles(projectPath, themeName, displayName, descripti
1697
1737
  /description: ".*?"/,
1698
1738
  `description: "${description}"`
1699
1739
  );
1700
- fs2.writeFileSync(configPath, content, "utf-8");
1740
+ fs3.writeFileSync(configPath, content, "utf-8");
1701
1741
  }
1702
- const pkgPath = path7.join(projectPath, "package.json");
1703
- if (fs2.existsSync(pkgPath)) {
1704
- let content = fs2.readFileSync(pkgPath, "utf-8");
1742
+ const pkgPath = path8.join(projectPath, "package.json");
1743
+ if (fs3.existsSync(pkgPath)) {
1744
+ let content = fs3.readFileSync(pkgPath, "utf-8");
1705
1745
  content = content.replace(
1706
1746
  /@onex-themes\/my-simple/g,
1707
1747
  `@onex-themes/${themeName}`
@@ -1710,7 +1750,7 @@ async function renameThemeInFiles(projectPath, themeName, displayName, descripti
1710
1750
  /"description": ".*?"/,
1711
1751
  `"description": "${description}"`
1712
1752
  );
1713
- fs2.writeFileSync(pkgPath, content, "utf-8");
1753
+ fs3.writeFileSync(pkgPath, content, "utf-8");
1714
1754
  }
1715
1755
  }
1716
1756
 
@@ -1721,10 +1761,10 @@ async function createSectionCommand(name, options) {
1721
1761
  ensureOneXProject();
1722
1762
  if (!options.theme) {
1723
1763
  const isStandaloneTheme = ["theme.config.ts", "bundle-entry.ts"].some(
1724
- (f) => fs.existsSync(path7.join(process.cwd(), f))
1764
+ (f) => fs.existsSync(path8.join(process.cwd(), f))
1725
1765
  );
1726
1766
  if (isStandaloneTheme) {
1727
- options.theme = path7.basename(process.cwd());
1767
+ options.theme = path8.basename(process.cwd());
1728
1768
  }
1729
1769
  }
1730
1770
  const sectionName = toKebabCase(name);
@@ -1787,35 +1827,35 @@ async function createSectionCommand(name, options) {
1787
1827
  };
1788
1828
  logger.startSpinner("Creating section files...");
1789
1829
  try {
1790
- const themePath = path7.join(getThemesDir(), themeName);
1791
- const sectionPath = path7.join(themePath, "sections", sectionName);
1830
+ const themePath = path8.join(getThemesDir(), themeName);
1831
+ const sectionPath = path8.join(themePath, "sections", sectionName);
1792
1832
  const schemaContent = generateSectionSchema(data);
1793
1833
  await writeFile(
1794
- path7.join(sectionPath, `${sectionName}.schema.ts`),
1834
+ path8.join(sectionPath, `${sectionName}.schema.ts`),
1795
1835
  schemaContent
1796
1836
  );
1797
1837
  if (createTemplate) {
1798
1838
  const templateContent = generateSectionTemplate(data);
1799
1839
  await writeFile(
1800
- path7.join(sectionPath, `${sectionName}-default.tsx`),
1840
+ path8.join(sectionPath, `${sectionName}-default.tsx`),
1801
1841
  templateContent
1802
1842
  );
1803
1843
  }
1804
1844
  const indexContent = generateSectionIndex(data, createTemplate);
1805
- await writeFile(path7.join(sectionPath, "index.ts"), indexContent);
1845
+ await writeFile(path8.join(sectionPath, "index.ts"), indexContent);
1806
1846
  logger.stopSpinner(true, "Section files created successfully!");
1807
1847
  logger.newLine();
1808
1848
  logger.section("Next steps:");
1809
1849
  logger.log(
1810
- ` 1. Edit schema: ${path7.relative(process.cwd(), path7.join(sectionPath, `${sectionName}.schema.ts`))}`
1850
+ ` 1. Edit schema: ${path8.relative(process.cwd(), path8.join(sectionPath, `${sectionName}.schema.ts`))}`
1811
1851
  );
1812
1852
  if (createTemplate) {
1813
1853
  logger.log(
1814
- ` 2. Edit template: ${path7.relative(process.cwd(), path7.join(sectionPath, `${sectionName}-default.tsx`))}`
1854
+ ` 2. Edit template: ${path8.relative(process.cwd(), path8.join(sectionPath, `${sectionName}-default.tsx`))}`
1815
1855
  );
1816
1856
  }
1817
1857
  logger.log(
1818
- ` 3. Add to theme manifest: ${path7.relative(process.cwd(), path7.join(themePath, "manifest.ts"))}`
1858
+ ` 3. Add to theme manifest: ${path8.relative(process.cwd(), path8.join(themePath, "manifest.ts"))}`
1819
1859
  );
1820
1860
  logger.newLine();
1821
1861
  logger.success("Section created successfully!");
@@ -1963,10 +2003,10 @@ async function createBlockCommand(name, options) {
1963
2003
  ensureOneXProject();
1964
2004
  if (!options.theme) {
1965
2005
  const isStandaloneTheme = ["theme.config.ts", "bundle-entry.ts"].some(
1966
- (f) => fs.existsSync(path7.join(process.cwd(), f))
2006
+ (f) => fs.existsSync(path8.join(process.cwd(), f))
1967
2007
  );
1968
2008
  if (isStandaloneTheme) {
1969
- options.theme = path7.basename(process.cwd());
2009
+ options.theme = path8.basename(process.cwd());
1970
2010
  }
1971
2011
  }
1972
2012
  const blockName = toKebabCase(name);
@@ -2041,24 +2081,24 @@ async function createBlockCommand(name, options) {
2041
2081
  };
2042
2082
  logger.startSpinner("Creating block files...");
2043
2083
  try {
2044
- const blockPath = scope === "shared" ? path7.join(getFeaturesDir(), "blocks", blockName) : path7.join(getThemesDir(), themeName, "blocks", blockName);
2084
+ const blockPath = scope === "shared" ? path8.join(getFeaturesDir(), "blocks", blockName) : path8.join(getThemesDir(), themeName, "blocks", blockName);
2045
2085
  const schemaContent = generateBlockSchema(data);
2046
2086
  await writeFile(
2047
- path7.join(blockPath, `${blockName}.schema.ts`),
2087
+ path8.join(blockPath, `${blockName}.schema.ts`),
2048
2088
  schemaContent
2049
2089
  );
2050
2090
  const componentContent = generateBlockComponent(data);
2051
- await writeFile(path7.join(blockPath, `${blockName}.tsx`), componentContent);
2091
+ await writeFile(path8.join(blockPath, `${blockName}.tsx`), componentContent);
2052
2092
  const indexContent = generateBlockIndex(data);
2053
- await writeFile(path7.join(blockPath, "index.ts"), indexContent);
2093
+ await writeFile(path8.join(blockPath, "index.ts"), indexContent);
2054
2094
  logger.stopSpinner(true, "Block files created successfully!");
2055
2095
  logger.newLine();
2056
2096
  logger.section("Next steps:");
2057
2097
  logger.log(
2058
- ` 1. Edit schema: ${path7.relative(process.cwd(), path7.join(blockPath, `${blockName}.schema.ts`))}`
2098
+ ` 1. Edit schema: ${path8.relative(process.cwd(), path8.join(blockPath, `${blockName}.schema.ts`))}`
2059
2099
  );
2060
2100
  logger.log(
2061
- ` 2. Edit component: ${path7.relative(process.cwd(), path7.join(blockPath, `${blockName}.tsx`))}`
2101
+ ` 2. Edit component: ${path8.relative(process.cwd(), path8.join(blockPath, `${blockName}.tsx`))}`
2062
2102
  );
2063
2103
  logger.log(
2064
2104
  ` 3. Register in block registry: src/lib/registry/block-registry.ts`
@@ -2236,31 +2276,31 @@ async function createComponentCommand(name, options) {
2236
2276
  };
2237
2277
  logger.startSpinner("Creating component files...");
2238
2278
  try {
2239
- const componentPath = path7.join(
2279
+ const componentPath = path8.join(
2240
2280
  getFeaturesDir(),
2241
2281
  "components",
2242
2282
  componentName
2243
2283
  );
2244
2284
  const schemaContent = generateComponentSchema(data);
2245
2285
  await writeFile(
2246
- path7.join(componentPath, `${componentName}.schema.ts`),
2286
+ path8.join(componentPath, `${componentName}.schema.ts`),
2247
2287
  schemaContent
2248
2288
  );
2249
2289
  const componentContent = generateComponent(data);
2250
2290
  await writeFile(
2251
- path7.join(componentPath, `${componentName}.tsx`),
2291
+ path8.join(componentPath, `${componentName}.tsx`),
2252
2292
  componentContent
2253
2293
  );
2254
2294
  const indexContent = generateComponentIndex(data);
2255
- await writeFile(path7.join(componentPath, "index.ts"), indexContent);
2295
+ await writeFile(path8.join(componentPath, "index.ts"), indexContent);
2256
2296
  logger.stopSpinner(true, "Component files created successfully!");
2257
2297
  logger.newLine();
2258
2298
  logger.section("Next steps:");
2259
2299
  logger.log(
2260
- ` 1. Edit schema: ${path7.relative(process.cwd(), path7.join(componentPath, `${componentName}.schema.ts`))}`
2300
+ ` 1. Edit schema: ${path8.relative(process.cwd(), path8.join(componentPath, `${componentName}.schema.ts`))}`
2261
2301
  );
2262
2302
  logger.log(
2263
- ` 2. Edit component: ${path7.relative(process.cwd(), path7.join(componentPath, `${componentName}.tsx`))}`
2303
+ ` 2. Edit component: ${path8.relative(process.cwd(), path8.join(componentPath, `${componentName}.tsx`))}`
2264
2304
  );
2265
2305
  logger.log(
2266
2306
  ` 3. Register in component registry: src/lib/registry/component-registry.ts`
@@ -2417,13 +2457,13 @@ async function listSections(themeFilter) {
2417
2457
  return;
2418
2458
  }
2419
2459
  for (const theme of themes) {
2420
- const sectionsDir = path7.join(getThemesDir(), theme, "sections");
2460
+ const sectionsDir = path8.join(getThemesDir(), theme, "sections");
2421
2461
  if (!fs.existsSync(sectionsDir)) {
2422
2462
  continue;
2423
2463
  }
2424
2464
  const sections = fs.readdirSync(sectionsDir).filter((name) => {
2425
- const sectionPath = path7.join(sectionsDir, name);
2426
- return fs.statSync(sectionPath).isDirectory() && fs.existsSync(path7.join(sectionPath, "index.ts"));
2465
+ const sectionPath = path8.join(sectionsDir, name);
2466
+ return fs.statSync(sectionPath).isDirectory() && fs.existsSync(path8.join(sectionPath, "index.ts"));
2427
2467
  });
2428
2468
  if (sections.length > 0) {
2429
2469
  logger.log(chalk4.cyan(`
@@ -2437,11 +2477,11 @@ async function listSections(themeFilter) {
2437
2477
  }
2438
2478
  async function listBlocks(themeFilter) {
2439
2479
  logger.section("\u{1F9F1} Blocks");
2440
- const sharedBlocksDir = path7.join(getFeaturesDir(), "blocks");
2480
+ const sharedBlocksDir = path8.join(getFeaturesDir(), "blocks");
2441
2481
  if (fs.existsSync(sharedBlocksDir)) {
2442
2482
  const sharedBlocks = fs.readdirSync(sharedBlocksDir).filter((name) => {
2443
- const blockPath = path7.join(sharedBlocksDir, name);
2444
- return fs.statSync(blockPath).isDirectory() && fs.existsSync(path7.join(blockPath, "index.ts"));
2483
+ const blockPath = path8.join(sharedBlocksDir, name);
2484
+ return fs.statSync(blockPath).isDirectory() && fs.existsSync(path8.join(blockPath, "index.ts"));
2445
2485
  });
2446
2486
  if (sharedBlocks.length > 0) {
2447
2487
  logger.log(chalk4.cyan("\n Shared:"));
@@ -2452,13 +2492,13 @@ async function listBlocks(themeFilter) {
2452
2492
  }
2453
2493
  const themes = themeFilter ? [themeFilter] : listThemes();
2454
2494
  for (const theme of themes) {
2455
- const blocksDir = path7.join(getThemesDir(), theme, "blocks");
2495
+ const blocksDir = path8.join(getThemesDir(), theme, "blocks");
2456
2496
  if (!fs.existsSync(blocksDir)) {
2457
2497
  continue;
2458
2498
  }
2459
2499
  const blocks = fs.readdirSync(blocksDir).filter((name) => {
2460
- const blockPath = path7.join(blocksDir, name);
2461
- return fs.statSync(blockPath).isDirectory() && fs.existsSync(path7.join(blockPath, "index.ts"));
2500
+ const blockPath = path8.join(blocksDir, name);
2501
+ return fs.statSync(blockPath).isDirectory() && fs.existsSync(path8.join(blockPath, "index.ts"));
2462
2502
  });
2463
2503
  if (blocks.length > 0) {
2464
2504
  logger.log(chalk4.cyan(`
@@ -2472,14 +2512,14 @@ async function listBlocks(themeFilter) {
2472
2512
  }
2473
2513
  async function listComponents() {
2474
2514
  logger.section("\u2699\uFE0F Components");
2475
- const componentsDir = path7.join(getFeaturesDir(), "components");
2515
+ const componentsDir = path8.join(getFeaturesDir(), "components");
2476
2516
  if (!fs.existsSync(componentsDir)) {
2477
2517
  logger.warning("No components directory found");
2478
2518
  return;
2479
2519
  }
2480
2520
  const components = fs.readdirSync(componentsDir).filter((name) => {
2481
- const componentPath = path7.join(componentsDir, name);
2482
- return fs.statSync(componentPath).isDirectory() && fs.existsSync(path7.join(componentPath, "index.ts"));
2521
+ const componentPath = path8.join(componentsDir, name);
2522
+ return fs.statSync(componentPath).isDirectory() && fs.existsSync(path8.join(componentPath, "index.ts"));
2483
2523
  });
2484
2524
  if (components.length === 0) {
2485
2525
  logger.warning("No components found");
@@ -2500,11 +2540,11 @@ async function listThemesInfo() {
2500
2540
  }
2501
2541
  logger.log("");
2502
2542
  for (const theme of themes) {
2503
- const themeDir = path7.join(getThemesDir(), theme);
2543
+ const themeDir = path8.join(getThemesDir(), theme);
2504
2544
  const candidates = ["theme.config.ts", "bundle-entry.ts", "manifest.ts"];
2505
2545
  let manifestContent = "";
2506
2546
  for (const candidate of candidates) {
2507
- const candidatePath = path7.join(themeDir, candidate);
2547
+ const candidatePath = path8.join(themeDir, candidate);
2508
2548
  if (fs.existsSync(candidatePath)) {
2509
2549
  manifestContent = fs.readFileSync(candidatePath, "utf-8");
2510
2550
  break;
@@ -2533,14 +2573,14 @@ async function buildCommand(options) {
2533
2573
  if (options.theme) {
2534
2574
  themeName = options.theme;
2535
2575
  try {
2536
- const workspaceThemePath = path7.join(getThemesDir(), themeName);
2576
+ const workspaceThemePath = path8.join(getThemesDir(), themeName);
2537
2577
  if (fs.existsSync(workspaceThemePath)) {
2538
2578
  themePath = workspaceThemePath;
2539
2579
  } else {
2540
- themePath = path7.join(process.cwd(), themeName);
2580
+ themePath = path8.join(process.cwd(), themeName);
2541
2581
  }
2542
2582
  } catch {
2543
- themePath = path7.join(process.cwd(), themeName);
2583
+ themePath = path8.join(process.cwd(), themeName);
2544
2584
  }
2545
2585
  if (!fs.existsSync(themePath)) {
2546
2586
  logger.error(`Theme "${themeName}" not found.`);
@@ -2551,10 +2591,10 @@ async function buildCommand(options) {
2551
2591
  "theme.config.ts",
2552
2592
  "bundle-entry.ts",
2553
2593
  "manifest.ts"
2554
- ].some((f) => fs.existsSync(path7.join(process.cwd(), f)));
2594
+ ].some((f) => fs.existsSync(path8.join(process.cwd(), f)));
2555
2595
  if (isThemeDir) {
2556
2596
  themePath = process.cwd();
2557
- themeName = path7.basename(themePath);
2597
+ themeName = path8.basename(themePath);
2558
2598
  logger.info(`Building current theme: ${themeName}`);
2559
2599
  } else {
2560
2600
  logger.error(
@@ -2563,7 +2603,7 @@ async function buildCommand(options) {
2563
2603
  process.exit(1);
2564
2604
  }
2565
2605
  }
2566
- const packageJsonPath = path7.join(themePath, "package.json");
2606
+ const packageJsonPath = path8.join(themePath, "package.json");
2567
2607
  const hasPkgJson = fs.existsSync(packageJsonPath);
2568
2608
  if (!hasPkgJson) {
2569
2609
  logger.warning(
@@ -2619,9 +2659,9 @@ async function buildCommand(options) {
2619
2659
  logger.success("\u2713 Theme built successfully!");
2620
2660
  logger.newLine();
2621
2661
  logger.info(`Theme: ${themeName}`);
2622
- const distPath = path7.join(themePath, "dist");
2662
+ const distPath = path8.join(themePath, "dist");
2623
2663
  if (fs.existsSync(distPath)) {
2624
- logger.log(`Output: ${path7.relative(process.cwd(), distPath)}`);
2664
+ logger.log(`Output: ${path8.relative(process.cwd(), distPath)}`);
2625
2665
  const files = fs.readdirSync(distPath);
2626
2666
  logger.log(`Files: ${files.length}`);
2627
2667
  }
@@ -2709,11 +2749,11 @@ function getBucketName(env) {
2709
2749
  return environment === "production" ? "theme-s3-bucket" : "theme-s3-bucket";
2710
2750
  }
2711
2751
  async function findCompiledThemeDir(themeId, version) {
2712
- const searchPaths = [path7.resolve(process.cwd(), "dist")];
2752
+ const searchPaths = [path8.resolve(process.cwd(), "dist")];
2713
2753
  for (const dir of searchPaths) {
2714
2754
  if (await fs.pathExists(dir)) {
2715
- const hasManifest = await fs.pathExists(path7.join(dir, "manifest.json"));
2716
- const hasThemeEntry = await fs.pathExists(path7.join(dir, "bundle-entry.js")) || await fs.pathExists(path7.join(dir, "theme.config.js")) || await fs.pathExists(path7.join(dir, "index.js"));
2755
+ const hasManifest = await fs.pathExists(path8.join(dir, "manifest.json"));
2756
+ const hasThemeEntry = await fs.pathExists(path8.join(dir, "bundle-entry.js")) || await fs.pathExists(path8.join(dir, "theme.config.js")) || await fs.pathExists(path8.join(dir, "index.js"));
2717
2757
  if (hasManifest || hasThemeEntry) {
2718
2758
  return dir;
2719
2759
  }
@@ -2722,7 +2762,7 @@ async function findCompiledThemeDir(themeId, version) {
2722
2762
  return null;
2723
2763
  }
2724
2764
  async function readManifest() {
2725
- const manifestTsPath = path7.resolve(process.cwd(), "manifest.ts");
2765
+ const manifestTsPath = path8.resolve(process.cwd(), "manifest.ts");
2726
2766
  if (await fs.pathExists(manifestTsPath)) {
2727
2767
  try {
2728
2768
  const module = await import(manifestTsPath);
@@ -2731,7 +2771,7 @@ async function readManifest() {
2731
2771
  logger.warning("Failed to import manifest.ts, trying package.json");
2732
2772
  }
2733
2773
  }
2734
- const packageJsonPath = path7.resolve(process.cwd(), "package.json");
2774
+ const packageJsonPath = path8.resolve(process.cwd(), "package.json");
2735
2775
  if (await fs.pathExists(packageJsonPath)) {
2736
2776
  const pkg = await fs.readJson(packageJsonPath);
2737
2777
  return {
@@ -2765,13 +2805,13 @@ async function findSourceDir(themeId, explicitDir) {
2765
2805
  }
2766
2806
  const searchPaths = [
2767
2807
  process.cwd(),
2768
- path7.resolve(process.cwd(), `../../themes/${themeId}`),
2769
- path7.resolve(process.cwd(), `../themes/${themeId}`)
2808
+ path8.resolve(process.cwd(), `../../themes/${themeId}`),
2809
+ path8.resolve(process.cwd(), `../themes/${themeId}`)
2770
2810
  ];
2771
2811
  const markers = ["theme.config.ts", "bundle-entry.ts"];
2772
2812
  for (const dir of searchPaths) {
2773
2813
  for (const marker of markers) {
2774
- if (await fs.pathExists(path7.join(dir, marker))) {
2814
+ if (await fs.pathExists(path8.join(dir, marker))) {
2775
2815
  return dir;
2776
2816
  }
2777
2817
  }
@@ -2823,7 +2863,7 @@ async function uploadCommand(options) {
2823
2863
  spinner.succeed(`Found compiled theme at: ${compiledDir}`);
2824
2864
  spinner.start("Creating bundle.zip...");
2825
2865
  const tmpDir = os.tmpdir();
2826
- const bundleZipPath = path7.join(tmpDir, `${themeId}-${version}-bundle.zip`);
2866
+ const bundleZipPath = path8.join(tmpDir, `${themeId}-${version}-bundle.zip`);
2827
2867
  await createZipFromDir(compiledDir, bundleZipPath);
2828
2868
  const bundleZipBuffer = await fs.readFile(bundleZipPath);
2829
2869
  const bundleSizeMB = (bundleZipBuffer.length / 1024 / 1024).toFixed(2);
@@ -2877,7 +2917,7 @@ async function uploadCommand(options) {
2877
2917
  if (sourceDir) {
2878
2918
  spinner.succeed(`Found source at: ${sourceDir}`);
2879
2919
  spinner.start("Creating source.zip...");
2880
- const sourceZipPath = path7.join(
2920
+ const sourceZipPath = path8.join(
2881
2921
  tmpDir,
2882
2922
  `${themeId}-${version}-source.zip`
2883
2923
  );
@@ -3011,8 +3051,8 @@ async function resolveLatestVersion(s3Client, bucket, themeId) {
3011
3051
  async function createCompatibilityFiles(outputDir, manifest) {
3012
3052
  const entryFile = manifest.output?.entry || "bundle-entry.js";
3013
3053
  if (entryFile !== "bundle-entry.js" && entryFile.startsWith("bundle-entry-")) {
3014
- const hashedPath = path7.join(outputDir, entryFile);
3015
- const stablePath = path7.join(outputDir, "bundle-entry.js");
3054
+ const hashedPath = path8.join(outputDir, entryFile);
3055
+ const stablePath = path8.join(outputDir, "bundle-entry.js");
3016
3056
  if (await fs.pathExists(hashedPath)) {
3017
3057
  await fs.copy(hashedPath, stablePath);
3018
3058
  const mapPath = hashedPath + ".map";
@@ -3021,13 +3061,13 @@ async function createCompatibilityFiles(outputDir, manifest) {
3021
3061
  }
3022
3062
  }
3023
3063
  }
3024
- const sectionsRegistryPath = path7.join(outputDir, "sections-registry.js");
3064
+ const sectionsRegistryPath = path8.join(outputDir, "sections-registry.js");
3025
3065
  const content = `// Re-export all sections from bundle-entry
3026
3066
  // This file exists to maintain compatibility with the import path
3027
3067
  export * from './bundle-entry.js';
3028
3068
  `;
3029
3069
  await fs.writeFile(sectionsRegistryPath, content, "utf-8");
3030
- const pkgJsonPath = path7.join(outputDir, "package.json");
3070
+ const pkgJsonPath = path8.join(outputDir, "package.json");
3031
3071
  await fs.writeFile(pkgJsonPath, '{\n "type": "module"\n}\n', "utf-8");
3032
3072
  }
3033
3073
  function showDownloadFailureHelp(themeId, bucket) {
@@ -3089,6 +3129,18 @@ async function downloadCommand(options) {
3089
3129
  spinner.succeed(
3090
3130
  `Resolved latest version: ${chalk4.cyan(resolvedVersion)}`
3091
3131
  );
3132
+ const isCI = !!(process.env.CI || process.env.GITHUB_ACTIONS || process.env.VERCEL);
3133
+ if (isCI) {
3134
+ console.log(
3135
+ chalk4.yellow(
3136
+ `
3137
+ Warning: Resolved "latest" to ${resolvedVersion} in CI environment.
3138
+ For production builds, pin to a specific version:
3139
+ THEME_VERSION=${resolvedVersion}
3140
+ `
3141
+ )
3142
+ );
3143
+ }
3092
3144
  }
3093
3145
  spinner.start(
3094
3146
  `Downloading bundle.zip for ${themeId}@${resolvedVersion}...`
@@ -3110,7 +3162,7 @@ async function downloadCommand(options) {
3110
3162
  zip.extractAllTo(outputDir, true);
3111
3163
  const entries = zip.getEntries().filter((e) => !e.isDirectory);
3112
3164
  spinner.succeed(`Extracted ${entries.length} files to ${outputDir}`);
3113
- const manifestPath = path7.join(outputDir, "manifest.json");
3165
+ const manifestPath = path8.join(outputDir, "manifest.json");
3114
3166
  const manifest = await fs.readJson(manifestPath);
3115
3167
  await createCompatibilityFiles(outputDir, manifest);
3116
3168
  console.log();
@@ -3244,7 +3296,7 @@ async function renameTheme(themeDir, oldName, newName) {
3244
3296
  const oldPrefix = `${oldName}-`;
3245
3297
  const newPrefix = `${newName}-`;
3246
3298
  const newDisplayName = newName.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
3247
- const pkgPath = path7.join(themeDir, "package.json");
3299
+ const pkgPath = path8.join(themeDir, "package.json");
3248
3300
  if (await fs.pathExists(pkgPath)) {
3249
3301
  const pkg = await fs.readJson(pkgPath);
3250
3302
  pkg.name = `@onex-themes/${newName}`;
@@ -3260,7 +3312,7 @@ async function renameTheme(themeDir, oldName, newName) {
3260
3312
  }
3261
3313
  await fs.writeJson(pkgPath, pkg, { spaces: 2 });
3262
3314
  }
3263
- const configPath = path7.join(themeDir, "theme.config.ts");
3315
+ const configPath = path8.join(themeDir, "theme.config.ts");
3264
3316
  if (await fs.pathExists(configPath)) {
3265
3317
  let content = await fs.readFile(configPath, "utf-8");
3266
3318
  content = content.replace(/id:\s*"[^"]*"/, `id: "${newName}"`);
@@ -3270,7 +3322,7 @@ async function renameTheme(themeDir, oldName, newName) {
3270
3322
  );
3271
3323
  await fs.writeFile(configPath, content);
3272
3324
  }
3273
- const layoutPath = path7.join(themeDir, "theme.layout.ts");
3325
+ const layoutPath = path8.join(themeDir, "theme.layout.ts");
3274
3326
  if (await fs.pathExists(layoutPath)) {
3275
3327
  let content = await fs.readFile(layoutPath, "utf-8");
3276
3328
  content = content.replace(/id:\s*"[^"]*"/, `id: "${newName}"`);
@@ -3283,7 +3335,7 @@ async function renameTheme(themeDir, oldName, newName) {
3283
3335
  const oldDisplayName = oldName.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
3284
3336
  const tsFiles = await glob("**/*.ts", { cwd: themeDir, nodir: true });
3285
3337
  for (const file of tsFiles) {
3286
- const filePath = path7.join(themeDir, file);
3338
+ const filePath = path8.join(themeDir, file);
3287
3339
  let content = await fs.readFile(filePath, "utf-8");
3288
3340
  const original = content;
3289
3341
  content = content.replace(
@@ -3312,7 +3364,7 @@ async function cloneCommand(themeName, options) {
3312
3364
  const spinner = ora("Initializing clone...").start();
3313
3365
  try {
3314
3366
  const bucket = options.bucket || getBucketName3(options.environment);
3315
- const outputDir = options.output || path7.resolve(process.cwd(), newName);
3367
+ const outputDir = options.output || path8.resolve(process.cwd(), newName);
3316
3368
  const s3Client = getS3Client3();
3317
3369
  if (await fs.pathExists(outputDir)) {
3318
3370
  spinner.fail(chalk4.red(`Directory already exists: ${outputDir}`));
@@ -3367,7 +3419,7 @@ async function cloneCommand(themeName, options) {
3367
3419
  spinner.succeed(
3368
3420
  `Renamed theme: ${chalk4.gray(themeName)} \u2192 ${chalk4.cyan(newName)}`
3369
3421
  );
3370
- const envExamplePath = path7.join(outputDir, ".env.example");
3422
+ const envExamplePath = path8.join(outputDir, ".env.example");
3371
3423
  if (!await fs.pathExists(envExamplePath)) {
3372
3424
  await fs.writeFile(
3373
3425
  envExamplePath,
@@ -3380,7 +3432,7 @@ async function cloneCommand(themeName, options) {
3380
3432
  ].join("\n")
3381
3433
  );
3382
3434
  }
3383
- const mcpJsonPath = path7.join(outputDir, ".mcp.json");
3435
+ const mcpJsonPath = path8.join(outputDir, ".mcp.json");
3384
3436
  if (await fs.pathExists(mcpJsonPath)) {
3385
3437
  const { default: inquirerMod } = await import('inquirer');
3386
3438
  const { figmaApiKey } = await inquirerMod.prompt([
@@ -3405,7 +3457,7 @@ async function cloneCommand(themeName, options) {
3405
3457
  }
3406
3458
  if (options.install !== false) {
3407
3459
  const hasPkgJson = await fs.pathExists(
3408
- path7.join(outputDir, "package.json")
3460
+ path8.join(outputDir, "package.json")
3409
3461
  );
3410
3462
  if (hasPkgJson) {
3411
3463
  spinner.start("Installing dependencies...");
@@ -3432,7 +3484,7 @@ async function cloneCommand(themeName, options) {
3432
3484
  console.log(chalk4.cyan(" Files: ") + chalk4.white(entries.length));
3433
3485
  console.log();
3434
3486
  console.log(chalk4.cyan("Next steps:"));
3435
- console.log(chalk4.gray(` cd ${path7.relative(process.cwd(), outputDir)}`));
3487
+ console.log(chalk4.gray(` cd ${path8.relative(process.cwd(), outputDir)}`));
3436
3488
  console.log(
3437
3489
  chalk4.gray(" cp .env.example .env # then add your Company ID")
3438
3490
  );