@onexapis/cli 1.1.38 → 1.1.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +384 -380
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +381 -376
- package/dist/cli.mjs.map +1 -1
- package/dist/index.js +258 -293
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +255 -289
- package/dist/index.mjs.map +1 -1
- package/dist/preview/preview-app.tsx +13 -5
- package/package.json +1 -3
- package/templates/default/AUTH_AND_PROFILE.md +167 -0
- package/templates/default/CLAUDE.md +334 -1
- package/templates/default/LAYOUT.md +195 -0
- package/templates/default/bundle-entry.ts +5 -0
- package/templates/default/esbuild.config.js +20 -0
- package/templates/default/hooks/index.ts +26 -0
- package/templates/default/hooks/use-forgot-password-form.ts +90 -0
- package/templates/default/hooks/use-login-form.ts +102 -0
- package/templates/default/hooks/use-profile-form.ts +255 -0
- package/templates/default/hooks/use-register-form.ts +154 -0
- package/templates/default/hooks/use-verify-code-form.ts +224 -0
- package/templates/default/index.ts +21 -1
- package/templates/default/pages/about.ts +2 -2
- package/templates/default/pages/forgot-password.ts +39 -0
- package/templates/default/pages/home.ts +4 -4
- package/templates/default/pages/login.ts +39 -0
- package/templates/default/pages/profile.ts +39 -0
- package/templates/default/pages/register.ts +39 -0
- package/templates/default/pages/showcase.ts +7 -7
- package/templates/default/pages/verify-code.ts +39 -0
- package/templates/default/sections/about/about.schema.ts +1 -1
- package/templates/default/sections/auth-forgot-password/auth-forgot-password-default.tsx +192 -0
- package/templates/default/sections/auth-forgot-password/auth-forgot-password.schema.ts +150 -0
- package/templates/default/sections/auth-forgot-password/index.ts +14 -0
- package/templates/default/sections/auth-login/auth-login-default.tsx +238 -0
- package/templates/default/sections/auth-login/auth-login.schema.ts +171 -0
- package/templates/default/sections/auth-login/index.ts +14 -0
- package/templates/default/sections/auth-register/auth-register-default.tsx +327 -0
- package/templates/default/sections/auth-register/auth-register.schema.ts +188 -0
- package/templates/default/sections/auth-register/index.ts +14 -0
- package/templates/default/sections/auth-verify-code/auth-verify-code-default.tsx +209 -0
- package/templates/default/sections/auth-verify-code/auth-verify-code.schema.ts +150 -0
- package/templates/default/sections/auth-verify-code/index.ts +14 -0
- package/templates/default/sections/cta/cta.schema.ts +1 -1
- package/templates/default/sections/features/features.schema.ts +1 -1
- package/templates/default/sections/footer/footer-default.tsx +214 -0
- package/templates/default/sections/footer/footer.schema.ts +170 -0
- package/templates/default/sections/footer/index.ts +14 -0
- package/templates/default/sections/gallery/gallery.schema.ts +1 -1
- package/templates/default/sections/header/header-default.tsx +322 -0
- package/templates/default/sections/header/header.schema.ts +168 -0
- package/templates/default/sections/header/index.ts +14 -0
- package/templates/default/sections/hero/hero.schema.ts +1 -1
- package/templates/default/sections/profile/index.ts +14 -0
- package/templates/default/sections/profile/profile-default.tsx +522 -0
- package/templates/default/sections/profile/profile.schema.ts +228 -0
- package/templates/default/sections/stats/stats.schema.ts +1 -1
- package/templates/default/sections/testimonials/testimonials.schema.ts +1 -1
- package/templates/default/sections-registry.ts +28 -0
- package/templates/default/theme.layout.ts +71 -2
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import chalk4 from 'chalk';
|
|
2
2
|
import ora from 'ora';
|
|
3
3
|
import * as esbuild from 'esbuild';
|
|
4
|
-
import
|
|
5
|
-
import
|
|
4
|
+
import path8 from 'path';
|
|
5
|
+
import fs7 from 'fs/promises';
|
|
6
6
|
import crypto from 'crypto';
|
|
7
7
|
import { glob } from 'glob';
|
|
8
8
|
import { createRequire } from 'module';
|
|
9
|
-
import
|
|
10
|
-
import
|
|
9
|
+
import fs3 from 'fs';
|
|
10
|
+
import { execSync, spawn } from 'child_process';
|
|
11
11
|
import inquirer from 'inquirer';
|
|
12
12
|
import fs from 'fs-extra';
|
|
13
13
|
import ejs from 'ejs';
|
|
@@ -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
|
-
|
|
106
|
-
|
|
105
|
+
path8.join(themePath, "sections/**/*.{ts,tsx}"),
|
|
106
|
+
path8.join(themePath, "components/**/*.{ts,tsx}")
|
|
107
107
|
],
|
|
108
108
|
theme: { extend: {} },
|
|
109
109
|
plugins: []
|
|
@@ -113,7 +113,7 @@ async function generateThemeCSS(themePath, outDir) {
|
|
|
113
113
|
inputCSS,
|
|
114
114
|
{ from: void 0 }
|
|
115
115
|
);
|
|
116
|
-
await
|
|
116
|
+
await fs7.writeFile(path8.join(outDir, "bundle.css"), result.css);
|
|
117
117
|
logger.info("Generated bundle.css");
|
|
118
118
|
} catch (err) {
|
|
119
119
|
logger.warning(
|
|
@@ -124,12 +124,12 @@ async function generateThemeCSS(themePath, outDir) {
|
|
|
124
124
|
async function resolveNodeModulesFile(startDir, relativePath) {
|
|
125
125
|
let dir = startDir;
|
|
126
126
|
while (true) {
|
|
127
|
-
const candidate =
|
|
127
|
+
const candidate = path8.join(dir, "node_modules", relativePath);
|
|
128
128
|
try {
|
|
129
|
-
await
|
|
129
|
+
await fs7.access(candidate);
|
|
130
130
|
return candidate;
|
|
131
131
|
} catch {
|
|
132
|
-
const parent =
|
|
132
|
+
const parent = path8.dirname(dir);
|
|
133
133
|
if (parent === dir) break;
|
|
134
134
|
dir = parent;
|
|
135
135
|
}
|
|
@@ -153,7 +153,7 @@ async function scanImportsFromPackage(sourceDir, packageName) {
|
|
|
153
153
|
});
|
|
154
154
|
for (const file of sourceFiles) {
|
|
155
155
|
try {
|
|
156
|
-
const content = await
|
|
156
|
+
const content = await fs7.readFile(path8.join(sourceDir, file), "utf-8");
|
|
157
157
|
for (const match of content.matchAll(namespaceImportRegex)) {
|
|
158
158
|
const subpath = match[1] ? match[1].slice(1) : "";
|
|
159
159
|
if (!result[subpath]) result[subpath] = /* @__PURE__ */ new Set();
|
|
@@ -207,17 +207,17 @@ function createCoreGlobalPlugin(themePath) {
|
|
|
207
207
|
const distFileName = subpath ? `${subpath}.mjs` : "index.mjs";
|
|
208
208
|
let distPath = await resolveNodeModulesFile(
|
|
209
209
|
themePath,
|
|
210
|
-
|
|
210
|
+
path8.join("@onexapis", "core", "dist", distFileName)
|
|
211
211
|
);
|
|
212
212
|
if (!distPath) {
|
|
213
213
|
distPath = await resolveNodeModulesFile(
|
|
214
214
|
__dirname,
|
|
215
|
-
|
|
215
|
+
path8.join("@onexapis", "core", "dist", distFileName)
|
|
216
216
|
);
|
|
217
217
|
}
|
|
218
218
|
try {
|
|
219
219
|
if (!distPath) throw new Error("not found");
|
|
220
|
-
const distContent = await
|
|
220
|
+
const distContent = await fs7.readFile(distPath, "utf-8");
|
|
221
221
|
const exportMatches = distContent.matchAll(/export\s*\{([^}]+)\}/g);
|
|
222
222
|
for (const m of exportMatches) {
|
|
223
223
|
const names = m[1].split(",").map((n) => {
|
|
@@ -446,7 +446,7 @@ async function generateThemeData(themePath, outputDir, themeId) {
|
|
|
446
446
|
const pages = {};
|
|
447
447
|
for (const ext of [".ts", ".js"]) {
|
|
448
448
|
try {
|
|
449
|
-
const mod = await jiti.import(
|
|
449
|
+
const mod = await jiti.import(path8.join(themePath, `theme.config${ext}`));
|
|
450
450
|
themeConfig = mod.default || mod;
|
|
451
451
|
break;
|
|
452
452
|
} catch {
|
|
@@ -454,20 +454,20 @@ async function generateThemeData(themePath, outputDir, themeId) {
|
|
|
454
454
|
}
|
|
455
455
|
for (const ext of [".ts", ".js"]) {
|
|
456
456
|
try {
|
|
457
|
-
const mod = await jiti.import(
|
|
457
|
+
const mod = await jiti.import(path8.join(themePath, `theme.layout${ext}`));
|
|
458
458
|
layoutConfig = mod.default || mod;
|
|
459
459
|
break;
|
|
460
460
|
} catch {
|
|
461
461
|
}
|
|
462
462
|
}
|
|
463
463
|
const schemas = {};
|
|
464
|
-
const sectionsDir =
|
|
464
|
+
const sectionsDir = path8.join(themePath, "sections");
|
|
465
465
|
try {
|
|
466
|
-
const sectionDirs = await
|
|
466
|
+
const sectionDirs = await fs7.readdir(sectionsDir);
|
|
467
467
|
for (const dir of sectionDirs) {
|
|
468
|
-
const schemaFile =
|
|
468
|
+
const schemaFile = path8.join(sectionsDir, dir, `${dir}.schema.ts`);
|
|
469
469
|
try {
|
|
470
|
-
await
|
|
470
|
+
await fs7.access(schemaFile);
|
|
471
471
|
const mod = await jiti.import(schemaFile);
|
|
472
472
|
for (const [key, value] of Object.entries(mod)) {
|
|
473
473
|
if (key.endsWith("Schema") && value && typeof value === "object" && value.type) {
|
|
@@ -479,14 +479,14 @@ async function generateThemeData(themePath, outputDir, themeId) {
|
|
|
479
479
|
}
|
|
480
480
|
} catch {
|
|
481
481
|
}
|
|
482
|
-
const pagesDir =
|
|
482
|
+
const pagesDir = path8.join(themePath, "pages");
|
|
483
483
|
try {
|
|
484
|
-
const files = await
|
|
484
|
+
const files = await fs7.readdir(pagesDir);
|
|
485
485
|
for (const file of files) {
|
|
486
486
|
if (!file.match(/\.(ts|js)$/)) continue;
|
|
487
487
|
const name = file.replace(/\.(ts|js)$/, "");
|
|
488
488
|
try {
|
|
489
|
-
const mod = await jiti.import(
|
|
489
|
+
const mod = await jiti.import(path8.join(pagesDir, file));
|
|
490
490
|
const config = mod.default || mod;
|
|
491
491
|
const sections = (config.sections || []).map((section) => {
|
|
492
492
|
const schema = schemas[section.type];
|
|
@@ -514,8 +514,8 @@ async function generateThemeData(themePath, outputDir, themeId) {
|
|
|
514
514
|
}
|
|
515
515
|
} catch {
|
|
516
516
|
}
|
|
517
|
-
await
|
|
518
|
-
|
|
517
|
+
await fs7.writeFile(
|
|
518
|
+
path8.join(outputDir, "theme-data.json"),
|
|
519
519
|
JSON.stringify(
|
|
520
520
|
{
|
|
521
521
|
themeId,
|
|
@@ -538,36 +538,36 @@ async function generateThemeData(themePath, outputDir, themeId) {
|
|
|
538
538
|
logger.info(`Generated theme-data.json (${Object.keys(pages).length} pages)`);
|
|
539
539
|
}
|
|
540
540
|
async function contentHashEntry(outputDir) {
|
|
541
|
-
const entryPath =
|
|
542
|
-
const mapPath =
|
|
541
|
+
const entryPath = path8.join(outputDir, "bundle-entry.js");
|
|
542
|
+
const mapPath = path8.join(outputDir, "bundle-entry.js.map");
|
|
543
543
|
const oldFiles = await glob("bundle-entry-*.js*", { cwd: outputDir });
|
|
544
544
|
for (const f of oldFiles) {
|
|
545
|
-
await
|
|
545
|
+
await fs7.unlink(path8.join(outputDir, f));
|
|
546
546
|
}
|
|
547
547
|
let entryContent;
|
|
548
548
|
try {
|
|
549
|
-
entryContent = await
|
|
549
|
+
entryContent = await fs7.readFile(entryPath, "utf-8");
|
|
550
550
|
} catch {
|
|
551
|
-
const indexPath =
|
|
551
|
+
const indexPath = path8.join(outputDir, "index.js");
|
|
552
552
|
try {
|
|
553
|
-
entryContent = await
|
|
553
|
+
entryContent = await fs7.readFile(indexPath, "utf-8");
|
|
554
554
|
} catch {
|
|
555
555
|
logger.warning("No entry file found in output, skipping content hash");
|
|
556
556
|
return;
|
|
557
557
|
}
|
|
558
558
|
const hash2 = crypto.createHash("sha256").update(entryContent).digest("hex").slice(0, 8);
|
|
559
559
|
const hashedName2 = `bundle-entry-${hash2}.js`;
|
|
560
|
-
const indexMapPath =
|
|
560
|
+
const indexMapPath = path8.join(outputDir, "index.js.map");
|
|
561
561
|
const hashedMapName2 = `bundle-entry-${hash2}.js.map`;
|
|
562
562
|
entryContent = entryContent.replace(
|
|
563
563
|
/\/\/# sourceMappingURL=index\.js\.map/,
|
|
564
564
|
`//# sourceMappingURL=${hashedMapName2}`
|
|
565
565
|
);
|
|
566
|
-
await
|
|
567
|
-
await
|
|
566
|
+
await fs7.writeFile(path8.join(outputDir, hashedName2), entryContent);
|
|
567
|
+
await fs7.unlink(indexPath);
|
|
568
568
|
try {
|
|
569
|
-
await
|
|
570
|
-
await
|
|
569
|
+
await fs7.access(indexMapPath);
|
|
570
|
+
await fs7.rename(indexMapPath, path8.join(outputDir, hashedMapName2));
|
|
571
571
|
} catch {
|
|
572
572
|
}
|
|
573
573
|
logger.info(`Entry hashed: ${hashedName2}`);
|
|
@@ -580,11 +580,11 @@ async function contentHashEntry(outputDir) {
|
|
|
580
580
|
/\/\/# sourceMappingURL=bundle-entry\.js\.map/,
|
|
581
581
|
`//# sourceMappingURL=${hashedMapName}`
|
|
582
582
|
);
|
|
583
|
-
await
|
|
584
|
-
await
|
|
583
|
+
await fs7.writeFile(path8.join(outputDir, hashedName), entryContent);
|
|
584
|
+
await fs7.unlink(entryPath);
|
|
585
585
|
try {
|
|
586
|
-
await
|
|
587
|
-
await
|
|
586
|
+
await fs7.access(mapPath);
|
|
587
|
+
await fs7.rename(mapPath, path8.join(outputDir, hashedMapName));
|
|
588
588
|
} catch {
|
|
589
589
|
}
|
|
590
590
|
logger.info(`Entry hashed: ${hashedName}`);
|
|
@@ -596,7 +596,7 @@ async function extractDataRequirements(themePath) {
|
|
|
596
596
|
const requirements = {};
|
|
597
597
|
for (const file of schemaFiles) {
|
|
598
598
|
try {
|
|
599
|
-
const mod = await jiti.import(
|
|
599
|
+
const mod = await jiti.import(path8.join(themePath, file));
|
|
600
600
|
const exports$1 = mod;
|
|
601
601
|
for (const value of Object.values(exports$1)) {
|
|
602
602
|
if (value && typeof value === "object" && typeof value.type === "string" && value.dataRequirements && typeof value.dataRequirements === "object") {
|
|
@@ -615,8 +615,8 @@ async function generateManifest(themeName, themePath, outputDir) {
|
|
|
615
615
|
let version = "1.0.0";
|
|
616
616
|
let themeId = themeName;
|
|
617
617
|
try {
|
|
618
|
-
const pkgContent = await
|
|
619
|
-
|
|
618
|
+
const pkgContent = await fs7.readFile(
|
|
619
|
+
path8.join(themePath, "package.json"),
|
|
620
620
|
"utf-8"
|
|
621
621
|
);
|
|
622
622
|
const pkg = JSON.parse(pkgContent);
|
|
@@ -634,7 +634,7 @@ async function generateManifest(themeName, themePath, outputDir) {
|
|
|
634
634
|
const dataRequirements = await extractDataRequirements(themePath);
|
|
635
635
|
let hasThemeConfig = false;
|
|
636
636
|
try {
|
|
637
|
-
await
|
|
637
|
+
await fs7.access(path8.join(themePath, "theme.config.ts"));
|
|
638
638
|
hasThemeConfig = true;
|
|
639
639
|
} catch {
|
|
640
640
|
}
|
|
@@ -675,24 +675,24 @@ async function generateManifest(themeName, themePath, outputDir) {
|
|
|
675
675
|
// Section data requirements for server-side prefetching (keyed by section type)
|
|
676
676
|
dataRequirements
|
|
677
677
|
};
|
|
678
|
-
await
|
|
679
|
-
|
|
678
|
+
await fs7.writeFile(
|
|
679
|
+
path8.join(outputDir, "manifest.json"),
|
|
680
680
|
JSON.stringify(manifest, null, 2)
|
|
681
681
|
);
|
|
682
682
|
}
|
|
683
683
|
async function compileStandaloneTheme(themePath, themeName) {
|
|
684
|
-
const outputDir =
|
|
685
|
-
const bundleEntry =
|
|
686
|
-
const indexEntry =
|
|
684
|
+
const outputDir = path8.join(themePath, "dist");
|
|
685
|
+
const bundleEntry = path8.join(themePath, "bundle-entry.ts");
|
|
686
|
+
const indexEntry = path8.join(themePath, "index.ts");
|
|
687
687
|
let entryPoint = indexEntry;
|
|
688
688
|
try {
|
|
689
|
-
await
|
|
689
|
+
await fs7.access(bundleEntry);
|
|
690
690
|
entryPoint = bundleEntry;
|
|
691
691
|
} catch {
|
|
692
692
|
}
|
|
693
|
-
const shimPath =
|
|
694
|
-
await
|
|
695
|
-
await
|
|
693
|
+
const shimPath = path8.join(outputDir, ".process-shim.js");
|
|
694
|
+
await fs7.mkdir(outputDir, { recursive: true });
|
|
695
|
+
await fs7.writeFile(shimPath, PROCESS_SHIM);
|
|
696
696
|
const buildOptions = {
|
|
697
697
|
entryPoints: [entryPoint],
|
|
698
698
|
bundle: true,
|
|
@@ -742,7 +742,7 @@ async function compileStandaloneTheme(themePath, themeName) {
|
|
|
742
742
|
try {
|
|
743
743
|
const result = await esbuild.build(buildOptions);
|
|
744
744
|
try {
|
|
745
|
-
await
|
|
745
|
+
await fs7.unlink(shimPath);
|
|
746
746
|
} catch {
|
|
747
747
|
}
|
|
748
748
|
await contentHashEntry(outputDir);
|
|
@@ -761,7 +761,7 @@ async function compileStandaloneTheme(themePath, themeName) {
|
|
|
761
761
|
return true;
|
|
762
762
|
} catch (error) {
|
|
763
763
|
try {
|
|
764
|
-
await
|
|
764
|
+
await fs7.unlink(shimPath);
|
|
765
765
|
} catch {
|
|
766
766
|
}
|
|
767
767
|
logger.error(`esbuild compilation failed: ${error}`);
|
|
@@ -769,18 +769,18 @@ async function compileStandaloneTheme(themePath, themeName) {
|
|
|
769
769
|
}
|
|
770
770
|
}
|
|
771
771
|
async function compileStandaloneThemeDev(themePath, themeName) {
|
|
772
|
-
const outputDir =
|
|
773
|
-
const bundleEntry =
|
|
774
|
-
const indexEntry =
|
|
772
|
+
const outputDir = path8.join(themePath, "dist");
|
|
773
|
+
const bundleEntry = path8.join(themePath, "bundle-entry.ts");
|
|
774
|
+
const indexEntry = path8.join(themePath, "index.ts");
|
|
775
775
|
let entryPoint = indexEntry;
|
|
776
776
|
try {
|
|
777
|
-
await
|
|
777
|
+
await fs7.access(bundleEntry);
|
|
778
778
|
entryPoint = bundleEntry;
|
|
779
779
|
} catch {
|
|
780
780
|
}
|
|
781
|
-
const shimPath =
|
|
782
|
-
await
|
|
783
|
-
await
|
|
781
|
+
const shimPath = path8.join(outputDir, ".process-shim.js");
|
|
782
|
+
await fs7.mkdir(outputDir, { recursive: true });
|
|
783
|
+
await fs7.writeFile(shimPath, PROCESS_SHIM);
|
|
784
784
|
const buildOptions = {
|
|
785
785
|
entryPoints: [entryPoint],
|
|
786
786
|
bundle: true,
|
|
@@ -833,18 +833,18 @@ async function compileStandaloneThemeDev(themePath, themeName) {
|
|
|
833
833
|
return { context: context2, outputDir };
|
|
834
834
|
}
|
|
835
835
|
async function compilePreviewRuntime(themePath) {
|
|
836
|
-
const outputDir =
|
|
837
|
-
await
|
|
838
|
-
const outputPath =
|
|
836
|
+
const outputDir = path8.join(themePath, "dist");
|
|
837
|
+
await fs7.mkdir(outputDir, { recursive: true });
|
|
838
|
+
const outputPath = path8.join(outputDir, "preview-runtime.js");
|
|
839
839
|
const locations = [
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
840
|
+
path8.join(__dirname, "..", "preview", "preview-app.tsx"),
|
|
841
|
+
path8.join(__dirname, "preview", "preview-app.tsx"),
|
|
842
|
+
path8.join(__dirname, "..", "..", "src", "preview", "preview-app.tsx")
|
|
843
843
|
];
|
|
844
844
|
let previewEntryPath = null;
|
|
845
845
|
for (const loc of locations) {
|
|
846
846
|
try {
|
|
847
|
-
await
|
|
847
|
+
await fs7.access(loc);
|
|
848
848
|
previewEntryPath = loc;
|
|
849
849
|
break;
|
|
850
850
|
} catch {
|
|
@@ -927,10 +927,10 @@ ${locations.join("\n")}`
|
|
|
927
927
|
if (!lucideScanned) {
|
|
928
928
|
lucideScanned = true;
|
|
929
929
|
const coreSrcCandidates = [
|
|
930
|
-
|
|
931
|
-
|
|
930
|
+
path8.join(themePath, "node_modules", "@onexapis", "core", "src"),
|
|
931
|
+
path8.join(themePath, "..", "..", "packages", "core", "src"),
|
|
932
932
|
// monorepo sibling
|
|
933
|
-
|
|
933
|
+
path8.join(
|
|
934
934
|
__dirname,
|
|
935
935
|
"..",
|
|
936
936
|
"..",
|
|
@@ -945,7 +945,7 @@ ${locations.join("\n")}`
|
|
|
945
945
|
let coreSourceDir = null;
|
|
946
946
|
for (const candidate of coreSrcCandidates) {
|
|
947
947
|
try {
|
|
948
|
-
await
|
|
948
|
+
await fs7.access(candidate);
|
|
949
949
|
coreSourceDir = candidate;
|
|
950
950
|
break;
|
|
951
951
|
} catch {
|
|
@@ -964,21 +964,21 @@ ${locations.join("\n")}`
|
|
|
964
964
|
}
|
|
965
965
|
} else {
|
|
966
966
|
const coreDistCandidates = [
|
|
967
|
-
|
|
967
|
+
path8.join(themePath, "node_modules", "@onexapis", "core", "dist")
|
|
968
968
|
];
|
|
969
969
|
const resolvedDist = await resolveNodeModulesFile(
|
|
970
970
|
__dirname,
|
|
971
|
-
|
|
971
|
+
path8.join("@onexapis", "core", "dist")
|
|
972
972
|
);
|
|
973
973
|
if (resolvedDist) coreDistCandidates.push(resolvedDist);
|
|
974
974
|
for (const candidate of coreDistCandidates) {
|
|
975
975
|
try {
|
|
976
|
-
await
|
|
976
|
+
await fs7.access(candidate);
|
|
977
977
|
const mjsFiles = await glob("*.mjs", { cwd: candidate });
|
|
978
978
|
const importRegex = /import\s*\{([^}]+)\}\s*from\s*["']lucide-react["']/g;
|
|
979
979
|
for (const file of mjsFiles) {
|
|
980
|
-
const content = await
|
|
981
|
-
|
|
980
|
+
const content = await fs7.readFile(
|
|
981
|
+
path8.join(candidate, file),
|
|
982
982
|
"utf-8"
|
|
983
983
|
);
|
|
984
984
|
for (const match of content.matchAll(importRegex)) {
|
|
@@ -1033,7 +1033,7 @@ export default new Proxy({}, { get: (_, name) => name === '__esModule' ? true :
|
|
|
1033
1033
|
const req = createRequire(import.meta.url || __filename);
|
|
1034
1034
|
const cjsPath = req.resolve("framer-motion");
|
|
1035
1035
|
const pkgDir = cjsPath.replace(/[/\\]dist[/\\].*$/, "");
|
|
1036
|
-
const esmEntry =
|
|
1036
|
+
const esmEntry = path8.join(pkgDir, "dist", "es", "index.mjs");
|
|
1037
1037
|
const { existsSync } = await import('fs');
|
|
1038
1038
|
if (existsSync(esmEntry)) {
|
|
1039
1039
|
return { path: esmEntry, namespace: "file" };
|
|
@@ -1132,8 +1132,8 @@ export function headers() { return new Headers(); }
|
|
|
1132
1132
|
});
|
|
1133
1133
|
}
|
|
1134
1134
|
};
|
|
1135
|
-
const shimPath =
|
|
1136
|
-
await
|
|
1135
|
+
const shimPath = path8.join(outputDir, ".process-shim-preview.js");
|
|
1136
|
+
await fs7.writeFile(shimPath, PROCESS_SHIM);
|
|
1137
1137
|
await esbuild.build({
|
|
1138
1138
|
entryPoints: [previewEntryPath],
|
|
1139
1139
|
bundle: true,
|
|
@@ -1168,7 +1168,7 @@ export function headers() { return new Headers(); }
|
|
|
1168
1168
|
}
|
|
1169
1169
|
});
|
|
1170
1170
|
try {
|
|
1171
|
-
await
|
|
1171
|
+
await fs7.unlink(shimPath);
|
|
1172
1172
|
} catch {
|
|
1173
1173
|
}
|
|
1174
1174
|
return outputPath;
|
|
@@ -1315,8 +1315,8 @@ function validateThemeName(name) {
|
|
|
1315
1315
|
return /^[a-z][a-z0-9-]*$/.test(name);
|
|
1316
1316
|
}
|
|
1317
1317
|
function pathExists(filePath) {
|
|
1318
|
-
const
|
|
1319
|
-
return
|
|
1318
|
+
const fs12 = __require("fs-extra");
|
|
1319
|
+
return fs12.existsSync(filePath);
|
|
1320
1320
|
}
|
|
1321
1321
|
function validateCategory(category) {
|
|
1322
1322
|
const validCategories = [
|
|
@@ -1357,18 +1357,18 @@ async function renderTemplate(templatePath, data) {
|
|
|
1357
1357
|
return ejs.render(template, data);
|
|
1358
1358
|
}
|
|
1359
1359
|
async function writeFile(filePath, content) {
|
|
1360
|
-
await fs.ensureDir(
|
|
1360
|
+
await fs.ensureDir(path8.dirname(filePath));
|
|
1361
1361
|
await fs.writeFile(filePath, content, "utf-8");
|
|
1362
1362
|
}
|
|
1363
1363
|
function getTemplatesDir() {
|
|
1364
1364
|
const locations = [
|
|
1365
|
-
|
|
1365
|
+
path8.join(__dirname, "../../templates"),
|
|
1366
1366
|
// Development
|
|
1367
|
-
|
|
1367
|
+
path8.join(__dirname, "../templates"),
|
|
1368
1368
|
// Production (dist/)
|
|
1369
|
-
|
|
1369
|
+
path8.join(process.cwd(), "templates"),
|
|
1370
1370
|
// Fallback
|
|
1371
|
-
|
|
1371
|
+
path8.join(process.cwd(), "packages/cli/templates")
|
|
1372
1372
|
// Monorepo
|
|
1373
1373
|
];
|
|
1374
1374
|
for (const location of locations) {
|
|
@@ -1380,7 +1380,7 @@ function getTemplatesDir() {
|
|
|
1380
1380
|
}
|
|
1381
1381
|
async function copyTemplate(templateName, targetDir, data) {
|
|
1382
1382
|
const templatesDir = getTemplatesDir();
|
|
1383
|
-
const templateDir =
|
|
1383
|
+
const templateDir = path8.join(templatesDir, templateName);
|
|
1384
1384
|
if (!fs.existsSync(templateDir)) {
|
|
1385
1385
|
throw new Error(
|
|
1386
1386
|
`Template "${templateName}" not found at ${templateDir}. Available templates: ${fs.readdirSync(templatesDir).join(", ")}`
|
|
@@ -1389,8 +1389,8 @@ async function copyTemplate(templateName, targetDir, data) {
|
|
|
1389
1389
|
await fs.ensureDir(targetDir);
|
|
1390
1390
|
const files = await fs.readdir(templateDir);
|
|
1391
1391
|
for (const file of files) {
|
|
1392
|
-
const templatePath =
|
|
1393
|
-
const targetPath =
|
|
1392
|
+
const templatePath = path8.join(templateDir, file);
|
|
1393
|
+
const targetPath = path8.join(targetDir, file);
|
|
1394
1394
|
const stat = await fs.stat(templatePath);
|
|
1395
1395
|
if (stat.isDirectory()) {
|
|
1396
1396
|
await copyTemplateDir(templatePath, targetPath, data);
|
|
@@ -1407,8 +1407,8 @@ async function copyTemplateDir(templateDir, targetDir, data) {
|
|
|
1407
1407
|
await fs.ensureDir(targetDir);
|
|
1408
1408
|
const files = await fs.readdir(templateDir);
|
|
1409
1409
|
for (const file of files) {
|
|
1410
|
-
const templatePath =
|
|
1411
|
-
const targetPath =
|
|
1410
|
+
const templatePath = path8.join(templateDir, file);
|
|
1411
|
+
const targetPath = path8.join(targetDir, file);
|
|
1412
1412
|
const stat = await fs.stat(templatePath);
|
|
1413
1413
|
if (stat.isDirectory()) {
|
|
1414
1414
|
await copyTemplateDir(templatePath, targetPath, data);
|
|
@@ -1423,32 +1423,32 @@ async function copyTemplateDir(templateDir, targetDir, data) {
|
|
|
1423
1423
|
}
|
|
1424
1424
|
function getProjectRoot() {
|
|
1425
1425
|
let currentDir = process.cwd();
|
|
1426
|
-
while (currentDir !==
|
|
1427
|
-
const packageJsonPath =
|
|
1426
|
+
while (currentDir !== path8.parse(currentDir).root) {
|
|
1427
|
+
const packageJsonPath = path8.join(currentDir, "package.json");
|
|
1428
1428
|
if (fs.existsSync(packageJsonPath)) {
|
|
1429
1429
|
const packageJson = fs.readJsonSync(packageJsonPath);
|
|
1430
|
-
if (packageJson.workspaces || fs.existsSync(
|
|
1430
|
+
if (packageJson.workspaces || fs.existsSync(path8.join(currentDir, "src/themes")) || fs.existsSync(path8.join(currentDir, "themes"))) {
|
|
1431
1431
|
return currentDir;
|
|
1432
1432
|
}
|
|
1433
1433
|
}
|
|
1434
|
-
currentDir =
|
|
1434
|
+
currentDir = path8.dirname(currentDir);
|
|
1435
1435
|
}
|
|
1436
1436
|
return process.cwd();
|
|
1437
1437
|
}
|
|
1438
1438
|
function getThemesDir() {
|
|
1439
1439
|
const root = getProjectRoot();
|
|
1440
|
-
if (fs.existsSync(
|
|
1441
|
-
return
|
|
1442
|
-
if (fs.existsSync(
|
|
1443
|
-
return
|
|
1444
|
-
return
|
|
1440
|
+
if (fs.existsSync(path8.join(root, "themes")))
|
|
1441
|
+
return path8.join(root, "themes");
|
|
1442
|
+
if (fs.existsSync(path8.join(root, "src/themes")))
|
|
1443
|
+
return path8.join(root, "src/themes");
|
|
1444
|
+
return path8.dirname(root);
|
|
1445
1445
|
}
|
|
1446
1446
|
function getFeaturesDir() {
|
|
1447
|
-
return
|
|
1447
|
+
return path8.join(getProjectRoot(), "src/features");
|
|
1448
1448
|
}
|
|
1449
1449
|
function isOneXProject() {
|
|
1450
1450
|
const root = getProjectRoot();
|
|
1451
|
-
return fs.existsSync(
|
|
1451
|
+
return fs.existsSync(path8.join(root, "themes")) || fs.existsSync(path8.join(root, "src/themes")) || fs.existsSync(path8.join(root, "theme.config.ts")) || fs.existsSync(path8.join(root, "bundle-entry.ts"));
|
|
1452
1452
|
}
|
|
1453
1453
|
function ensureOneXProject() {
|
|
1454
1454
|
if (!isOneXProject()) {
|
|
@@ -1464,13 +1464,13 @@ function listThemes() {
|
|
|
1464
1464
|
return [];
|
|
1465
1465
|
}
|
|
1466
1466
|
return fs.readdirSync(themesDir).filter((name) => {
|
|
1467
|
-
const themePath =
|
|
1468
|
-
return fs.statSync(themePath).isDirectory() && (fs.existsSync(
|
|
1467
|
+
const themePath = path8.join(themesDir, name);
|
|
1468
|
+
return fs.statSync(themePath).isDirectory() && (fs.existsSync(path8.join(themePath, "theme.config.ts")) || fs.existsSync(path8.join(themePath, "bundle-entry.ts")) || fs.existsSync(path8.join(themePath, "manifest.ts")));
|
|
1469
1469
|
});
|
|
1470
1470
|
}
|
|
1471
1471
|
function themeExists(themeName) {
|
|
1472
|
-
const themePath =
|
|
1473
|
-
return fs.existsSync(themePath) && (fs.existsSync(
|
|
1472
|
+
const themePath = path8.join(getThemesDir(), themeName);
|
|
1473
|
+
return fs.existsSync(themePath) && (fs.existsSync(path8.join(themePath, "theme.config.ts")) || fs.existsSync(path8.join(themePath, "bundle-entry.ts")) || fs.existsSync(path8.join(themePath, "manifest.ts")));
|
|
1474
1474
|
}
|
|
1475
1475
|
function detectPackageManager() {
|
|
1476
1476
|
const userAgent = process.env.npm_config_user_agent || "";
|
|
@@ -1478,92 +1478,30 @@ 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(
|
|
1482
|
-
if (fs.existsSync(
|
|
1483
|
-
if (fs.existsSync(
|
|
1481
|
+
if (fs.existsSync(path8.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
1482
|
+
if (fs.existsSync(path8.join(cwd, "yarn.lock"))) return "yarn";
|
|
1483
|
+
if (fs.existsSync(path8.join(cwd, "bun.lockb"))) return "bun";
|
|
1484
1484
|
return "npm";
|
|
1485
1485
|
}
|
|
1486
1486
|
async function installDependencies(projectPath, packageManager = "npm") {
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1487
|
+
return new Promise((resolve, reject) => {
|
|
1488
|
+
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);
|
|
1497
|
+
}
|
|
1491
1498
|
});
|
|
1492
|
-
if (result.status !== 0) {
|
|
1493
|
-
throw new Error(
|
|
1494
|
-
`${packageManager} install failed with exit code ${result.status}`
|
|
1495
|
-
);
|
|
1496
|
-
}
|
|
1497
1499
|
}
|
|
1498
|
-
var AUTH_DIR =
|
|
1499
|
-
|
|
1500
|
+
var AUTH_DIR = path8.join(os.homedir(), ".onexthm");
|
|
1501
|
+
path8.join(AUTH_DIR, "auth.json");
|
|
1500
1502
|
function getApiUrl() {
|
|
1501
1503
|
return process.env.ONEXTHM_API_URL || process.env.NEXT_PUBLIC_API_URL || "https://platform-dev.onexeos.com";
|
|
1502
1504
|
}
|
|
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)) {
|
|
1521
|
-
try {
|
|
1522
|
-
mcpConfig = JSON.parse(fs4.readFileSync(mcpJsonPath, "utf-8"));
|
|
1523
|
-
if (!mcpConfig.mcpServers) {
|
|
1524
|
-
mcpConfig.mcpServers = {};
|
|
1525
|
-
}
|
|
1526
|
-
} catch {
|
|
1527
|
-
mcpConfig = getDefaultMcpConfig();
|
|
1528
|
-
}
|
|
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
|
-
}
|
|
1566
|
-
}
|
|
1567
1505
|
|
|
1568
1506
|
// src/commands/init.ts
|
|
1569
1507
|
async function initCommand(projectName, options = {}) {
|
|
@@ -1581,7 +1519,7 @@ async function initCommand(projectName, options = {}) {
|
|
|
1581
1519
|
if (!validateThemeName(kebabName)) {
|
|
1582
1520
|
return "Invalid project name. Use lowercase letters, numbers, and hyphens only.";
|
|
1583
1521
|
}
|
|
1584
|
-
if (
|
|
1522
|
+
if (fs3.existsSync(path8.join(process.cwd(), kebabName))) {
|
|
1585
1523
|
return `Directory "${kebabName}" already exists`;
|
|
1586
1524
|
}
|
|
1587
1525
|
return true;
|
|
@@ -1592,8 +1530,8 @@ async function initCommand(projectName, options = {}) {
|
|
|
1592
1530
|
} else {
|
|
1593
1531
|
name = toKebabCase(projectName);
|
|
1594
1532
|
}
|
|
1595
|
-
const projectPath =
|
|
1596
|
-
if (
|
|
1533
|
+
const projectPath = path8.join(process.cwd(), name);
|
|
1534
|
+
if (fs3.existsSync(projectPath)) {
|
|
1597
1535
|
logger.error(`Directory "${name}" already exists.`);
|
|
1598
1536
|
process.exit(1);
|
|
1599
1537
|
}
|
|
@@ -1699,7 +1637,7 @@ async function initCommand(projectName, options = {}) {
|
|
|
1699
1637
|
}
|
|
1700
1638
|
logger.startSpinner("Creating project structure...");
|
|
1701
1639
|
try {
|
|
1702
|
-
|
|
1640
|
+
fs3.mkdirSync(projectPath, { recursive: true });
|
|
1703
1641
|
await copyTemplate(template, projectPath, data);
|
|
1704
1642
|
await renameThemeInFiles(
|
|
1705
1643
|
projectPath,
|
|
@@ -1708,14 +1646,28 @@ async function initCommand(projectName, options = {}) {
|
|
|
1708
1646
|
description,
|
|
1709
1647
|
author
|
|
1710
1648
|
);
|
|
1711
|
-
|
|
1649
|
+
const mcpJsonPath = path8.join(projectPath, ".mcp.json");
|
|
1650
|
+
if (fs3.existsSync(mcpJsonPath)) {
|
|
1651
|
+
let mcpContent = fs3.readFileSync(mcpJsonPath, "utf-8");
|
|
1652
|
+
if (figmaApiKey) {
|
|
1653
|
+
mcpContent = mcpContent.replace("__FIGMA_API_KEY__", figmaApiKey);
|
|
1654
|
+
} else {
|
|
1655
|
+
try {
|
|
1656
|
+
const mcpJson = JSON.parse(mcpContent);
|
|
1657
|
+
delete mcpJson.mcpServers.figma;
|
|
1658
|
+
mcpContent = JSON.stringify(mcpJson, null, 2) + "\n";
|
|
1659
|
+
} catch {
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
fs3.writeFileSync(mcpJsonPath, mcpContent, "utf-8");
|
|
1663
|
+
}
|
|
1712
1664
|
logger.stopSpinner(true, "Project structure created!");
|
|
1713
1665
|
if (options.git) {
|
|
1714
1666
|
logger.startSpinner("Initializing git repository...");
|
|
1715
1667
|
try {
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1668
|
+
execSync("git init", { cwd: projectPath, stdio: "ignore" });
|
|
1669
|
+
execSync("git add .", { cwd: projectPath, stdio: "ignore" });
|
|
1670
|
+
execSync('git commit -m "Initial commit from onexthm init"', {
|
|
1719
1671
|
cwd: projectPath,
|
|
1720
1672
|
stdio: "ignore"
|
|
1721
1673
|
});
|
|
@@ -1767,16 +1719,16 @@ async function initCommand(projectName, options = {}) {
|
|
|
1767
1719
|
logger.error(
|
|
1768
1720
|
error instanceof Error ? error.message : "Unknown error occurred"
|
|
1769
1721
|
);
|
|
1770
|
-
if (
|
|
1771
|
-
|
|
1722
|
+
if (fs3.existsSync(projectPath)) {
|
|
1723
|
+
fs3.rmSync(projectPath, { recursive: true, force: true });
|
|
1772
1724
|
}
|
|
1773
1725
|
process.exit(1);
|
|
1774
1726
|
}
|
|
1775
1727
|
}
|
|
1776
1728
|
async function renameThemeInFiles(projectPath, themeName, displayName, description, author) {
|
|
1777
|
-
const configPath =
|
|
1778
|
-
if (
|
|
1779
|
-
let content =
|
|
1729
|
+
const configPath = path8.join(projectPath, "theme.config.ts");
|
|
1730
|
+
if (fs3.existsSync(configPath)) {
|
|
1731
|
+
let content = fs3.readFileSync(configPath, "utf-8");
|
|
1780
1732
|
content = content.replace(
|
|
1781
1733
|
/name: "My Simple Theme"/,
|
|
1782
1734
|
`name: "${displayName}"`
|
|
@@ -1785,11 +1737,11 @@ async function renameThemeInFiles(projectPath, themeName, displayName, descripti
|
|
|
1785
1737
|
/description: ".*?"/,
|
|
1786
1738
|
`description: "${description}"`
|
|
1787
1739
|
);
|
|
1788
|
-
|
|
1740
|
+
fs3.writeFileSync(configPath, content, "utf-8");
|
|
1789
1741
|
}
|
|
1790
|
-
const pkgPath =
|
|
1791
|
-
if (
|
|
1792
|
-
let content =
|
|
1742
|
+
const pkgPath = path8.join(projectPath, "package.json");
|
|
1743
|
+
if (fs3.existsSync(pkgPath)) {
|
|
1744
|
+
let content = fs3.readFileSync(pkgPath, "utf-8");
|
|
1793
1745
|
content = content.replace(
|
|
1794
1746
|
/@onex-themes\/my-simple/g,
|
|
1795
1747
|
`@onex-themes/${themeName}`
|
|
@@ -1798,7 +1750,7 @@ async function renameThemeInFiles(projectPath, themeName, displayName, descripti
|
|
|
1798
1750
|
/"description": ".*?"/,
|
|
1799
1751
|
`"description": "${description}"`
|
|
1800
1752
|
);
|
|
1801
|
-
|
|
1753
|
+
fs3.writeFileSync(pkgPath, content, "utf-8");
|
|
1802
1754
|
}
|
|
1803
1755
|
}
|
|
1804
1756
|
|
|
@@ -1809,10 +1761,10 @@ async function createSectionCommand(name, options) {
|
|
|
1809
1761
|
ensureOneXProject();
|
|
1810
1762
|
if (!options.theme) {
|
|
1811
1763
|
const isStandaloneTheme = ["theme.config.ts", "bundle-entry.ts"].some(
|
|
1812
|
-
(f) => fs.existsSync(
|
|
1764
|
+
(f) => fs.existsSync(path8.join(process.cwd(), f))
|
|
1813
1765
|
);
|
|
1814
1766
|
if (isStandaloneTheme) {
|
|
1815
|
-
options.theme =
|
|
1767
|
+
options.theme = path8.basename(process.cwd());
|
|
1816
1768
|
}
|
|
1817
1769
|
}
|
|
1818
1770
|
const sectionName = toKebabCase(name);
|
|
@@ -1875,35 +1827,35 @@ async function createSectionCommand(name, options) {
|
|
|
1875
1827
|
};
|
|
1876
1828
|
logger.startSpinner("Creating section files...");
|
|
1877
1829
|
try {
|
|
1878
|
-
const themePath =
|
|
1879
|
-
const sectionPath =
|
|
1830
|
+
const themePath = path8.join(getThemesDir(), themeName);
|
|
1831
|
+
const sectionPath = path8.join(themePath, "sections", sectionName);
|
|
1880
1832
|
const schemaContent = generateSectionSchema(data);
|
|
1881
1833
|
await writeFile(
|
|
1882
|
-
|
|
1834
|
+
path8.join(sectionPath, `${sectionName}.schema.ts`),
|
|
1883
1835
|
schemaContent
|
|
1884
1836
|
);
|
|
1885
1837
|
if (createTemplate) {
|
|
1886
1838
|
const templateContent = generateSectionTemplate(data);
|
|
1887
1839
|
await writeFile(
|
|
1888
|
-
|
|
1840
|
+
path8.join(sectionPath, `${sectionName}-default.tsx`),
|
|
1889
1841
|
templateContent
|
|
1890
1842
|
);
|
|
1891
1843
|
}
|
|
1892
1844
|
const indexContent = generateSectionIndex(data, createTemplate);
|
|
1893
|
-
await writeFile(
|
|
1845
|
+
await writeFile(path8.join(sectionPath, "index.ts"), indexContent);
|
|
1894
1846
|
logger.stopSpinner(true, "Section files created successfully!");
|
|
1895
1847
|
logger.newLine();
|
|
1896
1848
|
logger.section("Next steps:");
|
|
1897
1849
|
logger.log(
|
|
1898
|
-
` 1. Edit schema: ${
|
|
1850
|
+
` 1. Edit schema: ${path8.relative(process.cwd(), path8.join(sectionPath, `${sectionName}.schema.ts`))}`
|
|
1899
1851
|
);
|
|
1900
1852
|
if (createTemplate) {
|
|
1901
1853
|
logger.log(
|
|
1902
|
-
` 2. Edit template: ${
|
|
1854
|
+
` 2. Edit template: ${path8.relative(process.cwd(), path8.join(sectionPath, `${sectionName}-default.tsx`))}`
|
|
1903
1855
|
);
|
|
1904
1856
|
}
|
|
1905
1857
|
logger.log(
|
|
1906
|
-
` 3. Add to theme manifest: ${
|
|
1858
|
+
` 3. Add to theme manifest: ${path8.relative(process.cwd(), path8.join(themePath, "manifest.ts"))}`
|
|
1907
1859
|
);
|
|
1908
1860
|
logger.newLine();
|
|
1909
1861
|
logger.success("Section created successfully!");
|
|
@@ -2051,10 +2003,10 @@ async function createBlockCommand(name, options) {
|
|
|
2051
2003
|
ensureOneXProject();
|
|
2052
2004
|
if (!options.theme) {
|
|
2053
2005
|
const isStandaloneTheme = ["theme.config.ts", "bundle-entry.ts"].some(
|
|
2054
|
-
(f) => fs.existsSync(
|
|
2006
|
+
(f) => fs.existsSync(path8.join(process.cwd(), f))
|
|
2055
2007
|
);
|
|
2056
2008
|
if (isStandaloneTheme) {
|
|
2057
|
-
options.theme =
|
|
2009
|
+
options.theme = path8.basename(process.cwd());
|
|
2058
2010
|
}
|
|
2059
2011
|
}
|
|
2060
2012
|
const blockName = toKebabCase(name);
|
|
@@ -2129,24 +2081,24 @@ async function createBlockCommand(name, options) {
|
|
|
2129
2081
|
};
|
|
2130
2082
|
logger.startSpinner("Creating block files...");
|
|
2131
2083
|
try {
|
|
2132
|
-
const blockPath = scope === "shared" ?
|
|
2084
|
+
const blockPath = scope === "shared" ? path8.join(getFeaturesDir(), "blocks", blockName) : path8.join(getThemesDir(), themeName, "blocks", blockName);
|
|
2133
2085
|
const schemaContent = generateBlockSchema(data);
|
|
2134
2086
|
await writeFile(
|
|
2135
|
-
|
|
2087
|
+
path8.join(blockPath, `${blockName}.schema.ts`),
|
|
2136
2088
|
schemaContent
|
|
2137
2089
|
);
|
|
2138
2090
|
const componentContent = generateBlockComponent(data);
|
|
2139
|
-
await writeFile(
|
|
2091
|
+
await writeFile(path8.join(blockPath, `${blockName}.tsx`), componentContent);
|
|
2140
2092
|
const indexContent = generateBlockIndex(data);
|
|
2141
|
-
await writeFile(
|
|
2093
|
+
await writeFile(path8.join(blockPath, "index.ts"), indexContent);
|
|
2142
2094
|
logger.stopSpinner(true, "Block files created successfully!");
|
|
2143
2095
|
logger.newLine();
|
|
2144
2096
|
logger.section("Next steps:");
|
|
2145
2097
|
logger.log(
|
|
2146
|
-
` 1. Edit schema: ${
|
|
2098
|
+
` 1. Edit schema: ${path8.relative(process.cwd(), path8.join(blockPath, `${blockName}.schema.ts`))}`
|
|
2147
2099
|
);
|
|
2148
2100
|
logger.log(
|
|
2149
|
-
` 2. Edit component: ${
|
|
2101
|
+
` 2. Edit component: ${path8.relative(process.cwd(), path8.join(blockPath, `${blockName}.tsx`))}`
|
|
2150
2102
|
);
|
|
2151
2103
|
logger.log(
|
|
2152
2104
|
` 3. Register in block registry: src/lib/registry/block-registry.ts`
|
|
@@ -2324,31 +2276,31 @@ async function createComponentCommand(name, options) {
|
|
|
2324
2276
|
};
|
|
2325
2277
|
logger.startSpinner("Creating component files...");
|
|
2326
2278
|
try {
|
|
2327
|
-
const componentPath =
|
|
2279
|
+
const componentPath = path8.join(
|
|
2328
2280
|
getFeaturesDir(),
|
|
2329
2281
|
"components",
|
|
2330
2282
|
componentName
|
|
2331
2283
|
);
|
|
2332
2284
|
const schemaContent = generateComponentSchema(data);
|
|
2333
2285
|
await writeFile(
|
|
2334
|
-
|
|
2286
|
+
path8.join(componentPath, `${componentName}.schema.ts`),
|
|
2335
2287
|
schemaContent
|
|
2336
2288
|
);
|
|
2337
2289
|
const componentContent = generateComponent(data);
|
|
2338
2290
|
await writeFile(
|
|
2339
|
-
|
|
2291
|
+
path8.join(componentPath, `${componentName}.tsx`),
|
|
2340
2292
|
componentContent
|
|
2341
2293
|
);
|
|
2342
2294
|
const indexContent = generateComponentIndex(data);
|
|
2343
|
-
await writeFile(
|
|
2295
|
+
await writeFile(path8.join(componentPath, "index.ts"), indexContent);
|
|
2344
2296
|
logger.stopSpinner(true, "Component files created successfully!");
|
|
2345
2297
|
logger.newLine();
|
|
2346
2298
|
logger.section("Next steps:");
|
|
2347
2299
|
logger.log(
|
|
2348
|
-
` 1. Edit schema: ${
|
|
2300
|
+
` 1. Edit schema: ${path8.relative(process.cwd(), path8.join(componentPath, `${componentName}.schema.ts`))}`
|
|
2349
2301
|
);
|
|
2350
2302
|
logger.log(
|
|
2351
|
-
` 2. Edit component: ${
|
|
2303
|
+
` 2. Edit component: ${path8.relative(process.cwd(), path8.join(componentPath, `${componentName}.tsx`))}`
|
|
2352
2304
|
);
|
|
2353
2305
|
logger.log(
|
|
2354
2306
|
` 3. Register in component registry: src/lib/registry/component-registry.ts`
|
|
@@ -2505,13 +2457,13 @@ async function listSections(themeFilter) {
|
|
|
2505
2457
|
return;
|
|
2506
2458
|
}
|
|
2507
2459
|
for (const theme of themes) {
|
|
2508
|
-
const sectionsDir =
|
|
2460
|
+
const sectionsDir = path8.join(getThemesDir(), theme, "sections");
|
|
2509
2461
|
if (!fs.existsSync(sectionsDir)) {
|
|
2510
2462
|
continue;
|
|
2511
2463
|
}
|
|
2512
2464
|
const sections = fs.readdirSync(sectionsDir).filter((name) => {
|
|
2513
|
-
const sectionPath =
|
|
2514
|
-
return fs.statSync(sectionPath).isDirectory() && fs.existsSync(
|
|
2465
|
+
const sectionPath = path8.join(sectionsDir, name);
|
|
2466
|
+
return fs.statSync(sectionPath).isDirectory() && fs.existsSync(path8.join(sectionPath, "index.ts"));
|
|
2515
2467
|
});
|
|
2516
2468
|
if (sections.length > 0) {
|
|
2517
2469
|
logger.log(chalk4.cyan(`
|
|
@@ -2525,11 +2477,11 @@ async function listSections(themeFilter) {
|
|
|
2525
2477
|
}
|
|
2526
2478
|
async function listBlocks(themeFilter) {
|
|
2527
2479
|
logger.section("\u{1F9F1} Blocks");
|
|
2528
|
-
const sharedBlocksDir =
|
|
2480
|
+
const sharedBlocksDir = path8.join(getFeaturesDir(), "blocks");
|
|
2529
2481
|
if (fs.existsSync(sharedBlocksDir)) {
|
|
2530
2482
|
const sharedBlocks = fs.readdirSync(sharedBlocksDir).filter((name) => {
|
|
2531
|
-
const blockPath =
|
|
2532
|
-
return fs.statSync(blockPath).isDirectory() && fs.existsSync(
|
|
2483
|
+
const blockPath = path8.join(sharedBlocksDir, name);
|
|
2484
|
+
return fs.statSync(blockPath).isDirectory() && fs.existsSync(path8.join(blockPath, "index.ts"));
|
|
2533
2485
|
});
|
|
2534
2486
|
if (sharedBlocks.length > 0) {
|
|
2535
2487
|
logger.log(chalk4.cyan("\n Shared:"));
|
|
@@ -2540,13 +2492,13 @@ async function listBlocks(themeFilter) {
|
|
|
2540
2492
|
}
|
|
2541
2493
|
const themes = themeFilter ? [themeFilter] : listThemes();
|
|
2542
2494
|
for (const theme of themes) {
|
|
2543
|
-
const blocksDir =
|
|
2495
|
+
const blocksDir = path8.join(getThemesDir(), theme, "blocks");
|
|
2544
2496
|
if (!fs.existsSync(blocksDir)) {
|
|
2545
2497
|
continue;
|
|
2546
2498
|
}
|
|
2547
2499
|
const blocks = fs.readdirSync(blocksDir).filter((name) => {
|
|
2548
|
-
const blockPath =
|
|
2549
|
-
return fs.statSync(blockPath).isDirectory() && fs.existsSync(
|
|
2500
|
+
const blockPath = path8.join(blocksDir, name);
|
|
2501
|
+
return fs.statSync(blockPath).isDirectory() && fs.existsSync(path8.join(blockPath, "index.ts"));
|
|
2550
2502
|
});
|
|
2551
2503
|
if (blocks.length > 0) {
|
|
2552
2504
|
logger.log(chalk4.cyan(`
|
|
@@ -2560,14 +2512,14 @@ async function listBlocks(themeFilter) {
|
|
|
2560
2512
|
}
|
|
2561
2513
|
async function listComponents() {
|
|
2562
2514
|
logger.section("\u2699\uFE0F Components");
|
|
2563
|
-
const componentsDir =
|
|
2515
|
+
const componentsDir = path8.join(getFeaturesDir(), "components");
|
|
2564
2516
|
if (!fs.existsSync(componentsDir)) {
|
|
2565
2517
|
logger.warning("No components directory found");
|
|
2566
2518
|
return;
|
|
2567
2519
|
}
|
|
2568
2520
|
const components = fs.readdirSync(componentsDir).filter((name) => {
|
|
2569
|
-
const componentPath =
|
|
2570
|
-
return fs.statSync(componentPath).isDirectory() && fs.existsSync(
|
|
2521
|
+
const componentPath = path8.join(componentsDir, name);
|
|
2522
|
+
return fs.statSync(componentPath).isDirectory() && fs.existsSync(path8.join(componentPath, "index.ts"));
|
|
2571
2523
|
});
|
|
2572
2524
|
if (components.length === 0) {
|
|
2573
2525
|
logger.warning("No components found");
|
|
@@ -2588,11 +2540,11 @@ async function listThemesInfo() {
|
|
|
2588
2540
|
}
|
|
2589
2541
|
logger.log("");
|
|
2590
2542
|
for (const theme of themes) {
|
|
2591
|
-
const themeDir =
|
|
2543
|
+
const themeDir = path8.join(getThemesDir(), theme);
|
|
2592
2544
|
const candidates = ["theme.config.ts", "bundle-entry.ts", "manifest.ts"];
|
|
2593
2545
|
let manifestContent = "";
|
|
2594
2546
|
for (const candidate of candidates) {
|
|
2595
|
-
const candidatePath =
|
|
2547
|
+
const candidatePath = path8.join(themeDir, candidate);
|
|
2596
2548
|
if (fs.existsSync(candidatePath)) {
|
|
2597
2549
|
manifestContent = fs.readFileSync(candidatePath, "utf-8");
|
|
2598
2550
|
break;
|
|
@@ -2621,14 +2573,14 @@ async function buildCommand(options) {
|
|
|
2621
2573
|
if (options.theme) {
|
|
2622
2574
|
themeName = options.theme;
|
|
2623
2575
|
try {
|
|
2624
|
-
const workspaceThemePath =
|
|
2576
|
+
const workspaceThemePath = path8.join(getThemesDir(), themeName);
|
|
2625
2577
|
if (fs.existsSync(workspaceThemePath)) {
|
|
2626
2578
|
themePath = workspaceThemePath;
|
|
2627
2579
|
} else {
|
|
2628
|
-
themePath =
|
|
2580
|
+
themePath = path8.join(process.cwd(), themeName);
|
|
2629
2581
|
}
|
|
2630
2582
|
} catch {
|
|
2631
|
-
themePath =
|
|
2583
|
+
themePath = path8.join(process.cwd(), themeName);
|
|
2632
2584
|
}
|
|
2633
2585
|
if (!fs.existsSync(themePath)) {
|
|
2634
2586
|
logger.error(`Theme "${themeName}" not found.`);
|
|
@@ -2639,10 +2591,10 @@ async function buildCommand(options) {
|
|
|
2639
2591
|
"theme.config.ts",
|
|
2640
2592
|
"bundle-entry.ts",
|
|
2641
2593
|
"manifest.ts"
|
|
2642
|
-
].some((f) => fs.existsSync(
|
|
2594
|
+
].some((f) => fs.existsSync(path8.join(process.cwd(), f)));
|
|
2643
2595
|
if (isThemeDir) {
|
|
2644
2596
|
themePath = process.cwd();
|
|
2645
|
-
themeName =
|
|
2597
|
+
themeName = path8.basename(themePath);
|
|
2646
2598
|
logger.info(`Building current theme: ${themeName}`);
|
|
2647
2599
|
} else {
|
|
2648
2600
|
logger.error(
|
|
@@ -2651,7 +2603,7 @@ async function buildCommand(options) {
|
|
|
2651
2603
|
process.exit(1);
|
|
2652
2604
|
}
|
|
2653
2605
|
}
|
|
2654
|
-
const packageJsonPath =
|
|
2606
|
+
const packageJsonPath = path8.join(themePath, "package.json");
|
|
2655
2607
|
const hasPkgJson = fs.existsSync(packageJsonPath);
|
|
2656
2608
|
if (!hasPkgJson) {
|
|
2657
2609
|
logger.warning(
|
|
@@ -2707,9 +2659,9 @@ async function buildCommand(options) {
|
|
|
2707
2659
|
logger.success("\u2713 Theme built successfully!");
|
|
2708
2660
|
logger.newLine();
|
|
2709
2661
|
logger.info(`Theme: ${themeName}`);
|
|
2710
|
-
const distPath =
|
|
2662
|
+
const distPath = path8.join(themePath, "dist");
|
|
2711
2663
|
if (fs.existsSync(distPath)) {
|
|
2712
|
-
logger.log(`Output: ${
|
|
2664
|
+
logger.log(`Output: ${path8.relative(process.cwd(), distPath)}`);
|
|
2713
2665
|
const files = fs.readdirSync(distPath);
|
|
2714
2666
|
logger.log(`Files: ${files.length}`);
|
|
2715
2667
|
}
|
|
@@ -2717,17 +2669,17 @@ async function buildCommand(options) {
|
|
|
2717
2669
|
}
|
|
2718
2670
|
function runCommand(command, args, cwd) {
|
|
2719
2671
|
return new Promise((resolve) => {
|
|
2720
|
-
const proc =
|
|
2672
|
+
const proc = spawn(command, args, {
|
|
2721
2673
|
cwd,
|
|
2722
2674
|
stdio: ["pipe", "pipe", "pipe"],
|
|
2723
2675
|
shell: true
|
|
2724
2676
|
});
|
|
2725
2677
|
let stdout = "";
|
|
2726
2678
|
let stderr = "";
|
|
2727
|
-
proc.stdout
|
|
2679
|
+
proc.stdout.on("data", (data) => {
|
|
2728
2680
|
stdout += data.toString();
|
|
2729
2681
|
});
|
|
2730
|
-
proc.stderr
|
|
2682
|
+
proc.stderr.on("data", (data) => {
|
|
2731
2683
|
stderr += data.toString();
|
|
2732
2684
|
});
|
|
2733
2685
|
proc.on("close", (code) => {
|
|
@@ -2797,11 +2749,11 @@ function getBucketName(env) {
|
|
|
2797
2749
|
return environment === "production" ? "theme-s3-bucket" : "theme-s3-bucket";
|
|
2798
2750
|
}
|
|
2799
2751
|
async function findCompiledThemeDir(themeId, version) {
|
|
2800
|
-
const searchPaths = [
|
|
2752
|
+
const searchPaths = [path8.resolve(process.cwd(), "dist")];
|
|
2801
2753
|
for (const dir of searchPaths) {
|
|
2802
2754
|
if (await fs.pathExists(dir)) {
|
|
2803
|
-
const hasManifest = await fs.pathExists(
|
|
2804
|
-
const hasThemeEntry = await fs.pathExists(
|
|
2755
|
+
const hasManifest = await fs.pathExists(path8.join(dir, "manifest.json"));
|
|
2756
|
+
const hasThemeEntry = await fs.pathExists(path8.join(dir, "bundle-entry.js")) || await fs.pathExists(path8.join(dir, "theme.config.js")) || await fs.pathExists(path8.join(dir, "index.js"));
|
|
2805
2757
|
if (hasManifest || hasThemeEntry) {
|
|
2806
2758
|
return dir;
|
|
2807
2759
|
}
|
|
@@ -2810,7 +2762,7 @@ async function findCompiledThemeDir(themeId, version) {
|
|
|
2810
2762
|
return null;
|
|
2811
2763
|
}
|
|
2812
2764
|
async function readManifest() {
|
|
2813
|
-
const manifestTsPath =
|
|
2765
|
+
const manifestTsPath = path8.resolve(process.cwd(), "manifest.ts");
|
|
2814
2766
|
if (await fs.pathExists(manifestTsPath)) {
|
|
2815
2767
|
try {
|
|
2816
2768
|
const module = await import(manifestTsPath);
|
|
@@ -2819,7 +2771,7 @@ async function readManifest() {
|
|
|
2819
2771
|
logger.warning("Failed to import manifest.ts, trying package.json");
|
|
2820
2772
|
}
|
|
2821
2773
|
}
|
|
2822
|
-
const packageJsonPath =
|
|
2774
|
+
const packageJsonPath = path8.resolve(process.cwd(), "package.json");
|
|
2823
2775
|
if (await fs.pathExists(packageJsonPath)) {
|
|
2824
2776
|
const pkg = await fs.readJson(packageJsonPath);
|
|
2825
2777
|
return {
|
|
@@ -2853,13 +2805,13 @@ async function findSourceDir(themeId, explicitDir) {
|
|
|
2853
2805
|
}
|
|
2854
2806
|
const searchPaths = [
|
|
2855
2807
|
process.cwd(),
|
|
2856
|
-
|
|
2857
|
-
|
|
2808
|
+
path8.resolve(process.cwd(), `../../themes/${themeId}`),
|
|
2809
|
+
path8.resolve(process.cwd(), `../themes/${themeId}`)
|
|
2858
2810
|
];
|
|
2859
2811
|
const markers = ["theme.config.ts", "bundle-entry.ts"];
|
|
2860
2812
|
for (const dir of searchPaths) {
|
|
2861
2813
|
for (const marker of markers) {
|
|
2862
|
-
if (await fs.pathExists(
|
|
2814
|
+
if (await fs.pathExists(path8.join(dir, marker))) {
|
|
2863
2815
|
return dir;
|
|
2864
2816
|
}
|
|
2865
2817
|
}
|
|
@@ -2911,7 +2863,7 @@ async function uploadCommand(options) {
|
|
|
2911
2863
|
spinner.succeed(`Found compiled theme at: ${compiledDir}`);
|
|
2912
2864
|
spinner.start("Creating bundle.zip...");
|
|
2913
2865
|
const tmpDir = os.tmpdir();
|
|
2914
|
-
const bundleZipPath =
|
|
2866
|
+
const bundleZipPath = path8.join(tmpDir, `${themeId}-${version}-bundle.zip`);
|
|
2915
2867
|
await createZipFromDir(compiledDir, bundleZipPath);
|
|
2916
2868
|
const bundleZipBuffer = await fs.readFile(bundleZipPath);
|
|
2917
2869
|
const bundleSizeMB = (bundleZipBuffer.length / 1024 / 1024).toFixed(2);
|
|
@@ -2965,7 +2917,7 @@ async function uploadCommand(options) {
|
|
|
2965
2917
|
if (sourceDir) {
|
|
2966
2918
|
spinner.succeed(`Found source at: ${sourceDir}`);
|
|
2967
2919
|
spinner.start("Creating source.zip...");
|
|
2968
|
-
const sourceZipPath =
|
|
2920
|
+
const sourceZipPath = path8.join(
|
|
2969
2921
|
tmpDir,
|
|
2970
2922
|
`${themeId}-${version}-source.zip`
|
|
2971
2923
|
);
|
|
@@ -3099,8 +3051,8 @@ async function resolveLatestVersion(s3Client, bucket, themeId) {
|
|
|
3099
3051
|
async function createCompatibilityFiles(outputDir, manifest) {
|
|
3100
3052
|
const entryFile = manifest.output?.entry || "bundle-entry.js";
|
|
3101
3053
|
if (entryFile !== "bundle-entry.js" && entryFile.startsWith("bundle-entry-")) {
|
|
3102
|
-
const hashedPath =
|
|
3103
|
-
const stablePath =
|
|
3054
|
+
const hashedPath = path8.join(outputDir, entryFile);
|
|
3055
|
+
const stablePath = path8.join(outputDir, "bundle-entry.js");
|
|
3104
3056
|
if (await fs.pathExists(hashedPath)) {
|
|
3105
3057
|
await fs.copy(hashedPath, stablePath);
|
|
3106
3058
|
const mapPath = hashedPath + ".map";
|
|
@@ -3109,13 +3061,13 @@ async function createCompatibilityFiles(outputDir, manifest) {
|
|
|
3109
3061
|
}
|
|
3110
3062
|
}
|
|
3111
3063
|
}
|
|
3112
|
-
const sectionsRegistryPath =
|
|
3064
|
+
const sectionsRegistryPath = path8.join(outputDir, "sections-registry.js");
|
|
3113
3065
|
const content = `// Re-export all sections from bundle-entry
|
|
3114
3066
|
// This file exists to maintain compatibility with the import path
|
|
3115
3067
|
export * from './bundle-entry.js';
|
|
3116
3068
|
`;
|
|
3117
3069
|
await fs.writeFile(sectionsRegistryPath, content, "utf-8");
|
|
3118
|
-
const pkgJsonPath =
|
|
3070
|
+
const pkgJsonPath = path8.join(outputDir, "package.json");
|
|
3119
3071
|
await fs.writeFile(pkgJsonPath, '{\n "type": "module"\n}\n', "utf-8");
|
|
3120
3072
|
}
|
|
3121
3073
|
function showDownloadFailureHelp(themeId, bucket) {
|
|
@@ -3210,7 +3162,7 @@ async function downloadCommand(options) {
|
|
|
3210
3162
|
zip.extractAllTo(outputDir, true);
|
|
3211
3163
|
const entries = zip.getEntries().filter((e) => !e.isDirectory);
|
|
3212
3164
|
spinner.succeed(`Extracted ${entries.length} files to ${outputDir}`);
|
|
3213
|
-
const manifestPath =
|
|
3165
|
+
const manifestPath = path8.join(outputDir, "manifest.json");
|
|
3214
3166
|
const manifest = await fs.readJson(manifestPath);
|
|
3215
3167
|
await createCompatibilityFiles(outputDir, manifest);
|
|
3216
3168
|
console.log();
|
|
@@ -3310,9 +3262,10 @@ async function resolveLatestVersion2(s3Client, bucket, themeId) {
|
|
|
3310
3262
|
}
|
|
3311
3263
|
function runInstall(cwd) {
|
|
3312
3264
|
return new Promise((resolve) => {
|
|
3313
|
-
const proc =
|
|
3265
|
+
const proc = spawn("pnpm", ["install"], {
|
|
3314
3266
|
cwd,
|
|
3315
|
-
stdio: "inherit"
|
|
3267
|
+
stdio: "inherit",
|
|
3268
|
+
shell: true
|
|
3316
3269
|
});
|
|
3317
3270
|
proc.on("close", (code) => resolve(code === 0));
|
|
3318
3271
|
proc.on("error", () => resolve(false));
|
|
@@ -3343,7 +3296,7 @@ async function renameTheme(themeDir, oldName, newName) {
|
|
|
3343
3296
|
const oldPrefix = `${oldName}-`;
|
|
3344
3297
|
const newPrefix = `${newName}-`;
|
|
3345
3298
|
const newDisplayName = newName.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
3346
|
-
const pkgPath =
|
|
3299
|
+
const pkgPath = path8.join(themeDir, "package.json");
|
|
3347
3300
|
if (await fs.pathExists(pkgPath)) {
|
|
3348
3301
|
const pkg = await fs.readJson(pkgPath);
|
|
3349
3302
|
pkg.name = `@onex-themes/${newName}`;
|
|
@@ -3359,7 +3312,7 @@ async function renameTheme(themeDir, oldName, newName) {
|
|
|
3359
3312
|
}
|
|
3360
3313
|
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
3361
3314
|
}
|
|
3362
|
-
const configPath =
|
|
3315
|
+
const configPath = path8.join(themeDir, "theme.config.ts");
|
|
3363
3316
|
if (await fs.pathExists(configPath)) {
|
|
3364
3317
|
let content = await fs.readFile(configPath, "utf-8");
|
|
3365
3318
|
content = content.replace(/id:\s*"[^"]*"/, `id: "${newName}"`);
|
|
@@ -3369,7 +3322,7 @@ async function renameTheme(themeDir, oldName, newName) {
|
|
|
3369
3322
|
);
|
|
3370
3323
|
await fs.writeFile(configPath, content);
|
|
3371
3324
|
}
|
|
3372
|
-
const layoutPath =
|
|
3325
|
+
const layoutPath = path8.join(themeDir, "theme.layout.ts");
|
|
3373
3326
|
if (await fs.pathExists(layoutPath)) {
|
|
3374
3327
|
let content = await fs.readFile(layoutPath, "utf-8");
|
|
3375
3328
|
content = content.replace(/id:\s*"[^"]*"/, `id: "${newName}"`);
|
|
@@ -3382,7 +3335,7 @@ async function renameTheme(themeDir, oldName, newName) {
|
|
|
3382
3335
|
const oldDisplayName = oldName.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
3383
3336
|
const tsFiles = await glob("**/*.ts", { cwd: themeDir, nodir: true });
|
|
3384
3337
|
for (const file of tsFiles) {
|
|
3385
|
-
const filePath =
|
|
3338
|
+
const filePath = path8.join(themeDir, file);
|
|
3386
3339
|
let content = await fs.readFile(filePath, "utf-8");
|
|
3387
3340
|
const original = content;
|
|
3388
3341
|
content = content.replace(
|
|
@@ -3411,7 +3364,7 @@ async function cloneCommand(themeName, options) {
|
|
|
3411
3364
|
const spinner = ora("Initializing clone...").start();
|
|
3412
3365
|
try {
|
|
3413
3366
|
const bucket = options.bucket || getBucketName3(options.environment);
|
|
3414
|
-
const outputDir = options.output ||
|
|
3367
|
+
const outputDir = options.output || path8.resolve(process.cwd(), newName);
|
|
3415
3368
|
const s3Client = getS3Client3();
|
|
3416
3369
|
if (await fs.pathExists(outputDir)) {
|
|
3417
3370
|
spinner.fail(chalk4.red(`Directory already exists: ${outputDir}`));
|
|
@@ -3466,7 +3419,7 @@ async function cloneCommand(themeName, options) {
|
|
|
3466
3419
|
spinner.succeed(
|
|
3467
3420
|
`Renamed theme: ${chalk4.gray(themeName)} \u2192 ${chalk4.cyan(newName)}`
|
|
3468
3421
|
);
|
|
3469
|
-
const envExamplePath =
|
|
3422
|
+
const envExamplePath = path8.join(outputDir, ".env.example");
|
|
3470
3423
|
if (!await fs.pathExists(envExamplePath)) {
|
|
3471
3424
|
await fs.writeFile(
|
|
3472
3425
|
envExamplePath,
|
|
@@ -3479,18 +3432,32 @@ async function cloneCommand(themeName, options) {
|
|
|
3479
3432
|
].join("\n")
|
|
3480
3433
|
);
|
|
3481
3434
|
}
|
|
3482
|
-
const
|
|
3483
|
-
|
|
3484
|
-
{
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3435
|
+
const mcpJsonPath = path8.join(outputDir, ".mcp.json");
|
|
3436
|
+
if (await fs.pathExists(mcpJsonPath)) {
|
|
3437
|
+
const { default: inquirerMod } = await import('inquirer');
|
|
3438
|
+
const { figmaApiKey } = await inquirerMod.prompt([
|
|
3439
|
+
{
|
|
3440
|
+
type: "password",
|
|
3441
|
+
name: "figmaApiKey",
|
|
3442
|
+
message: "Figma API Key (optional, for Figma-to-code MCP \u2014 press Enter to skip):"
|
|
3443
|
+
}
|
|
3444
|
+
]);
|
|
3445
|
+
let mcpContent = await fs.readFile(mcpJsonPath, "utf-8");
|
|
3446
|
+
if (figmaApiKey) {
|
|
3447
|
+
mcpContent = mcpContent.replace("__FIGMA_API_KEY__", figmaApiKey);
|
|
3448
|
+
} else {
|
|
3449
|
+
try {
|
|
3450
|
+
const mcpJson = JSON.parse(mcpContent);
|
|
3451
|
+
delete mcpJson.mcpServers?.figma;
|
|
3452
|
+
mcpContent = JSON.stringify(mcpJson, null, 2) + "\n";
|
|
3453
|
+
} catch {
|
|
3454
|
+
}
|
|
3488
3455
|
}
|
|
3489
|
-
|
|
3490
|
-
|
|
3456
|
+
await fs.writeFile(mcpJsonPath, mcpContent, "utf-8");
|
|
3457
|
+
}
|
|
3491
3458
|
if (options.install !== false) {
|
|
3492
3459
|
const hasPkgJson = await fs.pathExists(
|
|
3493
|
-
|
|
3460
|
+
path8.join(outputDir, "package.json")
|
|
3494
3461
|
);
|
|
3495
3462
|
if (hasPkgJson) {
|
|
3496
3463
|
spinner.start("Installing dependencies...");
|
|
@@ -3517,10 +3484,9 @@ async function cloneCommand(themeName, options) {
|
|
|
3517
3484
|
console.log(chalk4.cyan(" Files: ") + chalk4.white(entries.length));
|
|
3518
3485
|
console.log();
|
|
3519
3486
|
console.log(chalk4.cyan("Next steps:"));
|
|
3520
|
-
console.log(chalk4.gray(` cd ${
|
|
3521
|
-
const copyCmd = process.platform === "win32" ? "copy .env.example .env" : "cp .env.example .env";
|
|
3487
|
+
console.log(chalk4.gray(` cd ${path8.relative(process.cwd(), outputDir)}`));
|
|
3522
3488
|
console.log(
|
|
3523
|
-
chalk4.gray(
|
|
3489
|
+
chalk4.gray(" cp .env.example .env # then add your Company ID")
|
|
3524
3490
|
);
|
|
3525
3491
|
if (options.install === false) {
|
|
3526
3492
|
console.log(chalk4.gray(" pnpm install"));
|