@onexapis/cli 1.1.16 → 1.1.18

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 (63) hide show
  1. package/README.md +117 -51
  2. package/bin/onexthm.js +4 -0
  3. package/dist/cli.js +750 -328
  4. package/dist/cli.js.map +1 -1
  5. package/dist/cli.mjs +747 -325
  6. package/dist/cli.mjs.map +1 -1
  7. package/dist/index.js +162 -299
  8. package/dist/index.js.map +1 -1
  9. package/dist/index.mjs +162 -299
  10. package/dist/index.mjs.map +1 -1
  11. package/dist/preview/preview-app.tsx +175 -53
  12. package/package.json +14 -12
  13. package/templates/default/.env.example +1 -1
  14. package/templates/default/.mcp.json +8 -0
  15. package/templates/default/CLAUDE.md +941 -0
  16. package/templates/default/bundle-entry.ts +18 -0
  17. package/templates/default/index.ts +26 -0
  18. package/templates/default/package.json +37 -0
  19. package/templates/default/pages/about.ts +66 -0
  20. package/templates/default/pages/home.ts +93 -0
  21. package/templates/default/pages/showcase.ts +146 -0
  22. package/templates/default/sections/about/about-default.tsx +237 -0
  23. package/templates/default/sections/about/about.schema.ts +259 -0
  24. package/templates/default/sections/about/index.ts +15 -0
  25. package/templates/default/sections/cta/cta-default.tsx +180 -0
  26. package/templates/default/sections/cta/cta.schema.ts +210 -0
  27. package/templates/default/sections/cta/index.ts +11 -0
  28. package/templates/default/sections/features/features-default.tsx +154 -0
  29. package/templates/default/sections/features/features.schema.ts +330 -0
  30. package/templates/default/sections/features/index.ts +11 -0
  31. package/templates/default/sections/gallery/gallery-default.tsx +134 -0
  32. package/templates/default/sections/gallery/gallery.schema.ts +397 -0
  33. package/templates/default/sections/gallery/index.ts +11 -0
  34. package/templates/default/sections/hero/hero-default.tsx +212 -0
  35. package/templates/default/sections/hero/hero.schema.ts +273 -0
  36. package/templates/default/sections/hero/index.ts +15 -0
  37. package/templates/default/sections/stats/index.ts +11 -0
  38. package/templates/default/sections/stats/stats-default.tsx +103 -0
  39. package/templates/default/sections/stats/stats.schema.ts +266 -0
  40. package/templates/default/sections/testimonials/index.ts +11 -0
  41. package/templates/default/sections/testimonials/testimonials-default.tsx +130 -0
  42. package/templates/default/sections/testimonials/testimonials.schema.ts +371 -0
  43. package/templates/default/sections-registry.ts +32 -0
  44. package/templates/default/theme.config.ts +107 -0
  45. package/templates/default/theme.layout.ts +21 -0
  46. package/templates/default/tsconfig.json +16 -7
  47. package/templates/default/README.md.ejs +0 -129
  48. package/templates/default/esbuild.config.js +0 -81
  49. package/templates/default/package.json.ejs +0 -31
  50. package/templates/default/src/config.ts.ejs +0 -98
  51. package/templates/default/src/index.ts.ejs +0 -11
  52. package/templates/default/src/layout.ts +0 -23
  53. package/templates/default/src/manifest.ts.ejs +0 -47
  54. package/templates/default/src/pages/home.ts.ejs +0 -37
  55. package/templates/default/src/sections/footer/footer-default.tsx +0 -28
  56. package/templates/default/src/sections/footer/footer.schema.ts +0 -45
  57. package/templates/default/src/sections/footer/index.ts +0 -2
  58. package/templates/default/src/sections/header/header-default.tsx +0 -61
  59. package/templates/default/src/sections/header/header.schema.ts +0 -46
  60. package/templates/default/src/sections/header/index.ts +0 -2
  61. package/templates/default/src/sections/hero/hero-default.tsx +0 -52
  62. package/templates/default/src/sections/hero/hero.schema.ts +0 -52
  63. package/templates/default/src/sections/hero/index.ts +0 -2
package/dist/index.mjs CHANGED
@@ -5,6 +5,7 @@ import path7 from 'path';
5
5
  import fs6 from 'fs/promises';
6
6
  import crypto from 'crypto';
7
7
  import { glob } from 'glob';
8
+ import { createRequire } from 'module';
8
9
  import fs2 from 'fs';
9
10
  import { execSync, spawn } from 'child_process';
10
11
  import inquirer from 'inquirer';
@@ -93,7 +94,7 @@ __export(compile_theme_exports, {
93
94
  compilePreviewRuntime: () => compilePreviewRuntime,
94
95
  compileStandaloneTheme: () => compileStandaloneTheme,
95
96
  compileStandaloneThemeDev: () => compileStandaloneThemeDev,
96
- generateManifest: () => generateManifest2
97
+ generateManifest: () => generateManifest
97
98
  });
98
99
  async function resolveNodeModulesFile(startDir, relativePath) {
99
100
  let dir = startDir;
@@ -240,6 +241,12 @@ function createThemeDepsStubPlugin(themePath) {
240
241
  if (!result.errors.length) return result;
241
242
  } catch {
242
243
  }
244
+ try {
245
+ const req = createRequire(import.meta.url || __filename);
246
+ const resolved = req.resolve(args.path);
247
+ if (resolved) return { path: resolved, namespace: "file" };
248
+ } catch {
249
+ }
243
250
  return { path: args.path, namespace };
244
251
  });
245
252
  };
@@ -248,11 +255,19 @@ function createThemeDepsStubPlugin(themePath) {
248
255
  const stubs = {
249
256
  "next/image": `
250
257
  import React from 'react';
251
- const Image = (props) => {
252
- const { src, alt, width, height, fill, priority, ...rest } = props;
258
+ const Image = React.forwardRef((props, ref) => {
259
+ const { src, alt, width, height, fill, priority, sizes, quality, placeholder, blurDataURL, onLoad, onError, style, className, ...rest } = props;
253
260
  const imgSrc = typeof src === 'object' ? src.src : src;
254
- return React.createElement('img', { src: imgSrc, alt, width: fill ? undefined : width, height: fill ? undefined : height, loading: priority ? 'eager' : 'lazy', ...rest });
255
- };
261
+ const fillStyle = fill ? { position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: style?.objectFit || 'cover', display: 'block' } : {};
262
+ const mergedStyle = { ...fillStyle, ...style };
263
+ return React.createElement('img', {
264
+ ref, src: imgSrc, alt,
265
+ width: fill ? undefined : width, height: fill ? undefined : height,
266
+ loading: priority ? 'eager' : 'lazy',
267
+ style: Object.keys(mergedStyle).length > 0 ? mergedStyle : undefined,
268
+ className, onLoad, onError, ...rest,
269
+ });
270
+ });
256
271
  export default Image;
257
272
  `,
258
273
  "next/link": `
@@ -286,7 +301,10 @@ export function headers() { return new Headers(); }
286
301
  if (!lucideThemeScanned) {
287
302
  lucideThemeScanned = true;
288
303
  try {
289
- const scanned = await scanImportsFromPackage(themePath, "lucide-react");
304
+ const scanned = await scanImportsFromPackage(
305
+ themePath,
306
+ "lucide-react"
307
+ );
290
308
  for (const names of Object.values(scanned)) {
291
309
  for (const name of names) lucideImports.add(name);
292
310
  }
@@ -349,10 +367,13 @@ export function useFormContext() { return useForm(); }
349
367
  loader: "js"
350
368
  }));
351
369
  tryResolveOrStub(/^@hookform\/resolvers/, "hookform-resolvers-stub");
352
- build2.onLoad({ filter: /.*/, namespace: "hookform-resolvers-stub" }, () => ({
353
- contents: `export function zodResolver() { return () => ({ values: {}, errors: {} }); }`,
354
- loader: "js"
355
- }));
370
+ build2.onLoad(
371
+ { filter: /.*/, namespace: "hookform-resolvers-stub" },
372
+ () => ({
373
+ contents: `export function zodResolver() { return () => ({ values: {}, errors: {} }); }`,
374
+ loader: "js"
375
+ })
376
+ );
356
377
  tryResolveOrStub(/^next-intl$/, "next-intl-stub");
357
378
  build2.onLoad({ filter: /.*/, namespace: "next-intl-stub" }, () => ({
358
379
  contents: `
@@ -517,7 +538,7 @@ async function extractDataRequirements(themePath) {
517
538
  }
518
539
  return requirements;
519
540
  }
520
- async function generateManifest2(themeName, themePath, outputDir) {
541
+ async function generateManifest(themeName, themePath, outputDir) {
521
542
  let version = "1.0.0";
522
543
  let themeId = themeName;
523
544
  try {
@@ -610,7 +631,11 @@ async function compileStandaloneTheme(themePath, themeName) {
610
631
  banner: {
611
632
  js: '"use client";'
612
633
  },
613
- plugins: [reactGlobalPlugin, createCoreGlobalPlugin(themePath), createThemeDepsStubPlugin(themePath)],
634
+ plugins: [
635
+ reactGlobalPlugin,
636
+ createCoreGlobalPlugin(themePath),
637
+ createThemeDepsStubPlugin(themePath)
638
+ ],
614
639
  external: [],
615
640
  alias: {
616
641
  events: "events/",
@@ -648,7 +673,7 @@ async function compileStandaloneTheme(themePath, themeName) {
648
673
  } catch {
649
674
  }
650
675
  await contentHashEntry(outputDir);
651
- await generateManifest2(themeName, themePath, outputDir);
676
+ await generateManifest(themeName, themePath, outputDir);
652
677
  await generateThemeData(themePath, outputDir, themeName);
653
678
  if (result.metafile) {
654
679
  const outputs = result.metafile.outputs;
@@ -692,7 +717,11 @@ async function compileStandaloneThemeDev(themePath, themeName) {
692
717
  banner: {
693
718
  js: '"use client";'
694
719
  },
695
- plugins: [reactGlobalPlugin, createCoreGlobalPlugin(themePath), createThemeDepsStubPlugin(themePath)],
720
+ plugins: [
721
+ reactGlobalPlugin,
722
+ createCoreGlobalPlugin(themePath),
723
+ createThemeDepsStubPlugin(themePath)
724
+ ],
696
725
  external: [],
697
726
  alias: {
698
727
  events: "events/",
@@ -725,7 +754,7 @@ async function compileStandaloneThemeDev(themePath, themeName) {
725
754
  };
726
755
  const context2 = await esbuild.context(buildOptions);
727
756
  await context2.rebuild();
728
- await generateManifest2(themeName, themePath, outputDir);
757
+ await generateManifest(themeName, themePath, outputDir);
729
758
  await generateThemeData(themePath, outputDir, themeName);
730
759
  return { context: context2, outputDir };
731
760
  }
@@ -827,7 +856,16 @@ ${locations.join("\n")}`
827
856
  path7.join(themePath, "node_modules", "@onexapis", "core", "src"),
828
857
  path7.join(themePath, "..", "..", "packages", "core", "src"),
829
858
  // monorepo sibling
830
- path7.join(__dirname, "..", "..", "..", "..", "packages", "core", "src")
859
+ path7.join(
860
+ __dirname,
861
+ "..",
862
+ "..",
863
+ "..",
864
+ "..",
865
+ "packages",
866
+ "core",
867
+ "src"
868
+ )
831
869
  // from CLI src
832
870
  ];
833
871
  let coreSourceDir = null;
@@ -841,7 +879,10 @@ ${locations.join("\n")}`
841
879
  }
842
880
  if (coreSourceDir) {
843
881
  try {
844
- const scanned = await scanImportsFromPackage(coreSourceDir, "lucide-react");
882
+ const scanned = await scanImportsFromPackage(
883
+ coreSourceDir,
884
+ "lucide-react"
885
+ );
845
886
  for (const names of Object.values(scanned)) {
846
887
  for (const name of names) lucideIconNames.add(name);
847
888
  }
@@ -862,7 +903,10 @@ ${locations.join("\n")}`
862
903
  const mjsFiles = await glob("*.mjs", { cwd: candidate });
863
904
  const importRegex = /import\s*\{([^}]+)\}\s*from\s*["']lucide-react["']/g;
864
905
  for (const file of mjsFiles) {
865
- const content = await fs6.readFile(path7.join(candidate, file), "utf-8");
906
+ const content = await fs6.readFile(
907
+ path7.join(candidate, file),
908
+ "utf-8"
909
+ );
866
910
  for (const match of content.matchAll(importRegex)) {
867
911
  for (const name of match[1].split(",")) {
868
912
  const original = name.trim().split(/\s+as\s+/)[0].trim();
@@ -878,7 +922,10 @@ ${locations.join("\n")}`
878
922
  }
879
923
  }
880
924
  try {
881
- const scanned = await scanImportsFromPackage(themePath, "lucide-react");
925
+ const scanned = await scanImportsFromPackage(
926
+ themePath,
927
+ "lucide-react"
928
+ );
882
929
  for (const names of Object.values(scanned)) {
883
930
  for (const name of names) lucideIconNames.add(name);
884
931
  }
@@ -908,14 +955,39 @@ export default new Proxy({}, { get: (_, name) => name === '__esModule' ? true :
908
955
  if (!result.errors.length) return result;
909
956
  } catch {
910
957
  }
958
+ try {
959
+ const req = createRequire(import.meta.url || __filename);
960
+ const cjsPath = req.resolve("framer-motion");
961
+ const pkgDir = cjsPath.replace(/[/\\]dist[/\\].*$/, "");
962
+ const esmEntry = path7.join(pkgDir, "dist", "es", "index.mjs");
963
+ const { existsSync } = await import('fs');
964
+ if (existsSync(esmEntry)) {
965
+ return { path: esmEntry, namespace: "file" };
966
+ }
967
+ return { path: cjsPath, namespace: "file" };
968
+ } catch {
969
+ }
911
970
  return { path: args.path, namespace: "motion-stub" };
912
971
  });
913
972
  build2.onLoad({ filter: /.*/, namespace: "motion-stub" }, () => ({
914
973
  contents: `
915
- const stub = (props) => props.children || null;
916
- const handler = { get: (_, name) => name === '__esModule' ? true : stub };
974
+ import React from 'react';
975
+ const MotionComponent = React.forwardRef((props, ref) => {
976
+ const { initial, animate, exit, variants, transition, whileInView, whileHover, whileTap, viewport, onAnimationComplete, layout, layoutId, style, className, ...rest } = props;
977
+ return React.createElement(rest.as || 'div', { ref, style, className, ...rest }, rest.children);
978
+ });
979
+ const handler = { get: (_, name) => {
980
+ if (name === '__esModule') return true;
981
+ if (name === 'create') return () => new Proxy({}, handler);
982
+ return MotionComponent;
983
+ }};
917
984
  export const motion = new Proxy({}, handler);
918
- export const AnimatePresence = stub;
985
+ export const AnimatePresence = (props) => props.children || null;
986
+ export const useInView = () => true;
987
+ export const useAnimation = () => ({ start: () => {}, stop: () => {}, set: () => {} });
988
+ export const useMotionValue = (v) => ({ get: () => v, set: () => {}, onChange: () => () => {} });
989
+ export const useTransform = (v) => v;
990
+ export const useScroll = () => ({ scrollY: { get: () => 0, onChange: () => () => {} }, scrollYProgress: { get: () => 0, onChange: () => () => {} } });
919
991
  export default { motion, AnimatePresence };
920
992
  `.trim(),
921
993
  loader: "jsx"
@@ -938,12 +1010,26 @@ export default { motion, AnimatePresence };
938
1010
  build2.onLoad({ filter: /.*/, namespace: "next-stub" }, (args) => {
939
1011
  const stubs = {
940
1012
  "next/image": `
941
- const Image = (props) => {
942
- const { src, alt, width, height, fill, priority, ...rest } = props;
943
- const imgSrc = typeof src === 'object' ? src.src : src;
944
- return React.createElement('img', { src: imgSrc, alt, width: fill ? undefined : width, height: fill ? undefined : height, loading: priority ? 'eager' : 'lazy', ...rest });
945
- };
946
1013
  import React from 'react';
1014
+ const Image = React.forwardRef((props, ref) => {
1015
+ const { src, alt, width, height, fill, priority, sizes, quality, placeholder, blurDataURL, onLoad, onError, style, className, ...rest } = props;
1016
+ const imgSrc = typeof src === 'object' ? src.src : src;
1017
+ const fillStyle = fill ? { position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: style?.objectFit || 'cover', display: 'block' } : {};
1018
+ const mergedStyle = { ...fillStyle, ...style };
1019
+ return React.createElement('img', {
1020
+ ref,
1021
+ src: imgSrc,
1022
+ alt,
1023
+ width: fill ? undefined : width,
1024
+ height: fill ? undefined : height,
1025
+ loading: priority ? 'eager' : 'lazy',
1026
+ style: Object.keys(mergedStyle).length > 0 ? mergedStyle : undefined,
1027
+ className,
1028
+ onLoad,
1029
+ onError,
1030
+ ...rest,
1031
+ });
1032
+ });
947
1033
  export default Image;
948
1034
  `,
949
1035
  "next/link": `
@@ -1428,45 +1514,20 @@ async function initCommand(projectName, options = {}) {
1428
1514
  try {
1429
1515
  fs2.mkdirSync(projectPath, { recursive: true });
1430
1516
  await copyTemplate(template, projectPath, data);
1431
- const srcPath = path7.join(projectPath, "src");
1432
- fs2.mkdirSync(srcPath, { recursive: true });
1433
- const manifestContent = generateManifest(data);
1434
- await writeFile(path7.join(srcPath, "manifest.ts"), manifestContent);
1435
- const configContent = generateThemeConfig(data);
1436
- await writeFile(path7.join(srcPath, "config.ts"), configContent);
1437
- const layoutContent = generateThemeLayout(data);
1438
- await writeFile(path7.join(srcPath, "layout.ts"), layoutContent);
1439
- const indexContent = generateThemeIndex(data);
1440
- await writeFile(path7.join(srcPath, "index.ts"), indexContent);
1441
- const sectionsPath = path7.join(srcPath, "sections");
1442
- fs2.mkdirSync(sectionsPath, { recursive: true });
1443
- await writeFile(
1444
- path7.join(sectionsPath, "README.md"),
1445
- `# ${displayName} Sections
1446
-
1447
- Add your theme-specific sections here.
1448
- `
1449
- );
1450
- const blocksPath = path7.join(srcPath, "blocks");
1451
- fs2.mkdirSync(blocksPath, { recursive: true });
1452
- await writeFile(
1453
- path7.join(blocksPath, "README.md"),
1454
- `# ${displayName} Blocks
1455
-
1456
- Add your theme-specific blocks here.
1457
- `
1517
+ await renameThemeInFiles(
1518
+ projectPath,
1519
+ name,
1520
+ displayName,
1521
+ description,
1522
+ author
1458
1523
  );
1459
- const pagesPath = path7.join(srcPath, "pages");
1460
- fs2.mkdirSync(pagesPath, { recursive: true });
1461
- const homePageContent = generateHomePage(data);
1462
- await writeFile(path7.join(pagesPath, "home.ts"), homePageContent);
1463
1524
  logger.stopSpinner(true, "Project structure created!");
1464
1525
  if (options.git) {
1465
1526
  logger.startSpinner("Initializing git repository...");
1466
1527
  try {
1467
1528
  execSync("git init", { cwd: projectPath, stdio: "ignore" });
1468
1529
  execSync("git add .", { cwd: projectPath, stdio: "ignore" });
1469
- execSync('git commit -m "Initial commit from onex init"', {
1530
+ execSync('git commit -m "Initial commit from onexthm init"', {
1470
1531
  cwd: projectPath,
1471
1532
  stdio: "ignore"
1472
1533
  });
@@ -1503,14 +1564,14 @@ Add your theme-specific blocks here.
1503
1564
  logger.log(` npm run dev # Start development mode`);
1504
1565
  logger.newLine();
1505
1566
  logger.section("Theme structure:");
1506
- logger.log(" src/manifest.ts - Theme manifest and exports");
1567
+ logger.log(" bundle-entry.ts - Theme manifest and exports");
1507
1568
  logger.log(
1508
- " src/config.ts - Design tokens (colors, typography, etc.)"
1569
+ " theme.config.ts - Design tokens (colors, typography, etc.)"
1509
1570
  );
1510
- logger.log(" src/layout.ts - Header and footer configuration");
1511
- logger.log(" src/sections/ - Custom sections for your theme");
1512
- logger.log(" src/blocks/ - Reusable blocks");
1513
- logger.log(" src/pages/ - Page configurations");
1571
+ logger.log(" theme.layout.ts - Header and footer configuration");
1572
+ logger.log(" sections/ - Custom sections for your theme");
1573
+ logger.log(" pages/ - Page configurations");
1574
+ logger.log(" CLAUDE.md - AI assistant context");
1514
1575
  logger.newLine();
1515
1576
  logger.success(`Happy theming! \u{1F3A8}`);
1516
1577
  } catch (error) {
@@ -1524,231 +1585,33 @@ Add your theme-specific blocks here.
1524
1585
  process.exit(1);
1525
1586
  }
1526
1587
  }
1527
- function generateManifest(data) {
1528
- return `import type { ThemeExport } from "@onexapis/core";
1529
-
1530
- /**
1531
- * ${data.displayName} Theme Manifest
1532
- * ${data.description}
1533
- */
1534
- export const manifest: ThemeExport = {
1535
- id: "${data.themeName}",
1536
- name: "${data.displayName}",
1537
- description: "${data.description}",
1538
- version: "1.0.0",
1539
- author: "${data.author}",
1540
-
1541
- // Theme configuration
1542
- config: () => import("./config").then((m) => m.themeConfig),
1543
-
1544
- // Theme layout (header/footer sections)
1545
- layout: () => import("./layout").then((m) => m.themeLayout),
1546
-
1547
- // Available sections in this theme
1548
- sections: {
1549
- // Example: hero: () => import("./sections/hero").then((m) => m.heroSchema),
1550
- },
1551
-
1552
- // Available blocks in this theme
1553
- blocks: {
1554
- // Example: productCard: () => import("./blocks/product-card").then((m) => m.productCardDefinition),
1555
- },
1556
-
1557
- // Default pages
1558
- pages: {
1559
- home: () => import("./pages/home").then((m) => m.homePageConfig),
1560
- },
1561
-
1562
- // Supported page types
1563
- supportedPageTypes: ["home", "about", "contact", "custom"],
1564
-
1565
- // Preview image (optional)
1566
- preview: undefined,
1567
-
1568
- // Tags for categorization (optional)
1569
- tags: ["custom"],
1570
- };
1571
-
1572
- export default manifest;
1573
- `;
1574
- }
1575
- function generateThemeConfig(data) {
1576
- return `import type { ThemeConfig } from "@onexapis/core";
1577
-
1578
- /**
1579
- * ${data.displayName} Theme Configuration
1580
- * Design tokens: colors, typography, spacing, etc.
1581
- */
1582
- export const themeConfig: ThemeConfig = {
1583
- // Color palette
1584
- colors: {
1585
- primary: {
1586
- 50: "#eff6ff",
1587
- 100: "#dbeafe",
1588
- 200: "#bfdbfe",
1589
- 300: "#93c5fd",
1590
- 400: "#60a5fa",
1591
- 500: "#3b82f6",
1592
- 600: "#2563eb",
1593
- 700: "#1d4ed8",
1594
- 800: "#1e40af",
1595
- 900: "#1e3a8a",
1596
- },
1597
- secondary: {
1598
- 50: "#f8fafc",
1599
- 100: "#f1f5f9",
1600
- 200: "#e2e8f0",
1601
- 300: "#cbd5e1",
1602
- 400: "#94a3b8",
1603
- 500: "#64748b",
1604
- 600: "#475569",
1605
- 700: "#334155",
1606
- 800: "#1e293b",
1607
- 900: "#0f172a",
1608
- },
1609
- accent: {
1610
- 50: "#fdf4ff",
1611
- 100: "#fae8ff",
1612
- 200: "#f5d0fe",
1613
- 300: "#f0abfc",
1614
- 400: "#e879f9",
1615
- 500: "#d946ef",
1616
- 600: "#c026d3",
1617
- 700: "#a21caf",
1618
- 800: "#86198f",
1619
- 900: "#701a75",
1620
- },
1621
- },
1622
-
1623
- // Typography
1624
- typography: {
1625
- fontFamily: {
1626
- sans: ["Inter", "system-ui", "sans-serif"],
1627
- serif: ["Georgia", "serif"],
1628
- mono: ["Monaco", "monospace"],
1629
- },
1630
- fontSize: {
1631
- xs: "0.75rem",
1632
- sm: "0.875rem",
1633
- base: "1rem",
1634
- lg: "1.125rem",
1635
- xl: "1.25rem",
1636
- "2xl": "1.5rem",
1637
- "3xl": "1.875rem",
1638
- "4xl": "2.25rem",
1639
- "5xl": "3rem",
1640
- },
1641
- },
1642
-
1643
- // Spacing
1644
- spacing: {
1645
- xs: "0.5rem",
1646
- sm: "1rem",
1647
- md: "1.5rem",
1648
- lg: "2rem",
1649
- xl: "3rem",
1650
- "2xl": "4rem",
1651
- "3xl": "6rem",
1652
- "4xl": "8rem",
1653
- },
1654
-
1655
- // Border radius
1656
- borderRadius: {
1657
- none: "0",
1658
- sm: "0.125rem",
1659
- md: "0.375rem",
1660
- lg: "0.5rem",
1661
- xl: "0.75rem",
1662
- full: "9999px",
1663
- },
1664
-
1665
- // Breakpoints
1666
- breakpoints: {
1667
- sm: "640px",
1668
- md: "768px",
1669
- lg: "1024px",
1670
- xl: "1280px",
1671
- "2xl": "1536px",
1672
- },
1673
- };
1674
- `;
1675
- }
1676
- function generateThemeLayout(data) {
1677
- return `import type { ThemeLayoutConfig } from "@onexapis/core";
1678
-
1679
- /**
1680
- * ${data.themeName} Theme Layout
1681
- * Define header and footer sections
1682
- */
1683
- export const themeLayout: ThemeLayoutConfig = {
1684
- // Header section configuration
1685
- header: undefined,
1686
- // Example:
1687
- // header: {
1688
- // type: "header",
1689
- // template: "default",
1690
- // enabled: true,
1691
- // settings: {},
1692
- // },
1693
-
1694
- // Footer section configuration
1695
- footer: undefined,
1696
- // Example:
1697
- // footer: {
1698
- // type: "footer",
1699
- // template: "default",
1700
- // enabled: true,
1701
- // settings: {},
1702
- // },
1703
- };
1704
- `;
1705
- }
1706
- function generateThemeIndex(data) {
1707
- return `/**
1708
- * ${data.themeNamePascal} Theme
1709
- */
1710
-
1711
- export { manifest as ${data.themeNamePascal}Manifest } from "./manifest";
1712
- export { themeConfig as ${data.themeNamePascal}Config } from "./config";
1713
- export { themeLayout as ${data.themeNamePascal}Layout } from "./layout";
1714
- `;
1715
- }
1716
- function generateHomePage(data) {
1717
- return `import type { PageConfig } from "@onexapis/core";
1718
-
1719
- /**
1720
- * Home Page Configuration
1721
- */
1722
- export const homePageConfig: PageConfig = {
1723
- type: "home",
1724
- title: "${data.displayName}",
1725
- description: "Welcome to ${data.displayName}",
1726
-
1727
- // SEO metadata
1728
- seo: {
1729
- title: "${data.displayName} - Home",
1730
- description: "Welcome to ${data.displayName}",
1731
- keywords: [],
1732
- ogImage: undefined,
1733
- },
1734
-
1735
- // Page sections
1736
- sections: [
1737
- // Add your sections here
1738
- // Example:
1739
- // {
1740
- // id: "hero-1",
1741
- // type: "hero",
1742
- // template: "default",
1743
- // order: 0,
1744
- // enabled: true,
1745
- // settings: {},
1746
- // components: [],
1747
- // blocks: [],
1748
- // },
1749
- ],
1750
- };
1751
- `;
1588
+ async function renameThemeInFiles(projectPath, themeName, displayName, description, author) {
1589
+ const configPath = path7.join(projectPath, "theme.config.ts");
1590
+ if (fs2.existsSync(configPath)) {
1591
+ let content = fs2.readFileSync(configPath, "utf-8");
1592
+ content = content.replace(
1593
+ /name: "My Simple Theme"/,
1594
+ `name: "${displayName}"`
1595
+ );
1596
+ content = content.replace(
1597
+ /description: ".*?"/,
1598
+ `description: "${description}"`
1599
+ );
1600
+ fs2.writeFileSync(configPath, content, "utf-8");
1601
+ }
1602
+ const pkgPath = path7.join(projectPath, "package.json");
1603
+ if (fs2.existsSync(pkgPath)) {
1604
+ let content = fs2.readFileSync(pkgPath, "utf-8");
1605
+ content = content.replace(
1606
+ /@onex-themes\/my-simple/g,
1607
+ `@onex-themes/${themeName}`
1608
+ );
1609
+ content = content.replace(
1610
+ /"description": ".*?"/,
1611
+ `"description": "${description}"`
1612
+ );
1613
+ fs2.writeFileSync(pkgPath, content, "utf-8");
1614
+ }
1752
1615
  }
1753
1616
 
1754
1617
  // src/commands/create-section.ts
@@ -2634,7 +2497,7 @@ async function buildCommand(options) {
2634
2497
  logger.stopSpinner(true, "Lint passed");
2635
2498
  const pkgJson = fs.readJsonSync(packageJsonPath);
2636
2499
  const buildScript = pkgJson.scripts?.build || "";
2637
- const isRecursive = buildScript.includes("onex build") || buildScript.includes("onex-cli build");
2500
+ const isRecursive = buildScript.includes("onexthm build") || buildScript.includes("onex-cli build");
2638
2501
  logger.startSpinner(
2639
2502
  options.watch ? "Building (watch mode)..." : "Building..."
2640
2503
  );
@@ -2725,7 +2588,7 @@ function getBucketName(env) {
2725
2588
  return process.env.BUCKET_NAME;
2726
2589
  }
2727
2590
  const environment = env || process.env.ENVIRONMENT || "staging";
2728
- return environment === "production" ? "onex-themes-prod" : "onex-themes-staging";
2591
+ return environment === "production" ? "theme-s3-bucket" : "theme-s3-bucket";
2729
2592
  }
2730
2593
  async function findCompiledThemeDir(themeId, version) {
2731
2594
  const searchPaths = [path7.resolve(process.cwd(), "dist")];
@@ -2832,7 +2695,7 @@ async function uploadCommand(options) {
2832
2695
  if (!compiledDir) {
2833
2696
  spinner.fail(
2834
2697
  chalk4.red(
2835
- `Compiled theme not found for ${themeId}@${version}. Run 'onex build' first.`
2698
+ `Compiled theme not found for ${themeId}@${version}. Run 'onexthm build' first.`
2836
2699
  )
2837
2700
  );
2838
2701
  logger.info(chalk4.gray(`Expected location:
@@ -2994,7 +2857,7 @@ function getBucketName2(env) {
2994
2857
  return process.env.BUCKET_NAME;
2995
2858
  }
2996
2859
  const environment = env || process.env.ENVIRONMENT || "staging";
2997
- return environment === "production" ? "onex-themes-prod" : "onex-themes-staging";
2860
+ return environment === "production" ? "theme-s3-bucket" : "theme-s3-bucket";
2998
2861
  }
2999
2862
  async function streamToString(stream) {
3000
2863
  const chunks = [];
@@ -3064,7 +2927,7 @@ function showDownloadFailureHelp(themeId, bucket) {
3064
2927
  console.log(chalk4.white("1. Compile and upload the theme:"));
3065
2928
  console.log(chalk4.gray(` cd themes/${themeId}`));
3066
2929
  console.log(chalk4.gray(" pnpm build"));
3067
- console.log(chalk4.gray(" onex upload"));
2930
+ console.log(chalk4.gray(" onexthm upload"));
3068
2931
  console.log();
3069
2932
  console.log(chalk4.white("2. Verify AWS credentials are set:"));
3070
2933
  console.log(
@@ -3195,7 +3058,7 @@ function getBucketName3(env) {
3195
3058
  return process.env.BUCKET_NAME;
3196
3059
  }
3197
3060
  const environment = env || process.env.ENVIRONMENT || "staging";
3198
- return environment === "production" ? "onex-themes-prod" : "onex-themes-staging";
3061
+ return environment === "production" ? "theme-s3-bucket" : "theme-s3-bucket";
3199
3062
  }
3200
3063
  async function streamToString2(stream) {
3201
3064
  const chunks = [];
@@ -3366,7 +3229,7 @@ async function cloneCommand(themeName, options) {
3366
3229
  chalk4.yellow("The theme source may not have been uploaded yet.")
3367
3230
  );
3368
3231
  console.log(
3369
- chalk4.gray(`Upload source with: onex upload --theme ${themeName}`)
3232
+ chalk4.gray(`Upload source with: onexthm upload --theme ${themeName}`)
3370
3233
  );
3371
3234
  console.log();
3372
3235
  process.exit(1);
@@ -3393,7 +3256,7 @@ async function cloneCommand(themeName, options) {
3393
3256
  [
3394
3257
  "# API Configuration (enables real data in preview)",
3395
3258
  "# Get your Company ID from the OneX dashboard",
3396
- "NEXT_PUBLIC_API_URL=https://api-dev.onexeos.com",
3259
+ "NEXT_PUBLIC_API_URL=https://platform-dev.onexeos.com",
3397
3260
  "NEXT_PUBLIC_COMPANY_ID=",
3398
3261
  ""
3399
3262
  ].join("\n")
@@ -3435,7 +3298,7 @@ async function cloneCommand(themeName, options) {
3435
3298
  if (options.install === false) {
3436
3299
  console.log(chalk4.gray(" pnpm install"));
3437
3300
  }
3438
- console.log(chalk4.gray(" onex build"));
3301
+ console.log(chalk4.gray(" onexthm build"));
3439
3302
  console.log();
3440
3303
  } catch (error) {
3441
3304
  spinner.fail(chalk4.red(`Clone failed: ${error.message}`));