@onexapis/cli 1.1.37 → 1.1.38

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 (48) hide show
  1. package/dist/cli.js +688 -454
  2. package/dist/cli.js.map +1 -1
  3. package/dist/cli.mjs +681 -449
  4. package/dist/cli.mjs.map +1 -1
  5. package/dist/index.js +343 -256
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +339 -253
  8. package/dist/index.mjs.map +1 -1
  9. package/dist/preview/preview-app.tsx +5 -13
  10. package/package.json +8 -4
  11. package/templates/default/bundle-entry.ts +0 -5
  12. package/templates/default/index.ts +1 -21
  13. package/templates/default/sections-registry.ts +0 -28
  14. package/templates/default/theme.layout.ts +2 -53
  15. package/templates/default/AUTH_AND_PROFILE.md +0 -167
  16. package/templates/default/LAYOUT.md +0 -195
  17. package/templates/default/hooks/index.ts +0 -26
  18. package/templates/default/hooks/use-forgot-password-form.ts +0 -90
  19. package/templates/default/hooks/use-login-form.ts +0 -102
  20. package/templates/default/hooks/use-profile-form.ts +0 -255
  21. package/templates/default/hooks/use-register-form.ts +0 -154
  22. package/templates/default/hooks/use-verify-code-form.ts +0 -224
  23. package/templates/default/pages/forgot-password.ts +0 -41
  24. package/templates/default/pages/login.ts +0 -41
  25. package/templates/default/pages/profile.ts +0 -39
  26. package/templates/default/pages/register.ts +0 -41
  27. package/templates/default/pages/verify-code.ts +0 -41
  28. package/templates/default/sections/auth-forgot-password/auth-forgot-password-default.tsx +0 -192
  29. package/templates/default/sections/auth-forgot-password/auth-forgot-password.schema.ts +0 -150
  30. package/templates/default/sections/auth-forgot-password/index.ts +0 -14
  31. package/templates/default/sections/auth-login/auth-login-default.tsx +0 -238
  32. package/templates/default/sections/auth-login/auth-login.schema.ts +0 -171
  33. package/templates/default/sections/auth-login/index.ts +0 -14
  34. package/templates/default/sections/auth-register/auth-register-default.tsx +0 -327
  35. package/templates/default/sections/auth-register/auth-register.schema.ts +0 -188
  36. package/templates/default/sections/auth-register/index.ts +0 -14
  37. package/templates/default/sections/auth-verify-code/auth-verify-code-default.tsx +0 -209
  38. package/templates/default/sections/auth-verify-code/auth-verify-code.schema.ts +0 -150
  39. package/templates/default/sections/auth-verify-code/index.ts +0 -14
  40. package/templates/default/sections/footer/footer-default.tsx +0 -214
  41. package/templates/default/sections/footer/footer.schema.ts +0 -170
  42. package/templates/default/sections/footer/index.ts +0 -14
  43. package/templates/default/sections/header/header-default.tsx +0 -322
  44. package/templates/default/sections/header/header.schema.ts +0 -168
  45. package/templates/default/sections/header/index.ts +0 -14
  46. package/templates/default/sections/profile/index.ts +0 -14
  47. package/templates/default/sections/profile/profile-default.tsx +0 -522
  48. package/templates/default/sections/profile/profile.schema.ts +0 -228
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 path9 from 'path';
5
+ import fs8 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';
10
- import { execSync, spawn } from 'child_process';
9
+ import fs4 from 'fs';
10
+ import spawn2 from 'cross-spawn';
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
+ path9.join(themePath, "sections/**/*.{ts,tsx}"),
106
+ path9.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 fs8.writeFile(path9.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 = path9.join(dir, "node_modules", relativePath);
128
128
  try {
129
- await fs6.access(candidate);
129
+ await fs8.access(candidate);
130
130
  return candidate;
131
131
  } catch {
132
- const parent = path7.dirname(dir);
132
+ const parent = path9.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 fs8.readFile(path9.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
+ path9.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
+ path9.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 fs8.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(path9.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(path9.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 = path9.join(themePath, "sections");
465
465
  try {
466
- const sectionDirs = await fs6.readdir(sectionsDir);
466
+ const sectionDirs = await fs8.readdir(sectionsDir);
467
467
  for (const dir of sectionDirs) {
468
- const schemaFile = path7.join(sectionsDir, dir, `${dir}.schema.ts`);
468
+ const schemaFile = path9.join(sectionsDir, dir, `${dir}.schema.ts`);
469
469
  try {
470
- await fs6.access(schemaFile);
470
+ await fs8.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 = path9.join(themePath, "pages");
483
483
  try {
484
- const files = await fs6.readdir(pagesDir);
484
+ const files = await fs8.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(path9.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 fs8.writeFile(
518
+ path9.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 = path9.join(outputDir, "bundle-entry.js");
542
+ const mapPath = path9.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 fs8.unlink(path9.join(outputDir, f));
546
546
  }
547
547
  let entryContent;
548
548
  try {
549
- entryContent = await fs6.readFile(entryPath, "utf-8");
549
+ entryContent = await fs8.readFile(entryPath, "utf-8");
550
550
  } catch {
551
- const indexPath = path7.join(outputDir, "index.js");
551
+ const indexPath = path9.join(outputDir, "index.js");
552
552
  try {
553
- entryContent = await fs6.readFile(indexPath, "utf-8");
553
+ entryContent = await fs8.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 = path9.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 fs8.writeFile(path9.join(outputDir, hashedName2), entryContent);
567
+ await fs8.unlink(indexPath);
568
568
  try {
569
- await fs6.access(indexMapPath);
570
- await fs6.rename(indexMapPath, path7.join(outputDir, hashedMapName2));
569
+ await fs8.access(indexMapPath);
570
+ await fs8.rename(indexMapPath, path9.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 fs8.writeFile(path9.join(outputDir, hashedName), entryContent);
584
+ await fs8.unlink(entryPath);
585
585
  try {
586
- await fs6.access(mapPath);
587
- await fs6.rename(mapPath, path7.join(outputDir, hashedMapName));
586
+ await fs8.access(mapPath);
587
+ await fs8.rename(mapPath, path9.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(path9.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 fs8.readFile(
619
+ path9.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 fs8.access(path9.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 fs8.writeFile(
679
+ path9.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 = path9.join(themePath, "dist");
685
+ const bundleEntry = path9.join(themePath, "bundle-entry.ts");
686
+ const indexEntry = path9.join(themePath, "index.ts");
687
687
  let entryPoint = indexEntry;
688
688
  try {
689
- await fs6.access(bundleEntry);
689
+ await fs8.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 = path9.join(outputDir, ".process-shim.js");
694
+ await fs8.mkdir(outputDir, { recursive: true });
695
+ await fs8.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 fs8.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 fs8.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 = path9.join(themePath, "dist");
773
+ const bundleEntry = path9.join(themePath, "bundle-entry.ts");
774
+ const indexEntry = path9.join(themePath, "index.ts");
775
775
  let entryPoint = indexEntry;
776
776
  try {
777
- await fs6.access(bundleEntry);
777
+ await fs8.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 = path9.join(outputDir, ".process-shim.js");
782
+ await fs8.mkdir(outputDir, { recursive: true });
783
+ await fs8.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 = path9.join(themePath, "dist");
837
+ await fs8.mkdir(outputDir, { recursive: true });
838
+ const outputPath = path9.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
+ path9.join(__dirname, "..", "preview", "preview-app.tsx"),
841
+ path9.join(__dirname, "preview", "preview-app.tsx"),
842
+ path9.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 fs8.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
+ path9.join(themePath, "node_modules", "@onexapis", "core", "src"),
931
+ path9.join(themePath, "..", "..", "packages", "core", "src"),
932
932
  // monorepo sibling
933
- path7.join(
933
+ path9.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 fs8.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
+ path9.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
+ path9.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 fs8.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 fs8.readFile(
981
+ path9.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 = path9.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 = path9.join(outputDir, ".process-shim-preview.js");
1136
+ await fs8.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 fs8.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 fs13 = __require("fs-extra");
1319
+ return fs13.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(path9.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
+ path9.join(__dirname, "../../templates"),
1366
1366
  // Development
1367
- path7.join(__dirname, "../templates"),
1367
+ path9.join(__dirname, "../templates"),
1368
1368
  // Production (dist/)
1369
- path7.join(process.cwd(), "templates"),
1369
+ path9.join(process.cwd(), "templates"),
1370
1370
  // Fallback
1371
- path7.join(process.cwd(), "packages/cli/templates")
1371
+ path9.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 = path9.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 = path9.join(templateDir, file);
1393
+ const targetPath = path9.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 = path9.join(templateDir, file);
1411
+ const targetPath = path9.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 !== path9.parse(currentDir).root) {
1427
+ const packageJsonPath = path9.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(path9.join(currentDir, "src/themes")) || fs.existsSync(path9.join(currentDir, "themes"))) {
1431
1431
  return currentDir;
1432
1432
  }
1433
1433
  }
1434
- currentDir = path7.dirname(currentDir);
1434
+ currentDir = path9.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(path9.join(root, "themes")))
1441
+ return path9.join(root, "themes");
1442
+ if (fs.existsSync(path9.join(root, "src/themes")))
1443
+ return path9.join(root, "src/themes");
1444
+ return path9.dirname(root);
1445
1445
  }
1446
1446
  function getFeaturesDir() {
1447
- return path7.join(getProjectRoot(), "src/features");
1447
+ return path9.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(path9.join(root, "themes")) || fs.existsSync(path9.join(root, "src/themes")) || fs.existsSync(path9.join(root, "theme.config.ts")) || fs.existsSync(path9.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 = path9.join(themesDir, name);
1468
+ return fs.statSync(themePath).isDirectory() && (fs.existsSync(path9.join(themePath, "theme.config.ts")) || fs.existsSync(path9.join(themePath, "bundle-entry.ts")) || fs.existsSync(path9.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 = path9.join(getThemesDir(), themeName);
1473
+ return fs.existsSync(themePath) && (fs.existsSync(path9.join(themePath, "theme.config.ts")) || fs.existsSync(path9.join(themePath, "bundle-entry.ts")) || fs.existsSync(path9.join(themePath, "manifest.ts")));
1474
1474
  }
1475
1475
  function detectPackageManager() {
1476
1476
  const userAgent = process.env.npm_config_user_agent || "";
@@ -1478,24 +1478,91 @@ 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(path9.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
1482
+ if (fs.existsSync(path9.join(cwd, "yarn.lock"))) return "yarn";
1483
+ if (fs.existsSync(path9.join(cwd, "bun.lockb"))) return "bun";
1484
1484
  return "npm";
1485
1485
  }
1486
1486
  async function installDependencies(projectPath, packageManager = "npm") {
1487
- return new Promise((resolve, reject) => {
1487
+ const args = packageManager === "yarn" ? [] : ["install"];
1488
+ const result = spawn2.sync(packageManager, args, {
1489
+ cwd: projectPath,
1490
+ stdio: "inherit"
1491
+ });
1492
+ if (result.status !== 0) {
1493
+ throw new Error(
1494
+ `${packageManager} install failed with exit code ${result.status}`
1495
+ );
1496
+ }
1497
+ }
1498
+ var AUTH_DIR = path9.join(os.homedir(), ".onexthm");
1499
+ path9.join(AUTH_DIR, "auth.json");
1500
+ function getApiUrl() {
1501
+ return process.env.ONEXTHM_API_URL || process.env.NEXT_PUBLIC_API_URL || "https://platform-dev.onexeos.com";
1502
+ }
1503
+ function getNpxCommand() {
1504
+ return process.platform === "win32" ? "npx.cmd" : "npx";
1505
+ }
1506
+ function getDefaultMcpConfig() {
1507
+ return {
1508
+ mcpServers: {
1509
+ onexthm: {
1510
+ command: getNpxCommand(),
1511
+ args: ["-y", "@onexapis/theme-mcp"]
1512
+ }
1513
+ }
1514
+ };
1515
+ }
1516
+ function ensureMcpJson(projectPath, figmaApiKey) {
1517
+ const mcpJsonPath = path9.join(projectPath, ".mcp.json");
1518
+ const npx = getNpxCommand();
1519
+ let mcpConfig;
1520
+ if (fs4.existsSync(mcpJsonPath)) {
1488
1521
  try {
1489
- const installCmd = packageManager === "yarn" ? "yarn" : `${packageManager} install`;
1490
- execSync(installCmd, {
1491
- cwd: projectPath,
1492
- stdio: "inherit"
1493
- });
1494
- resolve();
1495
- } catch (error) {
1496
- reject(error);
1522
+ mcpConfig = JSON.parse(fs4.readFileSync(mcpJsonPath, "utf-8"));
1523
+ if (!mcpConfig.mcpServers) {
1524
+ mcpConfig.mcpServers = {};
1525
+ }
1526
+ } catch {
1527
+ mcpConfig = getDefaultMcpConfig();
1497
1528
  }
1498
- });
1529
+ } else {
1530
+ mcpConfig = getDefaultMcpConfig();
1531
+ }
1532
+ mcpConfig.mcpServers.onexthm = {
1533
+ command: npx,
1534
+ args: ["-y", "@onexapis/theme-mcp"]
1535
+ };
1536
+ if (figmaApiKey) {
1537
+ mcpConfig.mcpServers.figma = {
1538
+ command: npx,
1539
+ args: [
1540
+ "-y",
1541
+ "figma-developer-mcp",
1542
+ `--figma-api-key=${figmaApiKey}`,
1543
+ "--stdio"
1544
+ ]
1545
+ };
1546
+ } else {
1547
+ delete mcpConfig.mcpServers.figma;
1548
+ }
1549
+ fs4.writeFileSync(mcpJsonPath, JSON.stringify(mcpConfig, null, 2) + "\n");
1550
+ ensureThemeMcpDependency(projectPath);
1551
+ }
1552
+ function ensureThemeMcpDependency(projectPath) {
1553
+ const pkgJsonPath = path9.join(projectPath, "package.json");
1554
+ if (!fs4.existsSync(pkgJsonPath)) return;
1555
+ try {
1556
+ const pkg = JSON.parse(fs4.readFileSync(pkgJsonPath, "utf-8"));
1557
+ if (!pkg.devDependencies) {
1558
+ pkg.devDependencies = {};
1559
+ }
1560
+ if (!pkg.devDependencies["@onexapis/theme-mcp"]) {
1561
+ pkg.devDependencies["@onexapis/theme-mcp"] = "^0.1.0";
1562
+ fs4.writeFileSync(pkgJsonPath, JSON.stringify(pkg, null, 2) + "\n");
1563
+ }
1564
+ } catch {
1565
+ }
1499
1566
  }
1500
1567
 
1501
1568
  // src/commands/init.ts
@@ -1514,7 +1581,7 @@ async function initCommand(projectName, options = {}) {
1514
1581
  if (!validateThemeName(kebabName)) {
1515
1582
  return "Invalid project name. Use lowercase letters, numbers, and hyphens only.";
1516
1583
  }
1517
- if (fs2.existsSync(path7.join(process.cwd(), kebabName))) {
1584
+ if (fs4.existsSync(path9.join(process.cwd(), kebabName))) {
1518
1585
  return `Directory "${kebabName}" already exists`;
1519
1586
  }
1520
1587
  return true;
@@ -1525,11 +1592,46 @@ async function initCommand(projectName, options = {}) {
1525
1592
  } else {
1526
1593
  name = toKebabCase(projectName);
1527
1594
  }
1528
- const projectPath = path7.join(process.cwd(), name);
1529
- if (fs2.existsSync(projectPath)) {
1595
+ const projectPath = path9.join(process.cwd(), name);
1596
+ if (fs4.existsSync(projectPath)) {
1530
1597
  logger.error(`Directory "${name}" already exists.`);
1531
1598
  process.exit(1);
1532
1599
  }
1600
+ if (!options.yes) {
1601
+ try {
1602
+ const apiUrl = getApiUrl();
1603
+ const controller = new AbortController();
1604
+ const timeout = setTimeout(() => controller.abort(), 3e3);
1605
+ const response = await fetch(
1606
+ `${apiUrl}/website-api/themes/${encodeURIComponent(name)}/exists`,
1607
+ { signal: controller.signal }
1608
+ );
1609
+ clearTimeout(timeout);
1610
+ if (response.ok) {
1611
+ const data2 = await response.json();
1612
+ const body = data2.statusCode ? data2.body : data2;
1613
+ if (body.exists && body.owner === "other") {
1614
+ logger.warning(
1615
+ `Theme ID "${name}" is already registered by another developer.
1616
+ You can still create this locally, but publishing will fail.
1617
+ Consider using a different name.`
1618
+ );
1619
+ const { proceed } = await inquirer.prompt([
1620
+ {
1621
+ type: "confirm",
1622
+ name: "proceed",
1623
+ message: "Continue anyway?",
1624
+ default: false
1625
+ }
1626
+ ]);
1627
+ if (!proceed) {
1628
+ process.exit(0);
1629
+ }
1630
+ }
1631
+ }
1632
+ } catch {
1633
+ }
1634
+ }
1533
1635
  let displayName;
1534
1636
  let description;
1535
1637
  let author;
@@ -1597,7 +1699,7 @@ async function initCommand(projectName, options = {}) {
1597
1699
  }
1598
1700
  logger.startSpinner("Creating project structure...");
1599
1701
  try {
1600
- fs2.mkdirSync(projectPath, { recursive: true });
1702
+ fs4.mkdirSync(projectPath, { recursive: true });
1601
1703
  await copyTemplate(template, projectPath, data);
1602
1704
  await renameThemeInFiles(
1603
1705
  projectPath,
@@ -1606,28 +1708,14 @@ async function initCommand(projectName, options = {}) {
1606
1708
  description,
1607
1709
  author
1608
1710
  );
1609
- const mcpJsonPath = path7.join(projectPath, ".mcp.json");
1610
- if (fs2.existsSync(mcpJsonPath)) {
1611
- let mcpContent = fs2.readFileSync(mcpJsonPath, "utf-8");
1612
- if (figmaApiKey) {
1613
- mcpContent = mcpContent.replace("__FIGMA_API_KEY__", figmaApiKey);
1614
- } else {
1615
- try {
1616
- const mcpJson = JSON.parse(mcpContent);
1617
- delete mcpJson.mcpServers.figma;
1618
- mcpContent = JSON.stringify(mcpJson, null, 2) + "\n";
1619
- } catch {
1620
- }
1621
- }
1622
- fs2.writeFileSync(mcpJsonPath, mcpContent, "utf-8");
1623
- }
1711
+ ensureMcpJson(projectPath, figmaApiKey || void 0);
1624
1712
  logger.stopSpinner(true, "Project structure created!");
1625
1713
  if (options.git) {
1626
1714
  logger.startSpinner("Initializing git repository...");
1627
1715
  try {
1628
- execSync("git init", { cwd: projectPath, stdio: "ignore" });
1629
- execSync("git add .", { cwd: projectPath, stdio: "ignore" });
1630
- execSync('git commit -m "Initial commit from onexthm init"', {
1716
+ spawn2.sync("git", ["init"], { cwd: projectPath, stdio: "ignore" });
1717
+ spawn2.sync("git", ["add", "."], { cwd: projectPath, stdio: "ignore" });
1718
+ spawn2.sync("git", ["commit", "-m", "Initial commit from onexthm init"], {
1631
1719
  cwd: projectPath,
1632
1720
  stdio: "ignore"
1633
1721
  });
@@ -1679,16 +1767,16 @@ async function initCommand(projectName, options = {}) {
1679
1767
  logger.error(
1680
1768
  error instanceof Error ? error.message : "Unknown error occurred"
1681
1769
  );
1682
- if (fs2.existsSync(projectPath)) {
1683
- fs2.rmSync(projectPath, { recursive: true, force: true });
1770
+ if (fs4.existsSync(projectPath)) {
1771
+ fs4.rmSync(projectPath, { recursive: true, force: true });
1684
1772
  }
1685
1773
  process.exit(1);
1686
1774
  }
1687
1775
  }
1688
1776
  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");
1777
+ const configPath = path9.join(projectPath, "theme.config.ts");
1778
+ if (fs4.existsSync(configPath)) {
1779
+ let content = fs4.readFileSync(configPath, "utf-8");
1692
1780
  content = content.replace(
1693
1781
  /name: "My Simple Theme"/,
1694
1782
  `name: "${displayName}"`
@@ -1697,11 +1785,11 @@ async function renameThemeInFiles(projectPath, themeName, displayName, descripti
1697
1785
  /description: ".*?"/,
1698
1786
  `description: "${description}"`
1699
1787
  );
1700
- fs2.writeFileSync(configPath, content, "utf-8");
1788
+ fs4.writeFileSync(configPath, content, "utf-8");
1701
1789
  }
1702
- const pkgPath = path7.join(projectPath, "package.json");
1703
- if (fs2.existsSync(pkgPath)) {
1704
- let content = fs2.readFileSync(pkgPath, "utf-8");
1790
+ const pkgPath = path9.join(projectPath, "package.json");
1791
+ if (fs4.existsSync(pkgPath)) {
1792
+ let content = fs4.readFileSync(pkgPath, "utf-8");
1705
1793
  content = content.replace(
1706
1794
  /@onex-themes\/my-simple/g,
1707
1795
  `@onex-themes/${themeName}`
@@ -1710,7 +1798,7 @@ async function renameThemeInFiles(projectPath, themeName, displayName, descripti
1710
1798
  /"description": ".*?"/,
1711
1799
  `"description": "${description}"`
1712
1800
  );
1713
- fs2.writeFileSync(pkgPath, content, "utf-8");
1801
+ fs4.writeFileSync(pkgPath, content, "utf-8");
1714
1802
  }
1715
1803
  }
1716
1804
 
@@ -1721,10 +1809,10 @@ async function createSectionCommand(name, options) {
1721
1809
  ensureOneXProject();
1722
1810
  if (!options.theme) {
1723
1811
  const isStandaloneTheme = ["theme.config.ts", "bundle-entry.ts"].some(
1724
- (f) => fs.existsSync(path7.join(process.cwd(), f))
1812
+ (f) => fs.existsSync(path9.join(process.cwd(), f))
1725
1813
  );
1726
1814
  if (isStandaloneTheme) {
1727
- options.theme = path7.basename(process.cwd());
1815
+ options.theme = path9.basename(process.cwd());
1728
1816
  }
1729
1817
  }
1730
1818
  const sectionName = toKebabCase(name);
@@ -1787,35 +1875,35 @@ async function createSectionCommand(name, options) {
1787
1875
  };
1788
1876
  logger.startSpinner("Creating section files...");
1789
1877
  try {
1790
- const themePath = path7.join(getThemesDir(), themeName);
1791
- const sectionPath = path7.join(themePath, "sections", sectionName);
1878
+ const themePath = path9.join(getThemesDir(), themeName);
1879
+ const sectionPath = path9.join(themePath, "sections", sectionName);
1792
1880
  const schemaContent = generateSectionSchema(data);
1793
1881
  await writeFile(
1794
- path7.join(sectionPath, `${sectionName}.schema.ts`),
1882
+ path9.join(sectionPath, `${sectionName}.schema.ts`),
1795
1883
  schemaContent
1796
1884
  );
1797
1885
  if (createTemplate) {
1798
1886
  const templateContent = generateSectionTemplate(data);
1799
1887
  await writeFile(
1800
- path7.join(sectionPath, `${sectionName}-default.tsx`),
1888
+ path9.join(sectionPath, `${sectionName}-default.tsx`),
1801
1889
  templateContent
1802
1890
  );
1803
1891
  }
1804
1892
  const indexContent = generateSectionIndex(data, createTemplate);
1805
- await writeFile(path7.join(sectionPath, "index.ts"), indexContent);
1893
+ await writeFile(path9.join(sectionPath, "index.ts"), indexContent);
1806
1894
  logger.stopSpinner(true, "Section files created successfully!");
1807
1895
  logger.newLine();
1808
1896
  logger.section("Next steps:");
1809
1897
  logger.log(
1810
- ` 1. Edit schema: ${path7.relative(process.cwd(), path7.join(sectionPath, `${sectionName}.schema.ts`))}`
1898
+ ` 1. Edit schema: ${path9.relative(process.cwd(), path9.join(sectionPath, `${sectionName}.schema.ts`))}`
1811
1899
  );
1812
1900
  if (createTemplate) {
1813
1901
  logger.log(
1814
- ` 2. Edit template: ${path7.relative(process.cwd(), path7.join(sectionPath, `${sectionName}-default.tsx`))}`
1902
+ ` 2. Edit template: ${path9.relative(process.cwd(), path9.join(sectionPath, `${sectionName}-default.tsx`))}`
1815
1903
  );
1816
1904
  }
1817
1905
  logger.log(
1818
- ` 3. Add to theme manifest: ${path7.relative(process.cwd(), path7.join(themePath, "manifest.ts"))}`
1906
+ ` 3. Add to theme manifest: ${path9.relative(process.cwd(), path9.join(themePath, "manifest.ts"))}`
1819
1907
  );
1820
1908
  logger.newLine();
1821
1909
  logger.success("Section created successfully!");
@@ -1963,10 +2051,10 @@ async function createBlockCommand(name, options) {
1963
2051
  ensureOneXProject();
1964
2052
  if (!options.theme) {
1965
2053
  const isStandaloneTheme = ["theme.config.ts", "bundle-entry.ts"].some(
1966
- (f) => fs.existsSync(path7.join(process.cwd(), f))
2054
+ (f) => fs.existsSync(path9.join(process.cwd(), f))
1967
2055
  );
1968
2056
  if (isStandaloneTheme) {
1969
- options.theme = path7.basename(process.cwd());
2057
+ options.theme = path9.basename(process.cwd());
1970
2058
  }
1971
2059
  }
1972
2060
  const blockName = toKebabCase(name);
@@ -2041,24 +2129,24 @@ async function createBlockCommand(name, options) {
2041
2129
  };
2042
2130
  logger.startSpinner("Creating block files...");
2043
2131
  try {
2044
- const blockPath = scope === "shared" ? path7.join(getFeaturesDir(), "blocks", blockName) : path7.join(getThemesDir(), themeName, "blocks", blockName);
2132
+ const blockPath = scope === "shared" ? path9.join(getFeaturesDir(), "blocks", blockName) : path9.join(getThemesDir(), themeName, "blocks", blockName);
2045
2133
  const schemaContent = generateBlockSchema(data);
2046
2134
  await writeFile(
2047
- path7.join(blockPath, `${blockName}.schema.ts`),
2135
+ path9.join(blockPath, `${blockName}.schema.ts`),
2048
2136
  schemaContent
2049
2137
  );
2050
2138
  const componentContent = generateBlockComponent(data);
2051
- await writeFile(path7.join(blockPath, `${blockName}.tsx`), componentContent);
2139
+ await writeFile(path9.join(blockPath, `${blockName}.tsx`), componentContent);
2052
2140
  const indexContent = generateBlockIndex(data);
2053
- await writeFile(path7.join(blockPath, "index.ts"), indexContent);
2141
+ await writeFile(path9.join(blockPath, "index.ts"), indexContent);
2054
2142
  logger.stopSpinner(true, "Block files created successfully!");
2055
2143
  logger.newLine();
2056
2144
  logger.section("Next steps:");
2057
2145
  logger.log(
2058
- ` 1. Edit schema: ${path7.relative(process.cwd(), path7.join(blockPath, `${blockName}.schema.ts`))}`
2146
+ ` 1. Edit schema: ${path9.relative(process.cwd(), path9.join(blockPath, `${blockName}.schema.ts`))}`
2059
2147
  );
2060
2148
  logger.log(
2061
- ` 2. Edit component: ${path7.relative(process.cwd(), path7.join(blockPath, `${blockName}.tsx`))}`
2149
+ ` 2. Edit component: ${path9.relative(process.cwd(), path9.join(blockPath, `${blockName}.tsx`))}`
2062
2150
  );
2063
2151
  logger.log(
2064
2152
  ` 3. Register in block registry: src/lib/registry/block-registry.ts`
@@ -2236,31 +2324,31 @@ async function createComponentCommand(name, options) {
2236
2324
  };
2237
2325
  logger.startSpinner("Creating component files...");
2238
2326
  try {
2239
- const componentPath = path7.join(
2327
+ const componentPath = path9.join(
2240
2328
  getFeaturesDir(),
2241
2329
  "components",
2242
2330
  componentName
2243
2331
  );
2244
2332
  const schemaContent = generateComponentSchema(data);
2245
2333
  await writeFile(
2246
- path7.join(componentPath, `${componentName}.schema.ts`),
2334
+ path9.join(componentPath, `${componentName}.schema.ts`),
2247
2335
  schemaContent
2248
2336
  );
2249
2337
  const componentContent = generateComponent(data);
2250
2338
  await writeFile(
2251
- path7.join(componentPath, `${componentName}.tsx`),
2339
+ path9.join(componentPath, `${componentName}.tsx`),
2252
2340
  componentContent
2253
2341
  );
2254
2342
  const indexContent = generateComponentIndex(data);
2255
- await writeFile(path7.join(componentPath, "index.ts"), indexContent);
2343
+ await writeFile(path9.join(componentPath, "index.ts"), indexContent);
2256
2344
  logger.stopSpinner(true, "Component files created successfully!");
2257
2345
  logger.newLine();
2258
2346
  logger.section("Next steps:");
2259
2347
  logger.log(
2260
- ` 1. Edit schema: ${path7.relative(process.cwd(), path7.join(componentPath, `${componentName}.schema.ts`))}`
2348
+ ` 1. Edit schema: ${path9.relative(process.cwd(), path9.join(componentPath, `${componentName}.schema.ts`))}`
2261
2349
  );
2262
2350
  logger.log(
2263
- ` 2. Edit component: ${path7.relative(process.cwd(), path7.join(componentPath, `${componentName}.tsx`))}`
2351
+ ` 2. Edit component: ${path9.relative(process.cwd(), path9.join(componentPath, `${componentName}.tsx`))}`
2264
2352
  );
2265
2353
  logger.log(
2266
2354
  ` 3. Register in component registry: src/lib/registry/component-registry.ts`
@@ -2417,13 +2505,13 @@ async function listSections(themeFilter) {
2417
2505
  return;
2418
2506
  }
2419
2507
  for (const theme of themes) {
2420
- const sectionsDir = path7.join(getThemesDir(), theme, "sections");
2508
+ const sectionsDir = path9.join(getThemesDir(), theme, "sections");
2421
2509
  if (!fs.existsSync(sectionsDir)) {
2422
2510
  continue;
2423
2511
  }
2424
2512
  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"));
2513
+ const sectionPath = path9.join(sectionsDir, name);
2514
+ return fs.statSync(sectionPath).isDirectory() && fs.existsSync(path9.join(sectionPath, "index.ts"));
2427
2515
  });
2428
2516
  if (sections.length > 0) {
2429
2517
  logger.log(chalk4.cyan(`
@@ -2437,11 +2525,11 @@ async function listSections(themeFilter) {
2437
2525
  }
2438
2526
  async function listBlocks(themeFilter) {
2439
2527
  logger.section("\u{1F9F1} Blocks");
2440
- const sharedBlocksDir = path7.join(getFeaturesDir(), "blocks");
2528
+ const sharedBlocksDir = path9.join(getFeaturesDir(), "blocks");
2441
2529
  if (fs.existsSync(sharedBlocksDir)) {
2442
2530
  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"));
2531
+ const blockPath = path9.join(sharedBlocksDir, name);
2532
+ return fs.statSync(blockPath).isDirectory() && fs.existsSync(path9.join(blockPath, "index.ts"));
2445
2533
  });
2446
2534
  if (sharedBlocks.length > 0) {
2447
2535
  logger.log(chalk4.cyan("\n Shared:"));
@@ -2452,13 +2540,13 @@ async function listBlocks(themeFilter) {
2452
2540
  }
2453
2541
  const themes = themeFilter ? [themeFilter] : listThemes();
2454
2542
  for (const theme of themes) {
2455
- const blocksDir = path7.join(getThemesDir(), theme, "blocks");
2543
+ const blocksDir = path9.join(getThemesDir(), theme, "blocks");
2456
2544
  if (!fs.existsSync(blocksDir)) {
2457
2545
  continue;
2458
2546
  }
2459
2547
  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"));
2548
+ const blockPath = path9.join(blocksDir, name);
2549
+ return fs.statSync(blockPath).isDirectory() && fs.existsSync(path9.join(blockPath, "index.ts"));
2462
2550
  });
2463
2551
  if (blocks.length > 0) {
2464
2552
  logger.log(chalk4.cyan(`
@@ -2472,14 +2560,14 @@ async function listBlocks(themeFilter) {
2472
2560
  }
2473
2561
  async function listComponents() {
2474
2562
  logger.section("\u2699\uFE0F Components");
2475
- const componentsDir = path7.join(getFeaturesDir(), "components");
2563
+ const componentsDir = path9.join(getFeaturesDir(), "components");
2476
2564
  if (!fs.existsSync(componentsDir)) {
2477
2565
  logger.warning("No components directory found");
2478
2566
  return;
2479
2567
  }
2480
2568
  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"));
2569
+ const componentPath = path9.join(componentsDir, name);
2570
+ return fs.statSync(componentPath).isDirectory() && fs.existsSync(path9.join(componentPath, "index.ts"));
2483
2571
  });
2484
2572
  if (components.length === 0) {
2485
2573
  logger.warning("No components found");
@@ -2500,11 +2588,11 @@ async function listThemesInfo() {
2500
2588
  }
2501
2589
  logger.log("");
2502
2590
  for (const theme of themes) {
2503
- const themeDir = path7.join(getThemesDir(), theme);
2591
+ const themeDir = path9.join(getThemesDir(), theme);
2504
2592
  const candidates = ["theme.config.ts", "bundle-entry.ts", "manifest.ts"];
2505
2593
  let manifestContent = "";
2506
2594
  for (const candidate of candidates) {
2507
- const candidatePath = path7.join(themeDir, candidate);
2595
+ const candidatePath = path9.join(themeDir, candidate);
2508
2596
  if (fs.existsSync(candidatePath)) {
2509
2597
  manifestContent = fs.readFileSync(candidatePath, "utf-8");
2510
2598
  break;
@@ -2533,14 +2621,14 @@ async function buildCommand(options) {
2533
2621
  if (options.theme) {
2534
2622
  themeName = options.theme;
2535
2623
  try {
2536
- const workspaceThemePath = path7.join(getThemesDir(), themeName);
2624
+ const workspaceThemePath = path9.join(getThemesDir(), themeName);
2537
2625
  if (fs.existsSync(workspaceThemePath)) {
2538
2626
  themePath = workspaceThemePath;
2539
2627
  } else {
2540
- themePath = path7.join(process.cwd(), themeName);
2628
+ themePath = path9.join(process.cwd(), themeName);
2541
2629
  }
2542
2630
  } catch {
2543
- themePath = path7.join(process.cwd(), themeName);
2631
+ themePath = path9.join(process.cwd(), themeName);
2544
2632
  }
2545
2633
  if (!fs.existsSync(themePath)) {
2546
2634
  logger.error(`Theme "${themeName}" not found.`);
@@ -2551,10 +2639,10 @@ async function buildCommand(options) {
2551
2639
  "theme.config.ts",
2552
2640
  "bundle-entry.ts",
2553
2641
  "manifest.ts"
2554
- ].some((f) => fs.existsSync(path7.join(process.cwd(), f)));
2642
+ ].some((f) => fs.existsSync(path9.join(process.cwd(), f)));
2555
2643
  if (isThemeDir) {
2556
2644
  themePath = process.cwd();
2557
- themeName = path7.basename(themePath);
2645
+ themeName = path9.basename(themePath);
2558
2646
  logger.info(`Building current theme: ${themeName}`);
2559
2647
  } else {
2560
2648
  logger.error(
@@ -2563,7 +2651,7 @@ async function buildCommand(options) {
2563
2651
  process.exit(1);
2564
2652
  }
2565
2653
  }
2566
- const packageJsonPath = path7.join(themePath, "package.json");
2654
+ const packageJsonPath = path9.join(themePath, "package.json");
2567
2655
  const hasPkgJson = fs.existsSync(packageJsonPath);
2568
2656
  if (!hasPkgJson) {
2569
2657
  logger.warning(
@@ -2619,9 +2707,9 @@ async function buildCommand(options) {
2619
2707
  logger.success("\u2713 Theme built successfully!");
2620
2708
  logger.newLine();
2621
2709
  logger.info(`Theme: ${themeName}`);
2622
- const distPath = path7.join(themePath, "dist");
2710
+ const distPath = path9.join(themePath, "dist");
2623
2711
  if (fs.existsSync(distPath)) {
2624
- logger.log(`Output: ${path7.relative(process.cwd(), distPath)}`);
2712
+ logger.log(`Output: ${path9.relative(process.cwd(), distPath)}`);
2625
2713
  const files = fs.readdirSync(distPath);
2626
2714
  logger.log(`Files: ${files.length}`);
2627
2715
  }
@@ -2629,17 +2717,17 @@ async function buildCommand(options) {
2629
2717
  }
2630
2718
  function runCommand(command, args, cwd) {
2631
2719
  return new Promise((resolve) => {
2632
- const proc = spawn(command, args, {
2720
+ const proc = spawn2(command, args, {
2633
2721
  cwd,
2634
2722
  stdio: ["pipe", "pipe", "pipe"],
2635
2723
  shell: true
2636
2724
  });
2637
2725
  let stdout = "";
2638
2726
  let stderr = "";
2639
- proc.stdout.on("data", (data) => {
2727
+ proc.stdout?.on("data", (data) => {
2640
2728
  stdout += data.toString();
2641
2729
  });
2642
- proc.stderr.on("data", (data) => {
2730
+ proc.stderr?.on("data", (data) => {
2643
2731
  stderr += data.toString();
2644
2732
  });
2645
2733
  proc.on("close", (code) => {
@@ -2709,11 +2797,11 @@ function getBucketName(env) {
2709
2797
  return environment === "production" ? "theme-s3-bucket" : "theme-s3-bucket";
2710
2798
  }
2711
2799
  async function findCompiledThemeDir(themeId, version) {
2712
- const searchPaths = [path7.resolve(process.cwd(), "dist")];
2800
+ const searchPaths = [path9.resolve(process.cwd(), "dist")];
2713
2801
  for (const dir of searchPaths) {
2714
2802
  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"));
2803
+ const hasManifest = await fs.pathExists(path9.join(dir, "manifest.json"));
2804
+ const hasThemeEntry = await fs.pathExists(path9.join(dir, "bundle-entry.js")) || await fs.pathExists(path9.join(dir, "theme.config.js")) || await fs.pathExists(path9.join(dir, "index.js"));
2717
2805
  if (hasManifest || hasThemeEntry) {
2718
2806
  return dir;
2719
2807
  }
@@ -2722,7 +2810,7 @@ async function findCompiledThemeDir(themeId, version) {
2722
2810
  return null;
2723
2811
  }
2724
2812
  async function readManifest() {
2725
- const manifestTsPath = path7.resolve(process.cwd(), "manifest.ts");
2813
+ const manifestTsPath = path9.resolve(process.cwd(), "manifest.ts");
2726
2814
  if (await fs.pathExists(manifestTsPath)) {
2727
2815
  try {
2728
2816
  const module = await import(manifestTsPath);
@@ -2731,7 +2819,7 @@ async function readManifest() {
2731
2819
  logger.warning("Failed to import manifest.ts, trying package.json");
2732
2820
  }
2733
2821
  }
2734
- const packageJsonPath = path7.resolve(process.cwd(), "package.json");
2822
+ const packageJsonPath = path9.resolve(process.cwd(), "package.json");
2735
2823
  if (await fs.pathExists(packageJsonPath)) {
2736
2824
  const pkg = await fs.readJson(packageJsonPath);
2737
2825
  return {
@@ -2765,13 +2853,13 @@ async function findSourceDir(themeId, explicitDir) {
2765
2853
  }
2766
2854
  const searchPaths = [
2767
2855
  process.cwd(),
2768
- path7.resolve(process.cwd(), `../../themes/${themeId}`),
2769
- path7.resolve(process.cwd(), `../themes/${themeId}`)
2856
+ path9.resolve(process.cwd(), `../../themes/${themeId}`),
2857
+ path9.resolve(process.cwd(), `../themes/${themeId}`)
2770
2858
  ];
2771
2859
  const markers = ["theme.config.ts", "bundle-entry.ts"];
2772
2860
  for (const dir of searchPaths) {
2773
2861
  for (const marker of markers) {
2774
- if (await fs.pathExists(path7.join(dir, marker))) {
2862
+ if (await fs.pathExists(path9.join(dir, marker))) {
2775
2863
  return dir;
2776
2864
  }
2777
2865
  }
@@ -2823,7 +2911,7 @@ async function uploadCommand(options) {
2823
2911
  spinner.succeed(`Found compiled theme at: ${compiledDir}`);
2824
2912
  spinner.start("Creating bundle.zip...");
2825
2913
  const tmpDir = os.tmpdir();
2826
- const bundleZipPath = path7.join(tmpDir, `${themeId}-${version}-bundle.zip`);
2914
+ const bundleZipPath = path9.join(tmpDir, `${themeId}-${version}-bundle.zip`);
2827
2915
  await createZipFromDir(compiledDir, bundleZipPath);
2828
2916
  const bundleZipBuffer = await fs.readFile(bundleZipPath);
2829
2917
  const bundleSizeMB = (bundleZipBuffer.length / 1024 / 1024).toFixed(2);
@@ -2877,7 +2965,7 @@ async function uploadCommand(options) {
2877
2965
  if (sourceDir) {
2878
2966
  spinner.succeed(`Found source at: ${sourceDir}`);
2879
2967
  spinner.start("Creating source.zip...");
2880
- const sourceZipPath = path7.join(
2968
+ const sourceZipPath = path9.join(
2881
2969
  tmpDir,
2882
2970
  `${themeId}-${version}-source.zip`
2883
2971
  );
@@ -3011,8 +3099,8 @@ async function resolveLatestVersion(s3Client, bucket, themeId) {
3011
3099
  async function createCompatibilityFiles(outputDir, manifest) {
3012
3100
  const entryFile = manifest.output?.entry || "bundle-entry.js";
3013
3101
  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");
3102
+ const hashedPath = path9.join(outputDir, entryFile);
3103
+ const stablePath = path9.join(outputDir, "bundle-entry.js");
3016
3104
  if (await fs.pathExists(hashedPath)) {
3017
3105
  await fs.copy(hashedPath, stablePath);
3018
3106
  const mapPath = hashedPath + ".map";
@@ -3021,13 +3109,13 @@ async function createCompatibilityFiles(outputDir, manifest) {
3021
3109
  }
3022
3110
  }
3023
3111
  }
3024
- const sectionsRegistryPath = path7.join(outputDir, "sections-registry.js");
3112
+ const sectionsRegistryPath = path9.join(outputDir, "sections-registry.js");
3025
3113
  const content = `// Re-export all sections from bundle-entry
3026
3114
  // This file exists to maintain compatibility with the import path
3027
3115
  export * from './bundle-entry.js';
3028
3116
  `;
3029
3117
  await fs.writeFile(sectionsRegistryPath, content, "utf-8");
3030
- const pkgJsonPath = path7.join(outputDir, "package.json");
3118
+ const pkgJsonPath = path9.join(outputDir, "package.json");
3031
3119
  await fs.writeFile(pkgJsonPath, '{\n "type": "module"\n}\n', "utf-8");
3032
3120
  }
3033
3121
  function showDownloadFailureHelp(themeId, bucket) {
@@ -3089,6 +3177,18 @@ async function downloadCommand(options) {
3089
3177
  spinner.succeed(
3090
3178
  `Resolved latest version: ${chalk4.cyan(resolvedVersion)}`
3091
3179
  );
3180
+ const isCI = !!(process.env.CI || process.env.GITHUB_ACTIONS || process.env.VERCEL);
3181
+ if (isCI) {
3182
+ console.log(
3183
+ chalk4.yellow(
3184
+ `
3185
+ Warning: Resolved "latest" to ${resolvedVersion} in CI environment.
3186
+ For production builds, pin to a specific version:
3187
+ THEME_VERSION=${resolvedVersion}
3188
+ `
3189
+ )
3190
+ );
3191
+ }
3092
3192
  }
3093
3193
  spinner.start(
3094
3194
  `Downloading bundle.zip for ${themeId}@${resolvedVersion}...`
@@ -3110,7 +3210,7 @@ async function downloadCommand(options) {
3110
3210
  zip.extractAllTo(outputDir, true);
3111
3211
  const entries = zip.getEntries().filter((e) => !e.isDirectory);
3112
3212
  spinner.succeed(`Extracted ${entries.length} files to ${outputDir}`);
3113
- const manifestPath = path7.join(outputDir, "manifest.json");
3213
+ const manifestPath = path9.join(outputDir, "manifest.json");
3114
3214
  const manifest = await fs.readJson(manifestPath);
3115
3215
  await createCompatibilityFiles(outputDir, manifest);
3116
3216
  console.log();
@@ -3210,10 +3310,9 @@ async function resolveLatestVersion2(s3Client, bucket, themeId) {
3210
3310
  }
3211
3311
  function runInstall(cwd) {
3212
3312
  return new Promise((resolve) => {
3213
- const proc = spawn("pnpm", ["install"], {
3313
+ const proc = spawn2("pnpm", ["install"], {
3214
3314
  cwd,
3215
- stdio: "inherit",
3216
- shell: true
3315
+ stdio: "inherit"
3217
3316
  });
3218
3317
  proc.on("close", (code) => resolve(code === 0));
3219
3318
  proc.on("error", () => resolve(false));
@@ -3244,7 +3343,7 @@ async function renameTheme(themeDir, oldName, newName) {
3244
3343
  const oldPrefix = `${oldName}-`;
3245
3344
  const newPrefix = `${newName}-`;
3246
3345
  const newDisplayName = newName.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
3247
- const pkgPath = path7.join(themeDir, "package.json");
3346
+ const pkgPath = path9.join(themeDir, "package.json");
3248
3347
  if (await fs.pathExists(pkgPath)) {
3249
3348
  const pkg = await fs.readJson(pkgPath);
3250
3349
  pkg.name = `@onex-themes/${newName}`;
@@ -3260,7 +3359,7 @@ async function renameTheme(themeDir, oldName, newName) {
3260
3359
  }
3261
3360
  await fs.writeJson(pkgPath, pkg, { spaces: 2 });
3262
3361
  }
3263
- const configPath = path7.join(themeDir, "theme.config.ts");
3362
+ const configPath = path9.join(themeDir, "theme.config.ts");
3264
3363
  if (await fs.pathExists(configPath)) {
3265
3364
  let content = await fs.readFile(configPath, "utf-8");
3266
3365
  content = content.replace(/id:\s*"[^"]*"/, `id: "${newName}"`);
@@ -3270,7 +3369,7 @@ async function renameTheme(themeDir, oldName, newName) {
3270
3369
  );
3271
3370
  await fs.writeFile(configPath, content);
3272
3371
  }
3273
- const layoutPath = path7.join(themeDir, "theme.layout.ts");
3372
+ const layoutPath = path9.join(themeDir, "theme.layout.ts");
3274
3373
  if (await fs.pathExists(layoutPath)) {
3275
3374
  let content = await fs.readFile(layoutPath, "utf-8");
3276
3375
  content = content.replace(/id:\s*"[^"]*"/, `id: "${newName}"`);
@@ -3283,7 +3382,7 @@ async function renameTheme(themeDir, oldName, newName) {
3283
3382
  const oldDisplayName = oldName.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
3284
3383
  const tsFiles = await glob("**/*.ts", { cwd: themeDir, nodir: true });
3285
3384
  for (const file of tsFiles) {
3286
- const filePath = path7.join(themeDir, file);
3385
+ const filePath = path9.join(themeDir, file);
3287
3386
  let content = await fs.readFile(filePath, "utf-8");
3288
3387
  const original = content;
3289
3388
  content = content.replace(
@@ -3312,7 +3411,7 @@ async function cloneCommand(themeName, options) {
3312
3411
  const spinner = ora("Initializing clone...").start();
3313
3412
  try {
3314
3413
  const bucket = options.bucket || getBucketName3(options.environment);
3315
- const outputDir = options.output || path7.resolve(process.cwd(), newName);
3414
+ const outputDir = options.output || path9.resolve(process.cwd(), newName);
3316
3415
  const s3Client = getS3Client3();
3317
3416
  if (await fs.pathExists(outputDir)) {
3318
3417
  spinner.fail(chalk4.red(`Directory already exists: ${outputDir}`));
@@ -3367,7 +3466,7 @@ async function cloneCommand(themeName, options) {
3367
3466
  spinner.succeed(
3368
3467
  `Renamed theme: ${chalk4.gray(themeName)} \u2192 ${chalk4.cyan(newName)}`
3369
3468
  );
3370
- const envExamplePath = path7.join(outputDir, ".env.example");
3469
+ const envExamplePath = path9.join(outputDir, ".env.example");
3371
3470
  if (!await fs.pathExists(envExamplePath)) {
3372
3471
  await fs.writeFile(
3373
3472
  envExamplePath,
@@ -3380,32 +3479,18 @@ async function cloneCommand(themeName, options) {
3380
3479
  ].join("\n")
3381
3480
  );
3382
3481
  }
3383
- const mcpJsonPath = path7.join(outputDir, ".mcp.json");
3384
- if (await fs.pathExists(mcpJsonPath)) {
3385
- const { default: inquirerMod } = await import('inquirer');
3386
- const { figmaApiKey } = await inquirerMod.prompt([
3387
- {
3388
- type: "password",
3389
- name: "figmaApiKey",
3390
- message: "Figma API Key (optional, for Figma-to-code MCP \u2014 press Enter to skip):"
3391
- }
3392
- ]);
3393
- let mcpContent = await fs.readFile(mcpJsonPath, "utf-8");
3394
- if (figmaApiKey) {
3395
- mcpContent = mcpContent.replace("__FIGMA_API_KEY__", figmaApiKey);
3396
- } else {
3397
- try {
3398
- const mcpJson = JSON.parse(mcpContent);
3399
- delete mcpJson.mcpServers?.figma;
3400
- mcpContent = JSON.stringify(mcpJson, null, 2) + "\n";
3401
- } catch {
3402
- }
3482
+ const { default: inquirerMod } = await import('inquirer');
3483
+ const { figmaApiKey } = await inquirerMod.prompt([
3484
+ {
3485
+ type: "password",
3486
+ name: "figmaApiKey",
3487
+ message: "Figma API Key (optional, for Figma-to-code MCP \u2014 press Enter to skip):"
3403
3488
  }
3404
- await fs.writeFile(mcpJsonPath, mcpContent, "utf-8");
3405
- }
3489
+ ]);
3490
+ ensureMcpJson(outputDir, figmaApiKey || void 0);
3406
3491
  if (options.install !== false) {
3407
3492
  const hasPkgJson = await fs.pathExists(
3408
- path7.join(outputDir, "package.json")
3493
+ path9.join(outputDir, "package.json")
3409
3494
  );
3410
3495
  if (hasPkgJson) {
3411
3496
  spinner.start("Installing dependencies...");
@@ -3432,9 +3517,10 @@ async function cloneCommand(themeName, options) {
3432
3517
  console.log(chalk4.cyan(" Files: ") + chalk4.white(entries.length));
3433
3518
  console.log();
3434
3519
  console.log(chalk4.cyan("Next steps:"));
3435
- console.log(chalk4.gray(` cd ${path7.relative(process.cwd(), outputDir)}`));
3520
+ console.log(chalk4.gray(` cd ${path9.relative(process.cwd(), outputDir)}`));
3521
+ const copyCmd = process.platform === "win32" ? "copy .env.example .env" : "cp .env.example .env";
3436
3522
  console.log(
3437
- chalk4.gray(" cp .env.example .env # then add your Company ID")
3523
+ chalk4.gray(` ${copyCmd} # then add your Company ID`)
3438
3524
  );
3439
3525
  if (options.install === false) {
3440
3526
  console.log(chalk4.gray(" pnpm install"));