@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/cli.mjs
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import chalk4 from 'chalk';
|
|
3
3
|
import ora from 'ora';
|
|
4
4
|
import * as esbuild from 'esbuild';
|
|
5
|
-
import
|
|
6
|
-
import
|
|
5
|
+
import path9 from 'path';
|
|
6
|
+
import fs8 from 'fs/promises';
|
|
7
7
|
import crypto from 'crypto';
|
|
8
8
|
import { glob } from 'glob';
|
|
9
9
|
import { createRequire } from 'module';
|
|
@@ -11,9 +11,9 @@ import os from 'os';
|
|
|
11
11
|
import dotenv from 'dotenv';
|
|
12
12
|
import fs from 'fs-extra';
|
|
13
13
|
import ejs from 'ejs';
|
|
14
|
-
import
|
|
14
|
+
import { execSync, spawn } from 'child_process';
|
|
15
15
|
import { Command } from 'commander';
|
|
16
|
-
import
|
|
16
|
+
import fs3 from 'fs';
|
|
17
17
|
import inquirer from 'inquirer';
|
|
18
18
|
import archiver from 'archiver';
|
|
19
19
|
import FormData from 'form-data';
|
|
@@ -105,8 +105,8 @@ async function generateThemeCSS(themePath, outDir) {
|
|
|
105
105
|
const tailwindcss = (await import('tailwindcss')).default;
|
|
106
106
|
const tailwindConfig = {
|
|
107
107
|
content: [
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
path9.join(themePath, "sections/**/*.{ts,tsx}"),
|
|
109
|
+
path9.join(themePath, "components/**/*.{ts,tsx}")
|
|
110
110
|
],
|
|
111
111
|
theme: { extend: {} },
|
|
112
112
|
plugins: []
|
|
@@ -116,7 +116,7 @@ async function generateThemeCSS(themePath, outDir) {
|
|
|
116
116
|
inputCSS,
|
|
117
117
|
{ from: void 0 }
|
|
118
118
|
);
|
|
119
|
-
await
|
|
119
|
+
await fs8.writeFile(path9.join(outDir, "bundle.css"), result.css);
|
|
120
120
|
logger.info("Generated bundle.css");
|
|
121
121
|
} catch (err) {
|
|
122
122
|
logger.warning(
|
|
@@ -127,12 +127,12 @@ async function generateThemeCSS(themePath, outDir) {
|
|
|
127
127
|
async function resolveNodeModulesFile(startDir, relativePath) {
|
|
128
128
|
let dir = startDir;
|
|
129
129
|
while (true) {
|
|
130
|
-
const candidate =
|
|
130
|
+
const candidate = path9.join(dir, "node_modules", relativePath);
|
|
131
131
|
try {
|
|
132
|
-
await
|
|
132
|
+
await fs8.access(candidate);
|
|
133
133
|
return candidate;
|
|
134
134
|
} catch {
|
|
135
|
-
const parent =
|
|
135
|
+
const parent = path9.dirname(dir);
|
|
136
136
|
if (parent === dir) break;
|
|
137
137
|
dir = parent;
|
|
138
138
|
}
|
|
@@ -156,7 +156,7 @@ async function scanImportsFromPackage(sourceDir, packageName) {
|
|
|
156
156
|
});
|
|
157
157
|
for (const file of sourceFiles) {
|
|
158
158
|
try {
|
|
159
|
-
const content = await
|
|
159
|
+
const content = await fs8.readFile(path9.join(sourceDir, file), "utf-8");
|
|
160
160
|
for (const match of content.matchAll(namespaceImportRegex)) {
|
|
161
161
|
const subpath = match[1] ? match[1].slice(1) : "";
|
|
162
162
|
if (!result[subpath]) result[subpath] = /* @__PURE__ */ new Set();
|
|
@@ -210,17 +210,17 @@ function createCoreGlobalPlugin(themePath) {
|
|
|
210
210
|
const distFileName = subpath ? `${subpath}.mjs` : "index.mjs";
|
|
211
211
|
let distPath = await resolveNodeModulesFile(
|
|
212
212
|
themePath,
|
|
213
|
-
|
|
213
|
+
path9.join("@onexapis", "core", "dist", distFileName)
|
|
214
214
|
);
|
|
215
215
|
if (!distPath) {
|
|
216
216
|
distPath = await resolveNodeModulesFile(
|
|
217
217
|
__dirname,
|
|
218
|
-
|
|
218
|
+
path9.join("@onexapis", "core", "dist", distFileName)
|
|
219
219
|
);
|
|
220
220
|
}
|
|
221
221
|
try {
|
|
222
222
|
if (!distPath) throw new Error("not found");
|
|
223
|
-
const distContent = await
|
|
223
|
+
const distContent = await fs8.readFile(distPath, "utf-8");
|
|
224
224
|
const exportMatches = distContent.matchAll(/export\s*\{([^}]+)\}/g);
|
|
225
225
|
for (const m of exportMatches) {
|
|
226
226
|
const names = m[1].split(",").map((n) => {
|
|
@@ -449,7 +449,7 @@ async function generateThemeData(themePath, outputDir, themeId) {
|
|
|
449
449
|
const pages = {};
|
|
450
450
|
for (const ext of [".ts", ".js"]) {
|
|
451
451
|
try {
|
|
452
|
-
const mod = await jiti.import(
|
|
452
|
+
const mod = await jiti.import(path9.join(themePath, `theme.config${ext}`));
|
|
453
453
|
themeConfig = mod.default || mod;
|
|
454
454
|
break;
|
|
455
455
|
} catch {
|
|
@@ -457,20 +457,20 @@ async function generateThemeData(themePath, outputDir, themeId) {
|
|
|
457
457
|
}
|
|
458
458
|
for (const ext of [".ts", ".js"]) {
|
|
459
459
|
try {
|
|
460
|
-
const mod = await jiti.import(
|
|
460
|
+
const mod = await jiti.import(path9.join(themePath, `theme.layout${ext}`));
|
|
461
461
|
layoutConfig = mod.default || mod;
|
|
462
462
|
break;
|
|
463
463
|
} catch {
|
|
464
464
|
}
|
|
465
465
|
}
|
|
466
466
|
const schemas = {};
|
|
467
|
-
const sectionsDir =
|
|
467
|
+
const sectionsDir = path9.join(themePath, "sections");
|
|
468
468
|
try {
|
|
469
|
-
const sectionDirs = await
|
|
469
|
+
const sectionDirs = await fs8.readdir(sectionsDir);
|
|
470
470
|
for (const dir of sectionDirs) {
|
|
471
|
-
const schemaFile =
|
|
471
|
+
const schemaFile = path9.join(sectionsDir, dir, `${dir}.schema.ts`);
|
|
472
472
|
try {
|
|
473
|
-
await
|
|
473
|
+
await fs8.access(schemaFile);
|
|
474
474
|
const mod = await jiti.import(schemaFile);
|
|
475
475
|
for (const [key, value] of Object.entries(mod)) {
|
|
476
476
|
if (key.endsWith("Schema") && value && typeof value === "object" && value.type) {
|
|
@@ -482,14 +482,14 @@ async function generateThemeData(themePath, outputDir, themeId) {
|
|
|
482
482
|
}
|
|
483
483
|
} catch {
|
|
484
484
|
}
|
|
485
|
-
const pagesDir =
|
|
485
|
+
const pagesDir = path9.join(themePath, "pages");
|
|
486
486
|
try {
|
|
487
|
-
const files = await
|
|
487
|
+
const files = await fs8.readdir(pagesDir);
|
|
488
488
|
for (const file of files) {
|
|
489
489
|
if (!file.match(/\.(ts|js)$/)) continue;
|
|
490
490
|
const name = file.replace(/\.(ts|js)$/, "");
|
|
491
491
|
try {
|
|
492
|
-
const mod = await jiti.import(
|
|
492
|
+
const mod = await jiti.import(path9.join(pagesDir, file));
|
|
493
493
|
const config = mod.default || mod;
|
|
494
494
|
const sections = (config.sections || []).map((section) => {
|
|
495
495
|
const schema = schemas[section.type];
|
|
@@ -517,8 +517,8 @@ async function generateThemeData(themePath, outputDir, themeId) {
|
|
|
517
517
|
}
|
|
518
518
|
} catch {
|
|
519
519
|
}
|
|
520
|
-
await
|
|
521
|
-
|
|
520
|
+
await fs8.writeFile(
|
|
521
|
+
path9.join(outputDir, "theme-data.json"),
|
|
522
522
|
JSON.stringify(
|
|
523
523
|
{
|
|
524
524
|
themeId,
|
|
@@ -541,36 +541,36 @@ async function generateThemeData(themePath, outputDir, themeId) {
|
|
|
541
541
|
logger.info(`Generated theme-data.json (${Object.keys(pages).length} pages)`);
|
|
542
542
|
}
|
|
543
543
|
async function contentHashEntry(outputDir) {
|
|
544
|
-
const entryPath =
|
|
545
|
-
const mapPath =
|
|
544
|
+
const entryPath = path9.join(outputDir, "bundle-entry.js");
|
|
545
|
+
const mapPath = path9.join(outputDir, "bundle-entry.js.map");
|
|
546
546
|
const oldFiles = await glob("bundle-entry-*.js*", { cwd: outputDir });
|
|
547
547
|
for (const f of oldFiles) {
|
|
548
|
-
await
|
|
548
|
+
await fs8.unlink(path9.join(outputDir, f));
|
|
549
549
|
}
|
|
550
550
|
let entryContent;
|
|
551
551
|
try {
|
|
552
|
-
entryContent = await
|
|
552
|
+
entryContent = await fs8.readFile(entryPath, "utf-8");
|
|
553
553
|
} catch {
|
|
554
|
-
const indexPath =
|
|
554
|
+
const indexPath = path9.join(outputDir, "index.js");
|
|
555
555
|
try {
|
|
556
|
-
entryContent = await
|
|
556
|
+
entryContent = await fs8.readFile(indexPath, "utf-8");
|
|
557
557
|
} catch {
|
|
558
558
|
logger.warning("No entry file found in output, skipping content hash");
|
|
559
559
|
return;
|
|
560
560
|
}
|
|
561
561
|
const hash2 = crypto.createHash("sha256").update(entryContent).digest("hex").slice(0, 8);
|
|
562
562
|
const hashedName2 = `bundle-entry-${hash2}.js`;
|
|
563
|
-
const indexMapPath =
|
|
563
|
+
const indexMapPath = path9.join(outputDir, "index.js.map");
|
|
564
564
|
const hashedMapName2 = `bundle-entry-${hash2}.js.map`;
|
|
565
565
|
entryContent = entryContent.replace(
|
|
566
566
|
/\/\/# sourceMappingURL=index\.js\.map/,
|
|
567
567
|
`//# sourceMappingURL=${hashedMapName2}`
|
|
568
568
|
);
|
|
569
|
-
await
|
|
570
|
-
await
|
|
569
|
+
await fs8.writeFile(path9.join(outputDir, hashedName2), entryContent);
|
|
570
|
+
await fs8.unlink(indexPath);
|
|
571
571
|
try {
|
|
572
|
-
await
|
|
573
|
-
await
|
|
572
|
+
await fs8.access(indexMapPath);
|
|
573
|
+
await fs8.rename(indexMapPath, path9.join(outputDir, hashedMapName2));
|
|
574
574
|
} catch {
|
|
575
575
|
}
|
|
576
576
|
logger.info(`Entry hashed: ${hashedName2}`);
|
|
@@ -583,11 +583,11 @@ async function contentHashEntry(outputDir) {
|
|
|
583
583
|
/\/\/# sourceMappingURL=bundle-entry\.js\.map/,
|
|
584
584
|
`//# sourceMappingURL=${hashedMapName}`
|
|
585
585
|
);
|
|
586
|
-
await
|
|
587
|
-
await
|
|
586
|
+
await fs8.writeFile(path9.join(outputDir, hashedName), entryContent);
|
|
587
|
+
await fs8.unlink(entryPath);
|
|
588
588
|
try {
|
|
589
|
-
await
|
|
590
|
-
await
|
|
589
|
+
await fs8.access(mapPath);
|
|
590
|
+
await fs8.rename(mapPath, path9.join(outputDir, hashedMapName));
|
|
591
591
|
} catch {
|
|
592
592
|
}
|
|
593
593
|
logger.info(`Entry hashed: ${hashedName}`);
|
|
@@ -599,7 +599,7 @@ async function extractDataRequirements(themePath) {
|
|
|
599
599
|
const requirements = {};
|
|
600
600
|
for (const file of schemaFiles) {
|
|
601
601
|
try {
|
|
602
|
-
const mod = await jiti.import(
|
|
602
|
+
const mod = await jiti.import(path9.join(themePath, file));
|
|
603
603
|
const exports$1 = mod;
|
|
604
604
|
for (const value of Object.values(exports$1)) {
|
|
605
605
|
if (value && typeof value === "object" && typeof value.type === "string" && value.dataRequirements && typeof value.dataRequirements === "object") {
|
|
@@ -618,8 +618,8 @@ async function generateManifest(themeName, themePath, outputDir) {
|
|
|
618
618
|
let version2 = "1.0.0";
|
|
619
619
|
let themeId = themeName;
|
|
620
620
|
try {
|
|
621
|
-
const pkgContent = await
|
|
622
|
-
|
|
621
|
+
const pkgContent = await fs8.readFile(
|
|
622
|
+
path9.join(themePath, "package.json"),
|
|
623
623
|
"utf-8"
|
|
624
624
|
);
|
|
625
625
|
const pkg = JSON.parse(pkgContent);
|
|
@@ -637,7 +637,7 @@ async function generateManifest(themeName, themePath, outputDir) {
|
|
|
637
637
|
const dataRequirements = await extractDataRequirements(themePath);
|
|
638
638
|
let hasThemeConfig = false;
|
|
639
639
|
try {
|
|
640
|
-
await
|
|
640
|
+
await fs8.access(path9.join(themePath, "theme.config.ts"));
|
|
641
641
|
hasThemeConfig = true;
|
|
642
642
|
} catch {
|
|
643
643
|
}
|
|
@@ -678,24 +678,24 @@ async function generateManifest(themeName, themePath, outputDir) {
|
|
|
678
678
|
// Section data requirements for server-side prefetching (keyed by section type)
|
|
679
679
|
dataRequirements
|
|
680
680
|
};
|
|
681
|
-
await
|
|
682
|
-
|
|
681
|
+
await fs8.writeFile(
|
|
682
|
+
path9.join(outputDir, "manifest.json"),
|
|
683
683
|
JSON.stringify(manifest, null, 2)
|
|
684
684
|
);
|
|
685
685
|
}
|
|
686
686
|
async function compileStandaloneTheme(themePath, themeName) {
|
|
687
|
-
const outputDir =
|
|
688
|
-
const bundleEntry =
|
|
689
|
-
const indexEntry =
|
|
687
|
+
const outputDir = path9.join(themePath, "dist");
|
|
688
|
+
const bundleEntry = path9.join(themePath, "bundle-entry.ts");
|
|
689
|
+
const indexEntry = path9.join(themePath, "index.ts");
|
|
690
690
|
let entryPoint = indexEntry;
|
|
691
691
|
try {
|
|
692
|
-
await
|
|
692
|
+
await fs8.access(bundleEntry);
|
|
693
693
|
entryPoint = bundleEntry;
|
|
694
694
|
} catch {
|
|
695
695
|
}
|
|
696
|
-
const shimPath =
|
|
697
|
-
await
|
|
698
|
-
await
|
|
696
|
+
const shimPath = path9.join(outputDir, ".process-shim.js");
|
|
697
|
+
await fs8.mkdir(outputDir, { recursive: true });
|
|
698
|
+
await fs8.writeFile(shimPath, PROCESS_SHIM);
|
|
699
699
|
const buildOptions = {
|
|
700
700
|
entryPoints: [entryPoint],
|
|
701
701
|
bundle: true,
|
|
@@ -745,7 +745,7 @@ async function compileStandaloneTheme(themePath, themeName) {
|
|
|
745
745
|
try {
|
|
746
746
|
const result = await esbuild.build(buildOptions);
|
|
747
747
|
try {
|
|
748
|
-
await
|
|
748
|
+
await fs8.unlink(shimPath);
|
|
749
749
|
} catch {
|
|
750
750
|
}
|
|
751
751
|
await contentHashEntry(outputDir);
|
|
@@ -764,7 +764,7 @@ async function compileStandaloneTheme(themePath, themeName) {
|
|
|
764
764
|
return true;
|
|
765
765
|
} catch (error) {
|
|
766
766
|
try {
|
|
767
|
-
await
|
|
767
|
+
await fs8.unlink(shimPath);
|
|
768
768
|
} catch {
|
|
769
769
|
}
|
|
770
770
|
logger.error(`esbuild compilation failed: ${error}`);
|
|
@@ -772,18 +772,18 @@ async function compileStandaloneTheme(themePath, themeName) {
|
|
|
772
772
|
}
|
|
773
773
|
}
|
|
774
774
|
async function compileStandaloneThemeDev(themePath, themeName) {
|
|
775
|
-
const outputDir =
|
|
776
|
-
const bundleEntry =
|
|
777
|
-
const indexEntry =
|
|
775
|
+
const outputDir = path9.join(themePath, "dist");
|
|
776
|
+
const bundleEntry = path9.join(themePath, "bundle-entry.ts");
|
|
777
|
+
const indexEntry = path9.join(themePath, "index.ts");
|
|
778
778
|
let entryPoint = indexEntry;
|
|
779
779
|
try {
|
|
780
|
-
await
|
|
780
|
+
await fs8.access(bundleEntry);
|
|
781
781
|
entryPoint = bundleEntry;
|
|
782
782
|
} catch {
|
|
783
783
|
}
|
|
784
|
-
const shimPath =
|
|
785
|
-
await
|
|
786
|
-
await
|
|
784
|
+
const shimPath = path9.join(outputDir, ".process-shim.js");
|
|
785
|
+
await fs8.mkdir(outputDir, { recursive: true });
|
|
786
|
+
await fs8.writeFile(shimPath, PROCESS_SHIM);
|
|
787
787
|
const buildOptions = {
|
|
788
788
|
entryPoints: [entryPoint],
|
|
789
789
|
bundle: true,
|
|
@@ -836,18 +836,18 @@ async function compileStandaloneThemeDev(themePath, themeName) {
|
|
|
836
836
|
return { context: context2, outputDir };
|
|
837
837
|
}
|
|
838
838
|
async function compilePreviewRuntime(themePath) {
|
|
839
|
-
const outputDir =
|
|
840
|
-
await
|
|
841
|
-
const outputPath =
|
|
839
|
+
const outputDir = path9.join(themePath, "dist");
|
|
840
|
+
await fs8.mkdir(outputDir, { recursive: true });
|
|
841
|
+
const outputPath = path9.join(outputDir, "preview-runtime.js");
|
|
842
842
|
const locations = [
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
843
|
+
path9.join(__dirname, "..", "preview", "preview-app.tsx"),
|
|
844
|
+
path9.join(__dirname, "preview", "preview-app.tsx"),
|
|
845
|
+
path9.join(__dirname, "..", "..", "src", "preview", "preview-app.tsx")
|
|
846
846
|
];
|
|
847
847
|
let previewEntryPath = null;
|
|
848
848
|
for (const loc of locations) {
|
|
849
849
|
try {
|
|
850
|
-
await
|
|
850
|
+
await fs8.access(loc);
|
|
851
851
|
previewEntryPath = loc;
|
|
852
852
|
break;
|
|
853
853
|
} catch {
|
|
@@ -930,10 +930,10 @@ ${locations.join("\n")}`
|
|
|
930
930
|
if (!lucideScanned) {
|
|
931
931
|
lucideScanned = true;
|
|
932
932
|
const coreSrcCandidates = [
|
|
933
|
-
|
|
934
|
-
|
|
933
|
+
path9.join(themePath, "node_modules", "@onexapis", "core", "src"),
|
|
934
|
+
path9.join(themePath, "..", "..", "packages", "core", "src"),
|
|
935
935
|
// monorepo sibling
|
|
936
|
-
|
|
936
|
+
path9.join(
|
|
937
937
|
__dirname,
|
|
938
938
|
"..",
|
|
939
939
|
"..",
|
|
@@ -948,7 +948,7 @@ ${locations.join("\n")}`
|
|
|
948
948
|
let coreSourceDir = null;
|
|
949
949
|
for (const candidate of coreSrcCandidates) {
|
|
950
950
|
try {
|
|
951
|
-
await
|
|
951
|
+
await fs8.access(candidate);
|
|
952
952
|
coreSourceDir = candidate;
|
|
953
953
|
break;
|
|
954
954
|
} catch {
|
|
@@ -967,21 +967,21 @@ ${locations.join("\n")}`
|
|
|
967
967
|
}
|
|
968
968
|
} else {
|
|
969
969
|
const coreDistCandidates = [
|
|
970
|
-
|
|
970
|
+
path9.join(themePath, "node_modules", "@onexapis", "core", "dist")
|
|
971
971
|
];
|
|
972
972
|
const resolvedDist = await resolveNodeModulesFile(
|
|
973
973
|
__dirname,
|
|
974
|
-
|
|
974
|
+
path9.join("@onexapis", "core", "dist")
|
|
975
975
|
);
|
|
976
976
|
if (resolvedDist) coreDistCandidates.push(resolvedDist);
|
|
977
977
|
for (const candidate of coreDistCandidates) {
|
|
978
978
|
try {
|
|
979
|
-
await
|
|
979
|
+
await fs8.access(candidate);
|
|
980
980
|
const mjsFiles = await glob("*.mjs", { cwd: candidate });
|
|
981
981
|
const importRegex = /import\s*\{([^}]+)\}\s*from\s*["']lucide-react["']/g;
|
|
982
982
|
for (const file of mjsFiles) {
|
|
983
|
-
const content = await
|
|
984
|
-
|
|
983
|
+
const content = await fs8.readFile(
|
|
984
|
+
path9.join(candidate, file),
|
|
985
985
|
"utf-8"
|
|
986
986
|
);
|
|
987
987
|
for (const match of content.matchAll(importRegex)) {
|
|
@@ -1036,7 +1036,7 @@ export default new Proxy({}, { get: (_, name) => name === '__esModule' ? true :
|
|
|
1036
1036
|
const req = createRequire(import.meta.url || __filename);
|
|
1037
1037
|
const cjsPath = req.resolve("framer-motion");
|
|
1038
1038
|
const pkgDir = cjsPath.replace(/[/\\]dist[/\\].*$/, "");
|
|
1039
|
-
const esmEntry =
|
|
1039
|
+
const esmEntry = path9.join(pkgDir, "dist", "es", "index.mjs");
|
|
1040
1040
|
const { existsSync } = await import('fs');
|
|
1041
1041
|
if (existsSync(esmEntry)) {
|
|
1042
1042
|
return { path: esmEntry, namespace: "file" };
|
|
@@ -1135,8 +1135,8 @@ export function headers() { return new Headers(); }
|
|
|
1135
1135
|
});
|
|
1136
1136
|
}
|
|
1137
1137
|
};
|
|
1138
|
-
const shimPath =
|
|
1139
|
-
await
|
|
1138
|
+
const shimPath = path9.join(outputDir, ".process-shim-preview.js");
|
|
1139
|
+
await fs8.writeFile(shimPath, PROCESS_SHIM);
|
|
1140
1140
|
await esbuild.build({
|
|
1141
1141
|
entryPoints: [previewEntryPath],
|
|
1142
1142
|
bundle: true,
|
|
@@ -1171,7 +1171,7 @@ export function headers() { return new Headers(); }
|
|
|
1171
1171
|
}
|
|
1172
1172
|
});
|
|
1173
1173
|
try {
|
|
1174
|
-
await
|
|
1174
|
+
await fs8.unlink(shimPath);
|
|
1175
1175
|
} catch {
|
|
1176
1176
|
}
|
|
1177
1177
|
return outputPath;
|
|
@@ -1304,18 +1304,18 @@ async function renderTemplate(templatePath, data) {
|
|
|
1304
1304
|
return ejs.render(template, data);
|
|
1305
1305
|
}
|
|
1306
1306
|
async function writeFile(filePath, content) {
|
|
1307
|
-
await fs.ensureDir(
|
|
1307
|
+
await fs.ensureDir(path9.dirname(filePath));
|
|
1308
1308
|
await fs.writeFile(filePath, content, "utf-8");
|
|
1309
1309
|
}
|
|
1310
1310
|
function getTemplatesDir() {
|
|
1311
1311
|
const locations = [
|
|
1312
|
-
|
|
1312
|
+
path9.join(__dirname, "../../templates"),
|
|
1313
1313
|
// Development
|
|
1314
|
-
|
|
1314
|
+
path9.join(__dirname, "../templates"),
|
|
1315
1315
|
// Production (dist/)
|
|
1316
|
-
|
|
1316
|
+
path9.join(process.cwd(), "templates"),
|
|
1317
1317
|
// Fallback
|
|
1318
|
-
|
|
1318
|
+
path9.join(process.cwd(), "packages/cli/templates")
|
|
1319
1319
|
// Monorepo
|
|
1320
1320
|
];
|
|
1321
1321
|
for (const location of locations) {
|
|
@@ -1327,7 +1327,7 @@ function getTemplatesDir() {
|
|
|
1327
1327
|
}
|
|
1328
1328
|
async function copyTemplate(templateName, targetDir, data) {
|
|
1329
1329
|
const templatesDir = getTemplatesDir();
|
|
1330
|
-
const templateDir =
|
|
1330
|
+
const templateDir = path9.join(templatesDir, templateName);
|
|
1331
1331
|
if (!fs.existsSync(templateDir)) {
|
|
1332
1332
|
throw new Error(
|
|
1333
1333
|
`Template "${templateName}" not found at ${templateDir}. Available templates: ${fs.readdirSync(templatesDir).join(", ")}`
|
|
@@ -1336,8 +1336,8 @@ async function copyTemplate(templateName, targetDir, data) {
|
|
|
1336
1336
|
await fs.ensureDir(targetDir);
|
|
1337
1337
|
const files = await fs.readdir(templateDir);
|
|
1338
1338
|
for (const file of files) {
|
|
1339
|
-
const templatePath =
|
|
1340
|
-
const targetPath =
|
|
1339
|
+
const templatePath = path9.join(templateDir, file);
|
|
1340
|
+
const targetPath = path9.join(targetDir, file);
|
|
1341
1341
|
const stat = await fs.stat(templatePath);
|
|
1342
1342
|
if (stat.isDirectory()) {
|
|
1343
1343
|
await copyTemplateDir(templatePath, targetPath, data);
|
|
@@ -1354,8 +1354,8 @@ async function copyTemplateDir(templateDir, targetDir, data) {
|
|
|
1354
1354
|
await fs.ensureDir(targetDir);
|
|
1355
1355
|
const files = await fs.readdir(templateDir);
|
|
1356
1356
|
for (const file of files) {
|
|
1357
|
-
const templatePath =
|
|
1358
|
-
const targetPath =
|
|
1357
|
+
const templatePath = path9.join(templateDir, file);
|
|
1358
|
+
const targetPath = path9.join(targetDir, file);
|
|
1359
1359
|
const stat = await fs.stat(templatePath);
|
|
1360
1360
|
if (stat.isDirectory()) {
|
|
1361
1361
|
await copyTemplateDir(templatePath, targetPath, data);
|
|
@@ -1370,32 +1370,32 @@ async function copyTemplateDir(templateDir, targetDir, data) {
|
|
|
1370
1370
|
}
|
|
1371
1371
|
function getProjectRoot() {
|
|
1372
1372
|
let currentDir = process.cwd();
|
|
1373
|
-
while (currentDir !==
|
|
1374
|
-
const packageJsonPath =
|
|
1373
|
+
while (currentDir !== path9.parse(currentDir).root) {
|
|
1374
|
+
const packageJsonPath = path9.join(currentDir, "package.json");
|
|
1375
1375
|
if (fs.existsSync(packageJsonPath)) {
|
|
1376
1376
|
const packageJson = fs.readJsonSync(packageJsonPath);
|
|
1377
|
-
if (packageJson.workspaces || fs.existsSync(
|
|
1377
|
+
if (packageJson.workspaces || fs.existsSync(path9.join(currentDir, "src/themes")) || fs.existsSync(path9.join(currentDir, "themes"))) {
|
|
1378
1378
|
return currentDir;
|
|
1379
1379
|
}
|
|
1380
1380
|
}
|
|
1381
|
-
currentDir =
|
|
1381
|
+
currentDir = path9.dirname(currentDir);
|
|
1382
1382
|
}
|
|
1383
1383
|
return process.cwd();
|
|
1384
1384
|
}
|
|
1385
1385
|
function getThemesDir() {
|
|
1386
1386
|
const root = getProjectRoot();
|
|
1387
|
-
if (fs.existsSync(
|
|
1388
|
-
return
|
|
1389
|
-
if (fs.existsSync(
|
|
1390
|
-
return
|
|
1391
|
-
return
|
|
1387
|
+
if (fs.existsSync(path9.join(root, "themes")))
|
|
1388
|
+
return path9.join(root, "themes");
|
|
1389
|
+
if (fs.existsSync(path9.join(root, "src/themes")))
|
|
1390
|
+
return path9.join(root, "src/themes");
|
|
1391
|
+
return path9.dirname(root);
|
|
1392
1392
|
}
|
|
1393
1393
|
function getFeaturesDir() {
|
|
1394
|
-
return
|
|
1394
|
+
return path9.join(getProjectRoot(), "src/features");
|
|
1395
1395
|
}
|
|
1396
1396
|
function isOneXProject() {
|
|
1397
1397
|
const root = getProjectRoot();
|
|
1398
|
-
return fs.existsSync(
|
|
1398
|
+
return fs.existsSync(path9.join(root, "themes")) || fs.existsSync(path9.join(root, "src/themes")) || fs.existsSync(path9.join(root, "theme.config.ts")) || fs.existsSync(path9.join(root, "bundle-entry.ts"));
|
|
1399
1399
|
}
|
|
1400
1400
|
function ensureOneXProject() {
|
|
1401
1401
|
if (!isOneXProject()) {
|
|
@@ -1411,13 +1411,13 @@ function listThemes() {
|
|
|
1411
1411
|
return [];
|
|
1412
1412
|
}
|
|
1413
1413
|
return fs.readdirSync(themesDir).filter((name) => {
|
|
1414
|
-
const themePath =
|
|
1415
|
-
return fs.statSync(themePath).isDirectory() && (fs.existsSync(
|
|
1414
|
+
const themePath = path9.join(themesDir, name);
|
|
1415
|
+
return fs.statSync(themePath).isDirectory() && (fs.existsSync(path9.join(themePath, "theme.config.ts")) || fs.existsSync(path9.join(themePath, "bundle-entry.ts")) || fs.existsSync(path9.join(themePath, "manifest.ts")));
|
|
1416
1416
|
});
|
|
1417
1417
|
}
|
|
1418
1418
|
function themeExists(themeName) {
|
|
1419
|
-
const themePath =
|
|
1420
|
-
return fs.existsSync(themePath) && (fs.existsSync(
|
|
1419
|
+
const themePath = path9.join(getThemesDir(), themeName);
|
|
1420
|
+
return fs.existsSync(themePath) && (fs.existsSync(path9.join(themePath, "theme.config.ts")) || fs.existsSync(path9.join(themePath, "bundle-entry.ts")) || fs.existsSync(path9.join(themePath, "manifest.ts")));
|
|
1421
1421
|
}
|
|
1422
1422
|
function detectPackageManager() {
|
|
1423
1423
|
const userAgent = process.env.npm_config_user_agent || "";
|
|
@@ -1425,22 +1425,24 @@ function detectPackageManager() {
|
|
|
1425
1425
|
if (userAgent.includes("yarn")) return "yarn";
|
|
1426
1426
|
if (userAgent.includes("bun")) return "bun";
|
|
1427
1427
|
const cwd = process.cwd();
|
|
1428
|
-
if (fs.existsSync(
|
|
1429
|
-
if (fs.existsSync(
|
|
1430
|
-
if (fs.existsSync(
|
|
1428
|
+
if (fs.existsSync(path9.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
1429
|
+
if (fs.existsSync(path9.join(cwd, "yarn.lock"))) return "yarn";
|
|
1430
|
+
if (fs.existsSync(path9.join(cwd, "bun.lockb"))) return "bun";
|
|
1431
1431
|
return "npm";
|
|
1432
1432
|
}
|
|
1433
1433
|
async function installDependencies(projectPath, packageManager = "npm") {
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1434
|
+
return new Promise((resolve, reject) => {
|
|
1435
|
+
try {
|
|
1436
|
+
const installCmd = packageManager === "yarn" ? "yarn" : `${packageManager} install`;
|
|
1437
|
+
execSync(installCmd, {
|
|
1438
|
+
cwd: projectPath,
|
|
1439
|
+
stdio: "inherit"
|
|
1440
|
+
});
|
|
1441
|
+
resolve();
|
|
1442
|
+
} catch (error) {
|
|
1443
|
+
reject(error);
|
|
1444
|
+
}
|
|
1438
1445
|
});
|
|
1439
|
-
if (result.status !== 0) {
|
|
1440
|
-
throw new Error(
|
|
1441
|
-
`${packageManager} install failed with exit code ${result.status}`
|
|
1442
|
-
);
|
|
1443
|
-
}
|
|
1444
1446
|
}
|
|
1445
1447
|
|
|
1446
1448
|
// src/commands/init.ts
|
|
@@ -1474,8 +1476,8 @@ function getValidCategories() {
|
|
|
1474
1476
|
"contact"
|
|
1475
1477
|
];
|
|
1476
1478
|
}
|
|
1477
|
-
var AUTH_DIR =
|
|
1478
|
-
var AUTH_FILE =
|
|
1479
|
+
var AUTH_DIR = path9.join(os.homedir(), ".onexthm");
|
|
1480
|
+
var AUTH_FILE = path9.join(AUTH_DIR, "auth.json");
|
|
1479
1481
|
function getApiUrl() {
|
|
1480
1482
|
return process.env.ONEXTHM_API_URL || process.env.NEXT_PUBLIC_API_URL || "https://platform-dev.onexeos.com";
|
|
1481
1483
|
}
|
|
@@ -1588,70 +1590,6 @@ function parseJwtClaims(idToken) {
|
|
|
1588
1590
|
return {};
|
|
1589
1591
|
}
|
|
1590
1592
|
}
|
|
1591
|
-
function getNpxCommand() {
|
|
1592
|
-
return process.platform === "win32" ? "npx.cmd" : "npx";
|
|
1593
|
-
}
|
|
1594
|
-
function getDefaultMcpConfig() {
|
|
1595
|
-
return {
|
|
1596
|
-
mcpServers: {
|
|
1597
|
-
onexthm: {
|
|
1598
|
-
command: getNpxCommand(),
|
|
1599
|
-
args: ["-y", "@onexapis/theme-mcp"]
|
|
1600
|
-
}
|
|
1601
|
-
}
|
|
1602
|
-
};
|
|
1603
|
-
}
|
|
1604
|
-
function ensureMcpJson(projectPath, figmaApiKey) {
|
|
1605
|
-
const mcpJsonPath = path10.join(projectPath, ".mcp.json");
|
|
1606
|
-
const npx = getNpxCommand();
|
|
1607
|
-
let mcpConfig;
|
|
1608
|
-
if (fs4.existsSync(mcpJsonPath)) {
|
|
1609
|
-
try {
|
|
1610
|
-
mcpConfig = JSON.parse(fs4.readFileSync(mcpJsonPath, "utf-8"));
|
|
1611
|
-
if (!mcpConfig.mcpServers) {
|
|
1612
|
-
mcpConfig.mcpServers = {};
|
|
1613
|
-
}
|
|
1614
|
-
} catch {
|
|
1615
|
-
mcpConfig = getDefaultMcpConfig();
|
|
1616
|
-
}
|
|
1617
|
-
} else {
|
|
1618
|
-
mcpConfig = getDefaultMcpConfig();
|
|
1619
|
-
}
|
|
1620
|
-
mcpConfig.mcpServers.onexthm = {
|
|
1621
|
-
command: npx,
|
|
1622
|
-
args: ["-y", "@onexapis/theme-mcp"]
|
|
1623
|
-
};
|
|
1624
|
-
if (figmaApiKey) {
|
|
1625
|
-
mcpConfig.mcpServers.figma = {
|
|
1626
|
-
command: npx,
|
|
1627
|
-
args: [
|
|
1628
|
-
"-y",
|
|
1629
|
-
"figma-developer-mcp",
|
|
1630
|
-
`--figma-api-key=${figmaApiKey}`,
|
|
1631
|
-
"--stdio"
|
|
1632
|
-
]
|
|
1633
|
-
};
|
|
1634
|
-
} else {
|
|
1635
|
-
delete mcpConfig.mcpServers.figma;
|
|
1636
|
-
}
|
|
1637
|
-
fs4.writeFileSync(mcpJsonPath, JSON.stringify(mcpConfig, null, 2) + "\n");
|
|
1638
|
-
ensureThemeMcpDependency(projectPath);
|
|
1639
|
-
}
|
|
1640
|
-
function ensureThemeMcpDependency(projectPath) {
|
|
1641
|
-
const pkgJsonPath = path10.join(projectPath, "package.json");
|
|
1642
|
-
if (!fs4.existsSync(pkgJsonPath)) return;
|
|
1643
|
-
try {
|
|
1644
|
-
const pkg = JSON.parse(fs4.readFileSync(pkgJsonPath, "utf-8"));
|
|
1645
|
-
if (!pkg.devDependencies) {
|
|
1646
|
-
pkg.devDependencies = {};
|
|
1647
|
-
}
|
|
1648
|
-
if (!pkg.devDependencies["@onexapis/theme-mcp"]) {
|
|
1649
|
-
pkg.devDependencies["@onexapis/theme-mcp"] = "^0.1.0";
|
|
1650
|
-
fs4.writeFileSync(pkgJsonPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
1651
|
-
}
|
|
1652
|
-
} catch {
|
|
1653
|
-
}
|
|
1654
|
-
}
|
|
1655
1593
|
|
|
1656
1594
|
// src/commands/init.ts
|
|
1657
1595
|
async function initCommand(projectName, options = {}) {
|
|
@@ -1669,7 +1607,7 @@ async function initCommand(projectName, options = {}) {
|
|
|
1669
1607
|
if (!validateThemeName(kebabName)) {
|
|
1670
1608
|
return "Invalid project name. Use lowercase letters, numbers, and hyphens only.";
|
|
1671
1609
|
}
|
|
1672
|
-
if (
|
|
1610
|
+
if (fs3.existsSync(path9.join(process.cwd(), kebabName))) {
|
|
1673
1611
|
return `Directory "${kebabName}" already exists`;
|
|
1674
1612
|
}
|
|
1675
1613
|
return true;
|
|
@@ -1680,8 +1618,8 @@ async function initCommand(projectName, options = {}) {
|
|
|
1680
1618
|
} else {
|
|
1681
1619
|
name = toKebabCase(projectName);
|
|
1682
1620
|
}
|
|
1683
|
-
const projectPath =
|
|
1684
|
-
if (
|
|
1621
|
+
const projectPath = path9.join(process.cwd(), name);
|
|
1622
|
+
if (fs3.existsSync(projectPath)) {
|
|
1685
1623
|
logger.error(`Directory "${name}" already exists.`);
|
|
1686
1624
|
process.exit(1);
|
|
1687
1625
|
}
|
|
@@ -1787,7 +1725,7 @@ async function initCommand(projectName, options = {}) {
|
|
|
1787
1725
|
}
|
|
1788
1726
|
logger.startSpinner("Creating project structure...");
|
|
1789
1727
|
try {
|
|
1790
|
-
|
|
1728
|
+
fs3.mkdirSync(projectPath, { recursive: true });
|
|
1791
1729
|
await copyTemplate(template, projectPath, data);
|
|
1792
1730
|
await renameThemeInFiles(
|
|
1793
1731
|
projectPath,
|
|
@@ -1796,14 +1734,28 @@ async function initCommand(projectName, options = {}) {
|
|
|
1796
1734
|
description,
|
|
1797
1735
|
author
|
|
1798
1736
|
);
|
|
1799
|
-
|
|
1737
|
+
const mcpJsonPath = path9.join(projectPath, ".mcp.json");
|
|
1738
|
+
if (fs3.existsSync(mcpJsonPath)) {
|
|
1739
|
+
let mcpContent = fs3.readFileSync(mcpJsonPath, "utf-8");
|
|
1740
|
+
if (figmaApiKey) {
|
|
1741
|
+
mcpContent = mcpContent.replace("__FIGMA_API_KEY__", figmaApiKey);
|
|
1742
|
+
} else {
|
|
1743
|
+
try {
|
|
1744
|
+
const mcpJson = JSON.parse(mcpContent);
|
|
1745
|
+
delete mcpJson.mcpServers.figma;
|
|
1746
|
+
mcpContent = JSON.stringify(mcpJson, null, 2) + "\n";
|
|
1747
|
+
} catch {
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
fs3.writeFileSync(mcpJsonPath, mcpContent, "utf-8");
|
|
1751
|
+
}
|
|
1800
1752
|
logger.stopSpinner(true, "Project structure created!");
|
|
1801
1753
|
if (options.git) {
|
|
1802
1754
|
logger.startSpinner("Initializing git repository...");
|
|
1803
1755
|
try {
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1756
|
+
execSync("git init", { cwd: projectPath, stdio: "ignore" });
|
|
1757
|
+
execSync("git add .", { cwd: projectPath, stdio: "ignore" });
|
|
1758
|
+
execSync('git commit -m "Initial commit from onexthm init"', {
|
|
1807
1759
|
cwd: projectPath,
|
|
1808
1760
|
stdio: "ignore"
|
|
1809
1761
|
});
|
|
@@ -1855,16 +1807,16 @@ async function initCommand(projectName, options = {}) {
|
|
|
1855
1807
|
logger.error(
|
|
1856
1808
|
error instanceof Error ? error.message : "Unknown error occurred"
|
|
1857
1809
|
);
|
|
1858
|
-
if (
|
|
1859
|
-
|
|
1810
|
+
if (fs3.existsSync(projectPath)) {
|
|
1811
|
+
fs3.rmSync(projectPath, { recursive: true, force: true });
|
|
1860
1812
|
}
|
|
1861
1813
|
process.exit(1);
|
|
1862
1814
|
}
|
|
1863
1815
|
}
|
|
1864
1816
|
async function renameThemeInFiles(projectPath, themeName, displayName, description, author) {
|
|
1865
|
-
const configPath =
|
|
1866
|
-
if (
|
|
1867
|
-
let content =
|
|
1817
|
+
const configPath = path9.join(projectPath, "theme.config.ts");
|
|
1818
|
+
if (fs3.existsSync(configPath)) {
|
|
1819
|
+
let content = fs3.readFileSync(configPath, "utf-8");
|
|
1868
1820
|
content = content.replace(
|
|
1869
1821
|
/name: "My Simple Theme"/,
|
|
1870
1822
|
`name: "${displayName}"`
|
|
@@ -1873,11 +1825,11 @@ async function renameThemeInFiles(projectPath, themeName, displayName, descripti
|
|
|
1873
1825
|
/description: ".*?"/,
|
|
1874
1826
|
`description: "${description}"`
|
|
1875
1827
|
);
|
|
1876
|
-
|
|
1828
|
+
fs3.writeFileSync(configPath, content, "utf-8");
|
|
1877
1829
|
}
|
|
1878
|
-
const pkgPath =
|
|
1879
|
-
if (
|
|
1880
|
-
let content =
|
|
1830
|
+
const pkgPath = path9.join(projectPath, "package.json");
|
|
1831
|
+
if (fs3.existsSync(pkgPath)) {
|
|
1832
|
+
let content = fs3.readFileSync(pkgPath, "utf-8");
|
|
1881
1833
|
content = content.replace(
|
|
1882
1834
|
/@onex-themes\/my-simple/g,
|
|
1883
1835
|
`@onex-themes/${themeName}`
|
|
@@ -1886,7 +1838,7 @@ async function renameThemeInFiles(projectPath, themeName, displayName, descripti
|
|
|
1886
1838
|
/"description": ".*?"/,
|
|
1887
1839
|
`"description": "${description}"`
|
|
1888
1840
|
);
|
|
1889
|
-
|
|
1841
|
+
fs3.writeFileSync(pkgPath, content, "utf-8");
|
|
1890
1842
|
}
|
|
1891
1843
|
}
|
|
1892
1844
|
|
|
@@ -1897,10 +1849,10 @@ async function createSectionCommand(name, options) {
|
|
|
1897
1849
|
ensureOneXProject();
|
|
1898
1850
|
if (!options.theme) {
|
|
1899
1851
|
const isStandaloneTheme = ["theme.config.ts", "bundle-entry.ts"].some(
|
|
1900
|
-
(f) => fs.existsSync(
|
|
1852
|
+
(f) => fs.existsSync(path9.join(process.cwd(), f))
|
|
1901
1853
|
);
|
|
1902
1854
|
if (isStandaloneTheme) {
|
|
1903
|
-
options.theme =
|
|
1855
|
+
options.theme = path9.basename(process.cwd());
|
|
1904
1856
|
}
|
|
1905
1857
|
}
|
|
1906
1858
|
const sectionName = toKebabCase(name);
|
|
@@ -1963,35 +1915,35 @@ async function createSectionCommand(name, options) {
|
|
|
1963
1915
|
};
|
|
1964
1916
|
logger.startSpinner("Creating section files...");
|
|
1965
1917
|
try {
|
|
1966
|
-
const themePath =
|
|
1967
|
-
const sectionPath =
|
|
1918
|
+
const themePath = path9.join(getThemesDir(), themeName);
|
|
1919
|
+
const sectionPath = path9.join(themePath, "sections", sectionName);
|
|
1968
1920
|
const schemaContent = generateSectionSchema(data);
|
|
1969
1921
|
await writeFile(
|
|
1970
|
-
|
|
1922
|
+
path9.join(sectionPath, `${sectionName}.schema.ts`),
|
|
1971
1923
|
schemaContent
|
|
1972
1924
|
);
|
|
1973
1925
|
if (createTemplate) {
|
|
1974
1926
|
const templateContent = generateSectionTemplate(data);
|
|
1975
1927
|
await writeFile(
|
|
1976
|
-
|
|
1928
|
+
path9.join(sectionPath, `${sectionName}-default.tsx`),
|
|
1977
1929
|
templateContent
|
|
1978
1930
|
);
|
|
1979
1931
|
}
|
|
1980
1932
|
const indexContent = generateSectionIndex(data, createTemplate);
|
|
1981
|
-
await writeFile(
|
|
1933
|
+
await writeFile(path9.join(sectionPath, "index.ts"), indexContent);
|
|
1982
1934
|
logger.stopSpinner(true, "Section files created successfully!");
|
|
1983
1935
|
logger.newLine();
|
|
1984
1936
|
logger.section("Next steps:");
|
|
1985
1937
|
logger.log(
|
|
1986
|
-
` 1. Edit schema: ${
|
|
1938
|
+
` 1. Edit schema: ${path9.relative(process.cwd(), path9.join(sectionPath, `${sectionName}.schema.ts`))}`
|
|
1987
1939
|
);
|
|
1988
1940
|
if (createTemplate) {
|
|
1989
1941
|
logger.log(
|
|
1990
|
-
` 2. Edit template: ${
|
|
1942
|
+
` 2. Edit template: ${path9.relative(process.cwd(), path9.join(sectionPath, `${sectionName}-default.tsx`))}`
|
|
1991
1943
|
);
|
|
1992
1944
|
}
|
|
1993
1945
|
logger.log(
|
|
1994
|
-
` 3. Add to theme manifest: ${
|
|
1946
|
+
` 3. Add to theme manifest: ${path9.relative(process.cwd(), path9.join(themePath, "manifest.ts"))}`
|
|
1995
1947
|
);
|
|
1996
1948
|
logger.newLine();
|
|
1997
1949
|
logger.success("Section created successfully!");
|
|
@@ -2139,10 +2091,10 @@ async function createBlockCommand(name, options) {
|
|
|
2139
2091
|
ensureOneXProject();
|
|
2140
2092
|
if (!options.theme) {
|
|
2141
2093
|
const isStandaloneTheme = ["theme.config.ts", "bundle-entry.ts"].some(
|
|
2142
|
-
(f) => fs.existsSync(
|
|
2094
|
+
(f) => fs.existsSync(path9.join(process.cwd(), f))
|
|
2143
2095
|
);
|
|
2144
2096
|
if (isStandaloneTheme) {
|
|
2145
|
-
options.theme =
|
|
2097
|
+
options.theme = path9.basename(process.cwd());
|
|
2146
2098
|
}
|
|
2147
2099
|
}
|
|
2148
2100
|
const blockName = toKebabCase(name);
|
|
@@ -2217,24 +2169,24 @@ async function createBlockCommand(name, options) {
|
|
|
2217
2169
|
};
|
|
2218
2170
|
logger.startSpinner("Creating block files...");
|
|
2219
2171
|
try {
|
|
2220
|
-
const blockPath = scope === "shared" ?
|
|
2172
|
+
const blockPath = scope === "shared" ? path9.join(getFeaturesDir(), "blocks", blockName) : path9.join(getThemesDir(), themeName, "blocks", blockName);
|
|
2221
2173
|
const schemaContent = generateBlockSchema(data);
|
|
2222
2174
|
await writeFile(
|
|
2223
|
-
|
|
2175
|
+
path9.join(blockPath, `${blockName}.schema.ts`),
|
|
2224
2176
|
schemaContent
|
|
2225
2177
|
);
|
|
2226
2178
|
const componentContent = generateBlockComponent(data);
|
|
2227
|
-
await writeFile(
|
|
2179
|
+
await writeFile(path9.join(blockPath, `${blockName}.tsx`), componentContent);
|
|
2228
2180
|
const indexContent = generateBlockIndex(data);
|
|
2229
|
-
await writeFile(
|
|
2181
|
+
await writeFile(path9.join(blockPath, "index.ts"), indexContent);
|
|
2230
2182
|
logger.stopSpinner(true, "Block files created successfully!");
|
|
2231
2183
|
logger.newLine();
|
|
2232
2184
|
logger.section("Next steps:");
|
|
2233
2185
|
logger.log(
|
|
2234
|
-
` 1. Edit schema: ${
|
|
2186
|
+
` 1. Edit schema: ${path9.relative(process.cwd(), path9.join(blockPath, `${blockName}.schema.ts`))}`
|
|
2235
2187
|
);
|
|
2236
2188
|
logger.log(
|
|
2237
|
-
` 2. Edit component: ${
|
|
2189
|
+
` 2. Edit component: ${path9.relative(process.cwd(), path9.join(blockPath, `${blockName}.tsx`))}`
|
|
2238
2190
|
);
|
|
2239
2191
|
logger.log(
|
|
2240
2192
|
` 3. Register in block registry: src/lib/registry/block-registry.ts`
|
|
@@ -2412,31 +2364,31 @@ async function createComponentCommand(name, options) {
|
|
|
2412
2364
|
};
|
|
2413
2365
|
logger.startSpinner("Creating component files...");
|
|
2414
2366
|
try {
|
|
2415
|
-
const componentPath =
|
|
2367
|
+
const componentPath = path9.join(
|
|
2416
2368
|
getFeaturesDir(),
|
|
2417
2369
|
"components",
|
|
2418
2370
|
componentName
|
|
2419
2371
|
);
|
|
2420
2372
|
const schemaContent = generateComponentSchema(data);
|
|
2421
2373
|
await writeFile(
|
|
2422
|
-
|
|
2374
|
+
path9.join(componentPath, `${componentName}.schema.ts`),
|
|
2423
2375
|
schemaContent
|
|
2424
2376
|
);
|
|
2425
2377
|
const componentContent = generateComponent(data);
|
|
2426
2378
|
await writeFile(
|
|
2427
|
-
|
|
2379
|
+
path9.join(componentPath, `${componentName}.tsx`),
|
|
2428
2380
|
componentContent
|
|
2429
2381
|
);
|
|
2430
2382
|
const indexContent = generateComponentIndex(data);
|
|
2431
|
-
await writeFile(
|
|
2383
|
+
await writeFile(path9.join(componentPath, "index.ts"), indexContent);
|
|
2432
2384
|
logger.stopSpinner(true, "Component files created successfully!");
|
|
2433
2385
|
logger.newLine();
|
|
2434
2386
|
logger.section("Next steps:");
|
|
2435
2387
|
logger.log(
|
|
2436
|
-
` 1. Edit schema: ${
|
|
2388
|
+
` 1. Edit schema: ${path9.relative(process.cwd(), path9.join(componentPath, `${componentName}.schema.ts`))}`
|
|
2437
2389
|
);
|
|
2438
2390
|
logger.log(
|
|
2439
|
-
` 2. Edit component: ${
|
|
2391
|
+
` 2. Edit component: ${path9.relative(process.cwd(), path9.join(componentPath, `${componentName}.tsx`))}`
|
|
2440
2392
|
);
|
|
2441
2393
|
logger.log(
|
|
2442
2394
|
` 3. Register in component registry: src/lib/registry/component-registry.ts`
|
|
@@ -2593,13 +2545,13 @@ async function listSections(themeFilter) {
|
|
|
2593
2545
|
return;
|
|
2594
2546
|
}
|
|
2595
2547
|
for (const theme of themes) {
|
|
2596
|
-
const sectionsDir =
|
|
2548
|
+
const sectionsDir = path9.join(getThemesDir(), theme, "sections");
|
|
2597
2549
|
if (!fs.existsSync(sectionsDir)) {
|
|
2598
2550
|
continue;
|
|
2599
2551
|
}
|
|
2600
2552
|
const sections = fs.readdirSync(sectionsDir).filter((name) => {
|
|
2601
|
-
const sectionPath =
|
|
2602
|
-
return fs.statSync(sectionPath).isDirectory() && fs.existsSync(
|
|
2553
|
+
const sectionPath = path9.join(sectionsDir, name);
|
|
2554
|
+
return fs.statSync(sectionPath).isDirectory() && fs.existsSync(path9.join(sectionPath, "index.ts"));
|
|
2603
2555
|
});
|
|
2604
2556
|
if (sections.length > 0) {
|
|
2605
2557
|
logger.log(chalk4.cyan(`
|
|
@@ -2613,11 +2565,11 @@ async function listSections(themeFilter) {
|
|
|
2613
2565
|
}
|
|
2614
2566
|
async function listBlocks(themeFilter) {
|
|
2615
2567
|
logger.section("\u{1F9F1} Blocks");
|
|
2616
|
-
const sharedBlocksDir =
|
|
2568
|
+
const sharedBlocksDir = path9.join(getFeaturesDir(), "blocks");
|
|
2617
2569
|
if (fs.existsSync(sharedBlocksDir)) {
|
|
2618
2570
|
const sharedBlocks = fs.readdirSync(sharedBlocksDir).filter((name) => {
|
|
2619
|
-
const blockPath =
|
|
2620
|
-
return fs.statSync(blockPath).isDirectory() && fs.existsSync(
|
|
2571
|
+
const blockPath = path9.join(sharedBlocksDir, name);
|
|
2572
|
+
return fs.statSync(blockPath).isDirectory() && fs.existsSync(path9.join(blockPath, "index.ts"));
|
|
2621
2573
|
});
|
|
2622
2574
|
if (sharedBlocks.length > 0) {
|
|
2623
2575
|
logger.log(chalk4.cyan("\n Shared:"));
|
|
@@ -2628,13 +2580,13 @@ async function listBlocks(themeFilter) {
|
|
|
2628
2580
|
}
|
|
2629
2581
|
const themes = themeFilter ? [themeFilter] : listThemes();
|
|
2630
2582
|
for (const theme of themes) {
|
|
2631
|
-
const blocksDir =
|
|
2583
|
+
const blocksDir = path9.join(getThemesDir(), theme, "blocks");
|
|
2632
2584
|
if (!fs.existsSync(blocksDir)) {
|
|
2633
2585
|
continue;
|
|
2634
2586
|
}
|
|
2635
2587
|
const blocks = fs.readdirSync(blocksDir).filter((name) => {
|
|
2636
|
-
const blockPath =
|
|
2637
|
-
return fs.statSync(blockPath).isDirectory() && fs.existsSync(
|
|
2588
|
+
const blockPath = path9.join(blocksDir, name);
|
|
2589
|
+
return fs.statSync(blockPath).isDirectory() && fs.existsSync(path9.join(blockPath, "index.ts"));
|
|
2638
2590
|
});
|
|
2639
2591
|
if (blocks.length > 0) {
|
|
2640
2592
|
logger.log(chalk4.cyan(`
|
|
@@ -2648,14 +2600,14 @@ async function listBlocks(themeFilter) {
|
|
|
2648
2600
|
}
|
|
2649
2601
|
async function listComponents() {
|
|
2650
2602
|
logger.section("\u2699\uFE0F Components");
|
|
2651
|
-
const componentsDir =
|
|
2603
|
+
const componentsDir = path9.join(getFeaturesDir(), "components");
|
|
2652
2604
|
if (!fs.existsSync(componentsDir)) {
|
|
2653
2605
|
logger.warning("No components directory found");
|
|
2654
2606
|
return;
|
|
2655
2607
|
}
|
|
2656
2608
|
const components = fs.readdirSync(componentsDir).filter((name) => {
|
|
2657
|
-
const componentPath =
|
|
2658
|
-
return fs.statSync(componentPath).isDirectory() && fs.existsSync(
|
|
2609
|
+
const componentPath = path9.join(componentsDir, name);
|
|
2610
|
+
return fs.statSync(componentPath).isDirectory() && fs.existsSync(path9.join(componentPath, "index.ts"));
|
|
2659
2611
|
});
|
|
2660
2612
|
if (components.length === 0) {
|
|
2661
2613
|
logger.warning("No components found");
|
|
@@ -2676,11 +2628,11 @@ async function listThemesInfo() {
|
|
|
2676
2628
|
}
|
|
2677
2629
|
logger.log("");
|
|
2678
2630
|
for (const theme of themes) {
|
|
2679
|
-
const themeDir =
|
|
2631
|
+
const themeDir = path9.join(getThemesDir(), theme);
|
|
2680
2632
|
const candidates = ["theme.config.ts", "bundle-entry.ts", "manifest.ts"];
|
|
2681
2633
|
let manifestContent = "";
|
|
2682
2634
|
for (const candidate of candidates) {
|
|
2683
|
-
const candidatePath =
|
|
2635
|
+
const candidatePath = path9.join(themeDir, candidate);
|
|
2684
2636
|
if (fs.existsSync(candidatePath)) {
|
|
2685
2637
|
manifestContent = fs.readFileSync(candidatePath, "utf-8");
|
|
2686
2638
|
break;
|
|
@@ -2718,9 +2670,9 @@ async function validateCommand(options) {
|
|
|
2718
2670
|
"theme.config.ts",
|
|
2719
2671
|
"bundle-entry.ts",
|
|
2720
2672
|
"manifest.ts"
|
|
2721
|
-
].some((f) => fs.existsSync(
|
|
2673
|
+
].some((f) => fs.existsSync(path9.join(process.cwd(), f)));
|
|
2722
2674
|
if (isThemeDir) {
|
|
2723
|
-
themeToValidate =
|
|
2675
|
+
themeToValidate = path9.basename(process.cwd());
|
|
2724
2676
|
logger.info(`Validating current theme: ${themeToValidate}`);
|
|
2725
2677
|
} else {
|
|
2726
2678
|
logger.error(
|
|
@@ -2729,11 +2681,11 @@ async function validateCommand(options) {
|
|
|
2729
2681
|
process.exit(1);
|
|
2730
2682
|
}
|
|
2731
2683
|
}
|
|
2732
|
-
const themePath =
|
|
2684
|
+
const themePath = path9.join(getThemesDir(), themeToValidate);
|
|
2733
2685
|
logger.startSpinner("Running validation checks...");
|
|
2734
2686
|
const entryFiles = ["manifest.ts", "theme.config.ts", "bundle-entry.ts"];
|
|
2735
2687
|
const foundEntry = entryFiles.find(
|
|
2736
|
-
(f) => fs.existsSync(
|
|
2688
|
+
(f) => fs.existsSync(path9.join(themePath, f))
|
|
2737
2689
|
);
|
|
2738
2690
|
if (!foundEntry) {
|
|
2739
2691
|
issues.push({
|
|
@@ -2743,7 +2695,7 @@ async function validateCommand(options) {
|
|
|
2743
2695
|
});
|
|
2744
2696
|
} else if (foundEntry === "manifest.ts") {
|
|
2745
2697
|
const manifestContent = fs.readFileSync(
|
|
2746
|
-
|
|
2698
|
+
path9.join(themePath, foundEntry),
|
|
2747
2699
|
"utf-8"
|
|
2748
2700
|
);
|
|
2749
2701
|
if (!manifestContent.includes("export const") && !manifestContent.includes("export default") && !manifestContent.includes("export interface")) {
|
|
@@ -2754,7 +2706,7 @@ async function validateCommand(options) {
|
|
|
2754
2706
|
});
|
|
2755
2707
|
}
|
|
2756
2708
|
}
|
|
2757
|
-
const configPath =
|
|
2709
|
+
const configPath = path9.join(themePath, "theme.config.ts");
|
|
2758
2710
|
if (!fs.existsSync(configPath)) {
|
|
2759
2711
|
issues.push({
|
|
2760
2712
|
type: "warning",
|
|
@@ -2762,7 +2714,7 @@ async function validateCommand(options) {
|
|
|
2762
2714
|
message: "Theme config file not found (recommended)"
|
|
2763
2715
|
});
|
|
2764
2716
|
}
|
|
2765
|
-
const indexPath =
|
|
2717
|
+
const indexPath = path9.join(themePath, "index.ts");
|
|
2766
2718
|
if (!fs.existsSync(indexPath)) {
|
|
2767
2719
|
issues.push({
|
|
2768
2720
|
type: "warning",
|
|
@@ -2770,7 +2722,7 @@ async function validateCommand(options) {
|
|
|
2770
2722
|
message: "Index file not found (recommended)"
|
|
2771
2723
|
});
|
|
2772
2724
|
}
|
|
2773
|
-
const sectionsDir =
|
|
2725
|
+
const sectionsDir = path9.join(themePath, "sections");
|
|
2774
2726
|
if (!fs.existsSync(sectionsDir)) {
|
|
2775
2727
|
issues.push({
|
|
2776
2728
|
type: "warning",
|
|
@@ -2779,16 +2731,16 @@ async function validateCommand(options) {
|
|
|
2779
2731
|
});
|
|
2780
2732
|
} else {
|
|
2781
2733
|
const sections = fs.readdirSync(sectionsDir).filter(
|
|
2782
|
-
(name) => fs.statSync(
|
|
2734
|
+
(name) => fs.statSync(path9.join(sectionsDir, name)).isDirectory()
|
|
2783
2735
|
);
|
|
2784
2736
|
for (const sectionName of sections) {
|
|
2785
|
-
const sectionPath =
|
|
2786
|
-
const schemaFile =
|
|
2787
|
-
const defaultTemplate =
|
|
2737
|
+
const sectionPath = path9.join(sectionsDir, sectionName);
|
|
2738
|
+
const schemaFile = path9.join(sectionPath, `${sectionName}.schema.ts`);
|
|
2739
|
+
const defaultTemplate = path9.join(
|
|
2788
2740
|
sectionPath,
|
|
2789
2741
|
`${sectionName}-default.tsx`
|
|
2790
2742
|
);
|
|
2791
|
-
const indexFile =
|
|
2743
|
+
const indexFile = path9.join(sectionPath, "index.ts");
|
|
2792
2744
|
if (!fs.existsSync(schemaFile)) {
|
|
2793
2745
|
issues.push({
|
|
2794
2746
|
type: "error",
|
|
@@ -2812,14 +2764,14 @@ async function validateCommand(options) {
|
|
|
2812
2764
|
}
|
|
2813
2765
|
}
|
|
2814
2766
|
}
|
|
2815
|
-
const blocksDir =
|
|
2767
|
+
const blocksDir = path9.join(themePath, "blocks");
|
|
2816
2768
|
if (fs.existsSync(blocksDir)) {
|
|
2817
|
-
const blocks = fs.readdirSync(blocksDir).filter((name) => fs.statSync(
|
|
2769
|
+
const blocks = fs.readdirSync(blocksDir).filter((name) => fs.statSync(path9.join(blocksDir, name)).isDirectory());
|
|
2818
2770
|
for (const blockName of blocks) {
|
|
2819
|
-
const blockPath =
|
|
2820
|
-
const schemaFile =
|
|
2821
|
-
const componentFile =
|
|
2822
|
-
const indexFile =
|
|
2771
|
+
const blockPath = path9.join(blocksDir, blockName);
|
|
2772
|
+
const schemaFile = path9.join(blockPath, `${blockName}.schema.ts`);
|
|
2773
|
+
const componentFile = path9.join(blockPath, `${blockName}.tsx`);
|
|
2774
|
+
const indexFile = path9.join(blockPath, "index.ts");
|
|
2823
2775
|
if (!fs.existsSync(schemaFile)) {
|
|
2824
2776
|
issues.push({
|
|
2825
2777
|
type: "error",
|
|
@@ -2845,13 +2797,13 @@ async function validateCommand(options) {
|
|
|
2845
2797
|
}
|
|
2846
2798
|
if (fs.existsSync(sectionsDir)) {
|
|
2847
2799
|
const sections = fs.readdirSync(sectionsDir).filter(
|
|
2848
|
-
(name) => fs.statSync(
|
|
2800
|
+
(name) => fs.statSync(path9.join(sectionsDir, name)).isDirectory()
|
|
2849
2801
|
);
|
|
2850
2802
|
for (const sectionName of sections) {
|
|
2851
|
-
const sectionPath =
|
|
2803
|
+
const sectionPath = path9.join(sectionsDir, sectionName);
|
|
2852
2804
|
const tsxFiles = fs.readdirSync(sectionPath).filter((f) => f.endsWith(".tsx") && !f.endsWith(".schema.ts"));
|
|
2853
2805
|
for (const tsxFile of tsxFiles) {
|
|
2854
|
-
const filePath =
|
|
2806
|
+
const filePath = path9.join(sectionPath, tsxFile);
|
|
2855
2807
|
const content = fs.readFileSync(filePath, "utf-8");
|
|
2856
2808
|
const relPath = `sections/${sectionName}/${tsxFile}`;
|
|
2857
2809
|
if (!content.includes('"use client"') && !content.includes("'use client'")) {
|
|
@@ -2899,12 +2851,12 @@ async function validateCommand(options) {
|
|
|
2899
2851
|
}
|
|
2900
2852
|
}
|
|
2901
2853
|
}
|
|
2902
|
-
const registryPath =
|
|
2903
|
-
const bundleEntryPath =
|
|
2854
|
+
const registryPath = path9.join(themePath, "sections-registry.ts");
|
|
2855
|
+
const bundleEntryPath = path9.join(themePath, "bundle-entry.ts");
|
|
2904
2856
|
const registryContent = fs.existsSync(registryPath) ? fs.readFileSync(registryPath, "utf-8") : fs.existsSync(bundleEntryPath) ? fs.readFileSync(bundleEntryPath, "utf-8") : "";
|
|
2905
2857
|
if (fs.existsSync(sectionsDir) && registryContent) {
|
|
2906
2858
|
const sections = fs.readdirSync(sectionsDir).filter(
|
|
2907
|
-
(name) => fs.statSync(
|
|
2859
|
+
(name) => fs.statSync(path9.join(sectionsDir, name)).isDirectory()
|
|
2908
2860
|
);
|
|
2909
2861
|
for (const sectionName of sections) {
|
|
2910
2862
|
if (!registryContent.includes(`sections/${sectionName}`) && !registryContent.includes(`"${sectionName}"`)) {
|
|
@@ -2927,7 +2879,7 @@ async function validateCommand(options) {
|
|
|
2927
2879
|
});
|
|
2928
2880
|
}
|
|
2929
2881
|
}
|
|
2930
|
-
const pagesDir =
|
|
2882
|
+
const pagesDir = path9.join(themePath, "pages");
|
|
2931
2883
|
if (fs.existsSync(pagesDir)) {
|
|
2932
2884
|
const allSchemaTypeSet = new Set(
|
|
2933
2885
|
schemaTypes.map((s) => s.schemaType || s.folderName)
|
|
@@ -2979,9 +2931,9 @@ async function validateCommand(options) {
|
|
|
2979
2931
|
}
|
|
2980
2932
|
async function loadSchemaTypes(themePath, sectionsDir) {
|
|
2981
2933
|
const results = [];
|
|
2982
|
-
const sections = fs.readdirSync(sectionsDir).filter((name) => fs.statSync(
|
|
2934
|
+
const sections = fs.readdirSync(sectionsDir).filter((name) => fs.statSync(path9.join(sectionsDir, name)).isDirectory());
|
|
2983
2935
|
for (const sectionName of sections) {
|
|
2984
|
-
const schemaFile =
|
|
2936
|
+
const schemaFile = path9.join(
|
|
2985
2937
|
sectionsDir,
|
|
2986
2938
|
sectionName,
|
|
2987
2939
|
`${sectionName}.schema.ts`
|
|
@@ -2991,10 +2943,26 @@ async function loadSchemaTypes(themePath, sectionsDir) {
|
|
|
2991
2943
|
continue;
|
|
2992
2944
|
}
|
|
2993
2945
|
const content = fs.readFileSync(schemaFile, "utf-8");
|
|
2994
|
-
|
|
2946
|
+
let schemaType = null;
|
|
2947
|
+
const schemaExportMatch = content.match(
|
|
2948
|
+
/:\s*SectionSchema\s*=\s*\{[\s\S]*?\btype:\s*["']([^"']+)["']/
|
|
2949
|
+
);
|
|
2950
|
+
if (schemaExportMatch) {
|
|
2951
|
+
schemaType = schemaExportMatch[1];
|
|
2952
|
+
} else {
|
|
2953
|
+
const allTypeMatches = [
|
|
2954
|
+
...content.matchAll(/\btype:\s*["']([^"']+)["']/g)
|
|
2955
|
+
];
|
|
2956
|
+
for (const m of allTypeMatches) {
|
|
2957
|
+
if (!FIELD_TYPES.has(m[1])) {
|
|
2958
|
+
schemaType = m[1];
|
|
2959
|
+
break;
|
|
2960
|
+
}
|
|
2961
|
+
}
|
|
2962
|
+
}
|
|
2995
2963
|
results.push({
|
|
2996
2964
|
folderName: sectionName,
|
|
2997
|
-
schemaType
|
|
2965
|
+
schemaType
|
|
2998
2966
|
});
|
|
2999
2967
|
}
|
|
3000
2968
|
return results;
|
|
@@ -3003,12 +2971,22 @@ async function validatePageSectionTypes(pagesDir, validTypes) {
|
|
|
3003
2971
|
const issues = [];
|
|
3004
2972
|
const files = fs.readdirSync(pagesDir).filter((f) => f.match(/\.(ts|js)$/));
|
|
3005
2973
|
for (const file of files) {
|
|
3006
|
-
const content = fs.readFileSync(
|
|
2974
|
+
const content = fs.readFileSync(path9.join(pagesDir, file), "utf-8");
|
|
3007
2975
|
const pageName = file.replace(/\.(ts|js)$/, "");
|
|
3008
|
-
const
|
|
2976
|
+
const sectionsMatch = content.match(/\bsections:\s*\[/);
|
|
2977
|
+
if (!sectionsMatch || sectionsMatch.index === void 0) continue;
|
|
2978
|
+
const startIdx = sectionsMatch.index + sectionsMatch[0].length;
|
|
2979
|
+
let depth = 1;
|
|
2980
|
+
let endIdx = startIdx;
|
|
2981
|
+
for (let i = startIdx; i < content.length && depth > 0; i++) {
|
|
2982
|
+
if (content[i] === "[") depth++;
|
|
2983
|
+
else if (content[i] === "]") depth--;
|
|
2984
|
+
endIdx = i;
|
|
2985
|
+
}
|
|
2986
|
+
const sectionsBlock = content.slice(startIdx, endIdx);
|
|
2987
|
+
const typeMatches = sectionsBlock.matchAll(/\btype:\s*["']([^"']+)["']/g);
|
|
3009
2988
|
for (const match of typeMatches) {
|
|
3010
2989
|
const sectionType = match[1];
|
|
3011
|
-
if (isFieldType(sectionType)) continue;
|
|
3012
2990
|
if (!validTypes.has(sectionType)) {
|
|
3013
2991
|
issues.push({
|
|
3014
2992
|
type: "error",
|
|
@@ -3049,11 +3027,18 @@ var FIELD_TYPES = /* @__PURE__ */ new Set([
|
|
|
3049
3027
|
"array",
|
|
3050
3028
|
"object",
|
|
3051
3029
|
"group",
|
|
3052
|
-
"section"
|
|
3030
|
+
"section",
|
|
3031
|
+
"boolean",
|
|
3032
|
+
"color_token",
|
|
3033
|
+
"color_background",
|
|
3034
|
+
"image_picker",
|
|
3035
|
+
"video_url",
|
|
3036
|
+
"font",
|
|
3037
|
+
"font_picker",
|
|
3038
|
+
"text_alignment",
|
|
3039
|
+
"inline_richtext",
|
|
3040
|
+
"repeater"
|
|
3053
3041
|
]);
|
|
3054
|
-
function isFieldType(type) {
|
|
3055
|
-
return FIELD_TYPES.has(type);
|
|
3056
|
-
}
|
|
3057
3042
|
|
|
3058
3043
|
// src/commands/build.ts
|
|
3059
3044
|
init_logger();
|
|
@@ -3064,14 +3049,14 @@ async function buildCommand(options) {
|
|
|
3064
3049
|
if (options.theme) {
|
|
3065
3050
|
themeName = options.theme;
|
|
3066
3051
|
try {
|
|
3067
|
-
const workspaceThemePath =
|
|
3052
|
+
const workspaceThemePath = path9.join(getThemesDir(), themeName);
|
|
3068
3053
|
if (fs.existsSync(workspaceThemePath)) {
|
|
3069
3054
|
themePath = workspaceThemePath;
|
|
3070
3055
|
} else {
|
|
3071
|
-
themePath =
|
|
3056
|
+
themePath = path9.join(process.cwd(), themeName);
|
|
3072
3057
|
}
|
|
3073
3058
|
} catch {
|
|
3074
|
-
themePath =
|
|
3059
|
+
themePath = path9.join(process.cwd(), themeName);
|
|
3075
3060
|
}
|
|
3076
3061
|
if (!fs.existsSync(themePath)) {
|
|
3077
3062
|
logger.error(`Theme "${themeName}" not found.`);
|
|
@@ -3082,10 +3067,10 @@ async function buildCommand(options) {
|
|
|
3082
3067
|
"theme.config.ts",
|
|
3083
3068
|
"bundle-entry.ts",
|
|
3084
3069
|
"manifest.ts"
|
|
3085
|
-
].some((f) => fs.existsSync(
|
|
3070
|
+
].some((f) => fs.existsSync(path9.join(process.cwd(), f)));
|
|
3086
3071
|
if (isThemeDir) {
|
|
3087
3072
|
themePath = process.cwd();
|
|
3088
|
-
themeName =
|
|
3073
|
+
themeName = path9.basename(themePath);
|
|
3089
3074
|
logger.info(`Building current theme: ${themeName}`);
|
|
3090
3075
|
} else {
|
|
3091
3076
|
logger.error(
|
|
@@ -3094,7 +3079,7 @@ async function buildCommand(options) {
|
|
|
3094
3079
|
process.exit(1);
|
|
3095
3080
|
}
|
|
3096
3081
|
}
|
|
3097
|
-
const packageJsonPath =
|
|
3082
|
+
const packageJsonPath = path9.join(themePath, "package.json");
|
|
3098
3083
|
const hasPkgJson = fs.existsSync(packageJsonPath);
|
|
3099
3084
|
if (!hasPkgJson) {
|
|
3100
3085
|
logger.warning(
|
|
@@ -3150,9 +3135,9 @@ async function buildCommand(options) {
|
|
|
3150
3135
|
logger.success("\u2713 Theme built successfully!");
|
|
3151
3136
|
logger.newLine();
|
|
3152
3137
|
logger.info(`Theme: ${themeName}`);
|
|
3153
|
-
const distPath =
|
|
3138
|
+
const distPath = path9.join(themePath, "dist");
|
|
3154
3139
|
if (fs.existsSync(distPath)) {
|
|
3155
|
-
logger.log(`Output: ${
|
|
3140
|
+
logger.log(`Output: ${path9.relative(process.cwd(), distPath)}`);
|
|
3156
3141
|
const files = fs.readdirSync(distPath);
|
|
3157
3142
|
logger.log(`Files: ${files.length}`);
|
|
3158
3143
|
}
|
|
@@ -3160,17 +3145,17 @@ async function buildCommand(options) {
|
|
|
3160
3145
|
}
|
|
3161
3146
|
function runCommand(command, args, cwd) {
|
|
3162
3147
|
return new Promise((resolve) => {
|
|
3163
|
-
const proc =
|
|
3148
|
+
const proc = spawn(command, args, {
|
|
3164
3149
|
cwd,
|
|
3165
3150
|
stdio: ["pipe", "pipe", "pipe"],
|
|
3166
3151
|
shell: true
|
|
3167
3152
|
});
|
|
3168
3153
|
let stdout = "";
|
|
3169
3154
|
let stderr = "";
|
|
3170
|
-
proc.stdout
|
|
3155
|
+
proc.stdout.on("data", (data) => {
|
|
3171
3156
|
stdout += data.toString();
|
|
3172
3157
|
});
|
|
3173
|
-
proc.stderr
|
|
3158
|
+
proc.stderr.on("data", (data) => {
|
|
3174
3159
|
stderr += data.toString();
|
|
3175
3160
|
});
|
|
3176
3161
|
proc.on("close", (code) => {
|
|
@@ -3208,7 +3193,7 @@ async function packageCommand(options) {
|
|
|
3208
3193
|
let themeName;
|
|
3209
3194
|
if (options.theme) {
|
|
3210
3195
|
themeName = options.theme;
|
|
3211
|
-
themePath =
|
|
3196
|
+
themePath = path9.join(getThemesDir(), themeName);
|
|
3212
3197
|
if (!fs.existsSync(themePath)) {
|
|
3213
3198
|
logger.error(`Theme "${themeName}" not found.`);
|
|
3214
3199
|
process.exit(1);
|
|
@@ -3218,10 +3203,10 @@ async function packageCommand(options) {
|
|
|
3218
3203
|
"theme.config.ts",
|
|
3219
3204
|
"bundle-entry.ts",
|
|
3220
3205
|
"manifest.ts"
|
|
3221
|
-
].some((f) => fs.existsSync(
|
|
3206
|
+
].some((f) => fs.existsSync(path9.join(process.cwd(), f)));
|
|
3222
3207
|
if (isThemeDir) {
|
|
3223
3208
|
themePath = process.cwd();
|
|
3224
|
-
themeName =
|
|
3209
|
+
themeName = path9.basename(themePath);
|
|
3225
3210
|
logger.info(`Packaging current theme: ${themeName}`);
|
|
3226
3211
|
} else {
|
|
3227
3212
|
logger.error(
|
|
@@ -3230,7 +3215,7 @@ async function packageCommand(options) {
|
|
|
3230
3215
|
process.exit(1);
|
|
3231
3216
|
}
|
|
3232
3217
|
}
|
|
3233
|
-
const packageJsonPath =
|
|
3218
|
+
const packageJsonPath = path9.join(themePath, "package.json");
|
|
3234
3219
|
let version2 = "1.0.0";
|
|
3235
3220
|
if (fs.existsSync(packageJsonPath)) {
|
|
3236
3221
|
const packageJson = await fs.readJson(packageJsonPath);
|
|
@@ -3240,7 +3225,7 @@ async function packageCommand(options) {
|
|
|
3240
3225
|
logger.info(`Theme: ${themeName}`);
|
|
3241
3226
|
logger.info(`Version: ${version2}`);
|
|
3242
3227
|
logger.newLine();
|
|
3243
|
-
const compiledThemePath =
|
|
3228
|
+
const compiledThemePath = path9.join(
|
|
3244
3229
|
process.cwd(),
|
|
3245
3230
|
"themes",
|
|
3246
3231
|
themeName,
|
|
@@ -3274,8 +3259,8 @@ async function packageCommand(options) {
|
|
|
3274
3259
|
logger.newLine();
|
|
3275
3260
|
logger.section("Step 2: Create Package");
|
|
3276
3261
|
const packageName = options.name || `${themeName}-${version2}`;
|
|
3277
|
-
const outputDir = options.output ||
|
|
3278
|
-
const outputPath =
|
|
3262
|
+
const outputDir = options.output || path9.join(process.cwd(), "dist");
|
|
3263
|
+
const outputPath = path9.join(outputDir, `${packageName}.zip`);
|
|
3279
3264
|
await fs.ensureDir(outputDir);
|
|
3280
3265
|
logger.startSpinner("Creating zip archive...");
|
|
3281
3266
|
try {
|
|
@@ -3288,11 +3273,11 @@ async function packageCommand(options) {
|
|
|
3288
3273
|
logger.newLine();
|
|
3289
3274
|
logger.info(`Package: ${packageName}.zip`);
|
|
3290
3275
|
logger.log(`Size: ${sizeMB} MB`);
|
|
3291
|
-
logger.log(`Location: ${
|
|
3276
|
+
logger.log(`Location: ${path9.relative(process.cwd(), outputPath)}`);
|
|
3292
3277
|
logger.newLine();
|
|
3293
3278
|
logger.section("Next steps:");
|
|
3294
3279
|
logger.log(
|
|
3295
|
-
` onexthm deploy --package ${
|
|
3280
|
+
` onexthm deploy --package ${path9.relative(process.cwd(), outputPath)}`
|
|
3296
3281
|
);
|
|
3297
3282
|
} catch (error) {
|
|
3298
3283
|
logger.stopSpinner(false, "Failed to create package");
|
|
@@ -3304,13 +3289,13 @@ async function packageCommand(options) {
|
|
|
3304
3289
|
}
|
|
3305
3290
|
function runCommand2(command, args) {
|
|
3306
3291
|
return new Promise((resolve) => {
|
|
3307
|
-
const proc =
|
|
3292
|
+
const proc = spawn(command, args, {
|
|
3308
3293
|
cwd: process.cwd(),
|
|
3309
3294
|
stdio: "pipe",
|
|
3310
3295
|
shell: true
|
|
3311
3296
|
});
|
|
3312
3297
|
let hasError = false;
|
|
3313
|
-
proc.stderr
|
|
3298
|
+
proc.stderr.on("data", (data) => {
|
|
3314
3299
|
const message = data.toString();
|
|
3315
3300
|
if (message.includes("error") || message.includes("Error") || message.includes("ERROR")) {
|
|
3316
3301
|
hasError = true;
|
|
@@ -3350,9 +3335,9 @@ async function deployCommand(options) {
|
|
|
3350
3335
|
ensureOneXProject();
|
|
3351
3336
|
let packagePath;
|
|
3352
3337
|
if (options.package) {
|
|
3353
|
-
packagePath =
|
|
3338
|
+
packagePath = path9.resolve(options.package);
|
|
3354
3339
|
} else if (options.theme) {
|
|
3355
|
-
const distDir =
|
|
3340
|
+
const distDir = path9.join(process.cwd(), "dist");
|
|
3356
3341
|
if (!fs.existsSync(distDir)) {
|
|
3357
3342
|
logger.error("No dist/ directory found. Run 'onexthm package' first.");
|
|
3358
3343
|
process.exit(1);
|
|
@@ -3367,7 +3352,7 @@ async function deployCommand(options) {
|
|
|
3367
3352
|
process.exit(1);
|
|
3368
3353
|
}
|
|
3369
3354
|
packageFiles.sort().reverse();
|
|
3370
|
-
packagePath =
|
|
3355
|
+
packagePath = path9.join(distDir, packageFiles[0]);
|
|
3371
3356
|
} else {
|
|
3372
3357
|
logger.error("Either --package or --theme must be specified.");
|
|
3373
3358
|
logger.info("Examples:");
|
|
@@ -3381,11 +3366,11 @@ async function deployCommand(options) {
|
|
|
3381
3366
|
}
|
|
3382
3367
|
const stats = await fs.stat(packagePath);
|
|
3383
3368
|
const sizeMB = (stats.size / 1024 / 1024).toFixed(2);
|
|
3384
|
-
const fileName =
|
|
3369
|
+
const fileName = path9.basename(packagePath);
|
|
3385
3370
|
logger.newLine();
|
|
3386
3371
|
logger.info(`Package: ${fileName}`);
|
|
3387
3372
|
logger.log(`Size: ${sizeMB} MB`);
|
|
3388
|
-
logger.log(`Path: ${
|
|
3373
|
+
logger.log(`Path: ${path9.relative(process.cwd(), packagePath)}`);
|
|
3389
3374
|
logger.newLine();
|
|
3390
3375
|
const apiUrl = options.apiUrl || process.env.ONEX_API_URL || "http://localhost:3001";
|
|
3391
3376
|
const uploadEndpoint = `${apiUrl}/website-api/themes/upload`;
|
|
@@ -3489,11 +3474,11 @@ function getBucketName(env) {
|
|
|
3489
3474
|
return environment === "production" ? "theme-s3-bucket" : "theme-s3-bucket";
|
|
3490
3475
|
}
|
|
3491
3476
|
async function findCompiledThemeDir(themeId, version2) {
|
|
3492
|
-
const searchPaths = [
|
|
3477
|
+
const searchPaths = [path9.resolve(process.cwd(), "dist")];
|
|
3493
3478
|
for (const dir of searchPaths) {
|
|
3494
3479
|
if (await fs.pathExists(dir)) {
|
|
3495
|
-
const hasManifest = await fs.pathExists(
|
|
3496
|
-
const hasThemeEntry = await fs.pathExists(
|
|
3480
|
+
const hasManifest = await fs.pathExists(path9.join(dir, "manifest.json"));
|
|
3481
|
+
const hasThemeEntry = await fs.pathExists(path9.join(dir, "bundle-entry.js")) || await fs.pathExists(path9.join(dir, "theme.config.js")) || await fs.pathExists(path9.join(dir, "index.js"));
|
|
3497
3482
|
if (hasManifest || hasThemeEntry) {
|
|
3498
3483
|
return dir;
|
|
3499
3484
|
}
|
|
@@ -3502,7 +3487,7 @@ async function findCompiledThemeDir(themeId, version2) {
|
|
|
3502
3487
|
return null;
|
|
3503
3488
|
}
|
|
3504
3489
|
async function readManifest() {
|
|
3505
|
-
const manifestTsPath =
|
|
3490
|
+
const manifestTsPath = path9.resolve(process.cwd(), "manifest.ts");
|
|
3506
3491
|
if (await fs.pathExists(manifestTsPath)) {
|
|
3507
3492
|
try {
|
|
3508
3493
|
const module = await import(manifestTsPath);
|
|
@@ -3511,7 +3496,7 @@ async function readManifest() {
|
|
|
3511
3496
|
logger.warning("Failed to import manifest.ts, trying package.json");
|
|
3512
3497
|
}
|
|
3513
3498
|
}
|
|
3514
|
-
const packageJsonPath =
|
|
3499
|
+
const packageJsonPath = path9.resolve(process.cwd(), "package.json");
|
|
3515
3500
|
if (await fs.pathExists(packageJsonPath)) {
|
|
3516
3501
|
const pkg = await fs.readJson(packageJsonPath);
|
|
3517
3502
|
return {
|
|
@@ -3545,13 +3530,13 @@ async function findSourceDir(themeId, explicitDir) {
|
|
|
3545
3530
|
}
|
|
3546
3531
|
const searchPaths = [
|
|
3547
3532
|
process.cwd(),
|
|
3548
|
-
|
|
3549
|
-
|
|
3533
|
+
path9.resolve(process.cwd(), `../../themes/${themeId}`),
|
|
3534
|
+
path9.resolve(process.cwd(), `../themes/${themeId}`)
|
|
3550
3535
|
];
|
|
3551
3536
|
const markers = ["theme.config.ts", "bundle-entry.ts"];
|
|
3552
3537
|
for (const dir of searchPaths) {
|
|
3553
3538
|
for (const marker of markers) {
|
|
3554
|
-
if (await fs.pathExists(
|
|
3539
|
+
if (await fs.pathExists(path9.join(dir, marker))) {
|
|
3555
3540
|
return dir;
|
|
3556
3541
|
}
|
|
3557
3542
|
}
|
|
@@ -3603,7 +3588,7 @@ async function uploadCommand(options) {
|
|
|
3603
3588
|
spinner.succeed(`Found compiled theme at: ${compiledDir}`);
|
|
3604
3589
|
spinner.start("Creating bundle.zip...");
|
|
3605
3590
|
const tmpDir = os.tmpdir();
|
|
3606
|
-
const bundleZipPath =
|
|
3591
|
+
const bundleZipPath = path9.join(tmpDir, `${themeId}-${version2}-bundle.zip`);
|
|
3607
3592
|
await createZipFromDir(compiledDir, bundleZipPath);
|
|
3608
3593
|
const bundleZipBuffer = await fs.readFile(bundleZipPath);
|
|
3609
3594
|
const bundleSizeMB = (bundleZipBuffer.length / 1024 / 1024).toFixed(2);
|
|
@@ -3657,7 +3642,7 @@ async function uploadCommand(options) {
|
|
|
3657
3642
|
if (sourceDir) {
|
|
3658
3643
|
spinner.succeed(`Found source at: ${sourceDir}`);
|
|
3659
3644
|
spinner.start("Creating source.zip...");
|
|
3660
|
-
const sourceZipPath =
|
|
3645
|
+
const sourceZipPath = path9.join(
|
|
3661
3646
|
tmpDir,
|
|
3662
3647
|
`${themeId}-${version2}-source.zip`
|
|
3663
3648
|
);
|
|
@@ -3791,8 +3776,8 @@ async function resolveLatestVersion(s3Client, bucket, themeId) {
|
|
|
3791
3776
|
async function createCompatibilityFiles(outputDir, manifest) {
|
|
3792
3777
|
const entryFile = manifest.output?.entry || "bundle-entry.js";
|
|
3793
3778
|
if (entryFile !== "bundle-entry.js" && entryFile.startsWith("bundle-entry-")) {
|
|
3794
|
-
const hashedPath =
|
|
3795
|
-
const stablePath =
|
|
3779
|
+
const hashedPath = path9.join(outputDir, entryFile);
|
|
3780
|
+
const stablePath = path9.join(outputDir, "bundle-entry.js");
|
|
3796
3781
|
if (await fs.pathExists(hashedPath)) {
|
|
3797
3782
|
await fs.copy(hashedPath, stablePath);
|
|
3798
3783
|
const mapPath = hashedPath + ".map";
|
|
@@ -3801,13 +3786,13 @@ async function createCompatibilityFiles(outputDir, manifest) {
|
|
|
3801
3786
|
}
|
|
3802
3787
|
}
|
|
3803
3788
|
}
|
|
3804
|
-
const sectionsRegistryPath =
|
|
3789
|
+
const sectionsRegistryPath = path9.join(outputDir, "sections-registry.js");
|
|
3805
3790
|
const content = `// Re-export all sections from bundle-entry
|
|
3806
3791
|
// This file exists to maintain compatibility with the import path
|
|
3807
3792
|
export * from './bundle-entry.js';
|
|
3808
3793
|
`;
|
|
3809
3794
|
await fs.writeFile(sectionsRegistryPath, content, "utf-8");
|
|
3810
|
-
const pkgJsonPath =
|
|
3795
|
+
const pkgJsonPath = path9.join(outputDir, "package.json");
|
|
3811
3796
|
await fs.writeFile(pkgJsonPath, '{\n "type": "module"\n}\n', "utf-8");
|
|
3812
3797
|
}
|
|
3813
3798
|
function showDownloadFailureHelp(themeId, bucket) {
|
|
@@ -3902,7 +3887,7 @@ async function downloadCommand(options) {
|
|
|
3902
3887
|
zip.extractAllTo(outputDir, true);
|
|
3903
3888
|
const entries = zip.getEntries().filter((e) => !e.isDirectory);
|
|
3904
3889
|
spinner.succeed(`Extracted ${entries.length} files to ${outputDir}`);
|
|
3905
|
-
const manifestPath =
|
|
3890
|
+
const manifestPath = path9.join(outputDir, "manifest.json");
|
|
3906
3891
|
const manifest = await fs.readJson(manifestPath);
|
|
3907
3892
|
await createCompatibilityFiles(outputDir, manifest);
|
|
3908
3893
|
console.log();
|
|
@@ -4002,9 +3987,10 @@ async function resolveLatestVersion2(s3Client, bucket, themeId) {
|
|
|
4002
3987
|
}
|
|
4003
3988
|
function runInstall(cwd) {
|
|
4004
3989
|
return new Promise((resolve) => {
|
|
4005
|
-
const proc =
|
|
3990
|
+
const proc = spawn("pnpm", ["install"], {
|
|
4006
3991
|
cwd,
|
|
4007
|
-
stdio: "inherit"
|
|
3992
|
+
stdio: "inherit",
|
|
3993
|
+
shell: true
|
|
4008
3994
|
});
|
|
4009
3995
|
proc.on("close", (code) => resolve(code === 0));
|
|
4010
3996
|
proc.on("error", () => resolve(false));
|
|
@@ -4035,7 +4021,7 @@ async function renameTheme(themeDir, oldName, newName) {
|
|
|
4035
4021
|
const oldPrefix = `${oldName}-`;
|
|
4036
4022
|
const newPrefix = `${newName}-`;
|
|
4037
4023
|
const newDisplayName = newName.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
4038
|
-
const pkgPath =
|
|
4024
|
+
const pkgPath = path9.join(themeDir, "package.json");
|
|
4039
4025
|
if (await fs.pathExists(pkgPath)) {
|
|
4040
4026
|
const pkg = await fs.readJson(pkgPath);
|
|
4041
4027
|
pkg.name = `@onex-themes/${newName}`;
|
|
@@ -4051,7 +4037,7 @@ async function renameTheme(themeDir, oldName, newName) {
|
|
|
4051
4037
|
}
|
|
4052
4038
|
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
4053
4039
|
}
|
|
4054
|
-
const configPath =
|
|
4040
|
+
const configPath = path9.join(themeDir, "theme.config.ts");
|
|
4055
4041
|
if (await fs.pathExists(configPath)) {
|
|
4056
4042
|
let content = await fs.readFile(configPath, "utf-8");
|
|
4057
4043
|
content = content.replace(/id:\s*"[^"]*"/, `id: "${newName}"`);
|
|
@@ -4061,7 +4047,7 @@ async function renameTheme(themeDir, oldName, newName) {
|
|
|
4061
4047
|
);
|
|
4062
4048
|
await fs.writeFile(configPath, content);
|
|
4063
4049
|
}
|
|
4064
|
-
const layoutPath =
|
|
4050
|
+
const layoutPath = path9.join(themeDir, "theme.layout.ts");
|
|
4065
4051
|
if (await fs.pathExists(layoutPath)) {
|
|
4066
4052
|
let content = await fs.readFile(layoutPath, "utf-8");
|
|
4067
4053
|
content = content.replace(/id:\s*"[^"]*"/, `id: "${newName}"`);
|
|
@@ -4074,7 +4060,7 @@ async function renameTheme(themeDir, oldName, newName) {
|
|
|
4074
4060
|
const oldDisplayName = oldName.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
4075
4061
|
const tsFiles = await glob("**/*.ts", { cwd: themeDir, nodir: true });
|
|
4076
4062
|
for (const file of tsFiles) {
|
|
4077
|
-
const filePath =
|
|
4063
|
+
const filePath = path9.join(themeDir, file);
|
|
4078
4064
|
let content = await fs.readFile(filePath, "utf-8");
|
|
4079
4065
|
const original = content;
|
|
4080
4066
|
content = content.replace(
|
|
@@ -4103,7 +4089,7 @@ async function cloneCommand(themeName, options) {
|
|
|
4103
4089
|
const spinner = ora("Initializing clone...").start();
|
|
4104
4090
|
try {
|
|
4105
4091
|
const bucket = options.bucket || getBucketName3(options.environment);
|
|
4106
|
-
const outputDir = options.output ||
|
|
4092
|
+
const outputDir = options.output || path9.resolve(process.cwd(), newName);
|
|
4107
4093
|
const s3Client = getS3Client3();
|
|
4108
4094
|
if (await fs.pathExists(outputDir)) {
|
|
4109
4095
|
spinner.fail(chalk4.red(`Directory already exists: ${outputDir}`));
|
|
@@ -4158,7 +4144,7 @@ async function cloneCommand(themeName, options) {
|
|
|
4158
4144
|
spinner.succeed(
|
|
4159
4145
|
`Renamed theme: ${chalk4.gray(themeName)} \u2192 ${chalk4.cyan(newName)}`
|
|
4160
4146
|
);
|
|
4161
|
-
const envExamplePath =
|
|
4147
|
+
const envExamplePath = path9.join(outputDir, ".env.example");
|
|
4162
4148
|
if (!await fs.pathExists(envExamplePath)) {
|
|
4163
4149
|
await fs.writeFile(
|
|
4164
4150
|
envExamplePath,
|
|
@@ -4171,18 +4157,32 @@ async function cloneCommand(themeName, options) {
|
|
|
4171
4157
|
].join("\n")
|
|
4172
4158
|
);
|
|
4173
4159
|
}
|
|
4174
|
-
const
|
|
4175
|
-
|
|
4176
|
-
{
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4160
|
+
const mcpJsonPath = path9.join(outputDir, ".mcp.json");
|
|
4161
|
+
if (await fs.pathExists(mcpJsonPath)) {
|
|
4162
|
+
const { default: inquirerMod } = await import('inquirer');
|
|
4163
|
+
const { figmaApiKey } = await inquirerMod.prompt([
|
|
4164
|
+
{
|
|
4165
|
+
type: "password",
|
|
4166
|
+
name: "figmaApiKey",
|
|
4167
|
+
message: "Figma API Key (optional, for Figma-to-code MCP \u2014 press Enter to skip):"
|
|
4168
|
+
}
|
|
4169
|
+
]);
|
|
4170
|
+
let mcpContent = await fs.readFile(mcpJsonPath, "utf-8");
|
|
4171
|
+
if (figmaApiKey) {
|
|
4172
|
+
mcpContent = mcpContent.replace("__FIGMA_API_KEY__", figmaApiKey);
|
|
4173
|
+
} else {
|
|
4174
|
+
try {
|
|
4175
|
+
const mcpJson = JSON.parse(mcpContent);
|
|
4176
|
+
delete mcpJson.mcpServers?.figma;
|
|
4177
|
+
mcpContent = JSON.stringify(mcpJson, null, 2) + "\n";
|
|
4178
|
+
} catch {
|
|
4179
|
+
}
|
|
4180
4180
|
}
|
|
4181
|
-
|
|
4182
|
-
|
|
4181
|
+
await fs.writeFile(mcpJsonPath, mcpContent, "utf-8");
|
|
4182
|
+
}
|
|
4183
4183
|
if (options.install !== false) {
|
|
4184
4184
|
const hasPkgJson = await fs.pathExists(
|
|
4185
|
-
|
|
4185
|
+
path9.join(outputDir, "package.json")
|
|
4186
4186
|
);
|
|
4187
4187
|
if (hasPkgJson) {
|
|
4188
4188
|
spinner.start("Installing dependencies...");
|
|
@@ -4209,10 +4209,9 @@ async function cloneCommand(themeName, options) {
|
|
|
4209
4209
|
console.log(chalk4.cyan(" Files: ") + chalk4.white(entries.length));
|
|
4210
4210
|
console.log();
|
|
4211
4211
|
console.log(chalk4.cyan("Next steps:"));
|
|
4212
|
-
console.log(chalk4.gray(` cd ${
|
|
4213
|
-
const copyCmd = process.platform === "win32" ? "copy .env.example .env" : "cp .env.example .env";
|
|
4212
|
+
console.log(chalk4.gray(` cd ${path9.relative(process.cwd(), outputDir)}`));
|
|
4214
4213
|
console.log(
|
|
4215
|
-
chalk4.gray(
|
|
4214
|
+
chalk4.gray(" cp .env.example .env # then add your Company ID")
|
|
4216
4215
|
);
|
|
4217
4216
|
if (options.install === false) {
|
|
4218
4217
|
console.log(chalk4.gray(" pnpm install"));
|
|
@@ -4245,7 +4244,7 @@ var MIME_TYPES = {
|
|
|
4245
4244
|
};
|
|
4246
4245
|
function createDevServer(options) {
|
|
4247
4246
|
const clients = /* @__PURE__ */ new Set();
|
|
4248
|
-
const themeDataPath =
|
|
4247
|
+
const themeDataPath = path9.join(options.distDir, "theme-data.json");
|
|
4249
4248
|
const server = http.createServer((req, res) => {
|
|
4250
4249
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
4251
4250
|
res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
|
|
@@ -4271,8 +4270,8 @@ function createDevServer(options) {
|
|
|
4271
4270
|
if (pathname.startsWith("/_assets/")) {
|
|
4272
4271
|
const parts = pathname.replace(/^\/_assets\//, "").split("/");
|
|
4273
4272
|
const assetSubpath = parts.slice(1).join("/");
|
|
4274
|
-
const assetPath =
|
|
4275
|
-
if (!assetPath.startsWith(
|
|
4273
|
+
const assetPath = path9.join(options.themePath, "assets", assetSubpath);
|
|
4274
|
+
if (!assetPath.startsWith(path9.join(options.themePath, "assets"))) {
|
|
4276
4275
|
res.writeHead(403);
|
|
4277
4276
|
res.end("Forbidden");
|
|
4278
4277
|
return;
|
|
@@ -4283,8 +4282,8 @@ function createDevServer(options) {
|
|
|
4283
4282
|
if (pathname.startsWith("/themes/")) {
|
|
4284
4283
|
const match = pathname.match(/^\/themes\/[^/]+\/assets\/(.+)/);
|
|
4285
4284
|
if (match) {
|
|
4286
|
-
const assetPath =
|
|
4287
|
-
if (!assetPath.startsWith(
|
|
4285
|
+
const assetPath = path9.join(options.themePath, "assets", match[1]);
|
|
4286
|
+
if (!assetPath.startsWith(path9.join(options.themePath, "assets"))) {
|
|
4288
4287
|
res.writeHead(403);
|
|
4289
4288
|
res.end("Forbidden");
|
|
4290
4289
|
return;
|
|
@@ -4298,26 +4297,26 @@ function createDevServer(options) {
|
|
|
4298
4297
|
const segments = subpath.split("/");
|
|
4299
4298
|
let assetPath;
|
|
4300
4299
|
if (segments[0] === options.themeName || segments[0] === options.themeName.replace(/^my-/, "")) {
|
|
4301
|
-
assetPath =
|
|
4300
|
+
assetPath = path9.join(
|
|
4302
4301
|
options.themePath,
|
|
4303
4302
|
"assets",
|
|
4304
4303
|
segments.slice(1).join("/")
|
|
4305
4304
|
);
|
|
4306
4305
|
} else {
|
|
4307
|
-
assetPath =
|
|
4306
|
+
assetPath = path9.join(options.themePath, "assets", subpath);
|
|
4308
4307
|
}
|
|
4309
|
-
if (assetPath.startsWith(
|
|
4308
|
+
if (assetPath.startsWith(path9.join(options.themePath, "assets")) && fs3.existsSync(assetPath)) {
|
|
4310
4309
|
serveFile(res, assetPath);
|
|
4311
4310
|
return;
|
|
4312
4311
|
}
|
|
4313
4312
|
}
|
|
4314
|
-
const filePath =
|
|
4313
|
+
const filePath = path9.join(options.distDir, pathname);
|
|
4315
4314
|
if (!filePath.startsWith(options.distDir)) {
|
|
4316
4315
|
res.writeHead(403);
|
|
4317
4316
|
res.end("Forbidden");
|
|
4318
4317
|
return;
|
|
4319
4318
|
}
|
|
4320
|
-
if (
|
|
4319
|
+
if (fs3.existsSync(filePath) && fs3.statSync(filePath).isFile()) {
|
|
4321
4320
|
serveFile(res, filePath);
|
|
4322
4321
|
} else {
|
|
4323
4322
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
@@ -4349,14 +4348,14 @@ function createDevServer(options) {
|
|
|
4349
4348
|
}
|
|
4350
4349
|
function serveFile(res, filePath) {
|
|
4351
4350
|
try {
|
|
4352
|
-
if (!
|
|
4351
|
+
if (!fs3.existsSync(filePath)) {
|
|
4353
4352
|
res.writeHead(404);
|
|
4354
4353
|
res.end("Not Found");
|
|
4355
4354
|
return;
|
|
4356
4355
|
}
|
|
4357
|
-
const ext =
|
|
4356
|
+
const ext = path9.extname(filePath);
|
|
4358
4357
|
const contentType = MIME_TYPES[ext] || "application/octet-stream";
|
|
4359
|
-
const content =
|
|
4358
|
+
const content = fs3.readFileSync(filePath);
|
|
4360
4359
|
res.writeHead(200, { "Content-Type": contentType });
|
|
4361
4360
|
res.end(content);
|
|
4362
4361
|
} catch {
|
|
@@ -4369,7 +4368,7 @@ function generatePreviewHTML(themeName, port, themeDataPath) {
|
|
|
4369
4368
|
let fontVarsCSS = "";
|
|
4370
4369
|
if (themeDataPath) {
|
|
4371
4370
|
try {
|
|
4372
|
-
const themeData = JSON.parse(
|
|
4371
|
+
const themeData = JSON.parse(fs3.readFileSync(themeDataPath, "utf-8"));
|
|
4373
4372
|
const typography = (themeData?.themeConfig || themeData?.theme?.config)?.typography?.fontFamily;
|
|
4374
4373
|
if (typography) {
|
|
4375
4374
|
const fontFamilies = /* @__PURE__ */ new Set();
|
|
@@ -4457,14 +4456,14 @@ async function devCommand(options) {
|
|
|
4457
4456
|
if (options.theme) {
|
|
4458
4457
|
themeName = options.theme;
|
|
4459
4458
|
try {
|
|
4460
|
-
const workspaceThemePath =
|
|
4459
|
+
const workspaceThemePath = path9.join(getThemesDir(), themeName);
|
|
4461
4460
|
if (fs.existsSync(workspaceThemePath)) {
|
|
4462
4461
|
themePath = workspaceThemePath;
|
|
4463
4462
|
} else {
|
|
4464
|
-
themePath =
|
|
4463
|
+
themePath = path9.join(process.cwd(), themeName);
|
|
4465
4464
|
}
|
|
4466
4465
|
} catch {
|
|
4467
|
-
themePath =
|
|
4466
|
+
themePath = path9.join(process.cwd(), themeName);
|
|
4468
4467
|
}
|
|
4469
4468
|
if (!fs.existsSync(themePath)) {
|
|
4470
4469
|
logger.error(`Theme "${themeName}" not found.`);
|
|
@@ -4475,10 +4474,10 @@ async function devCommand(options) {
|
|
|
4475
4474
|
"theme.config.ts",
|
|
4476
4475
|
"bundle-entry.ts",
|
|
4477
4476
|
"manifest.ts"
|
|
4478
|
-
].some((f) => fs.existsSync(
|
|
4477
|
+
].some((f) => fs.existsSync(path9.join(process.cwd(), f)));
|
|
4479
4478
|
if (isThemeDir) {
|
|
4480
4479
|
themePath = process.cwd();
|
|
4481
|
-
themeName =
|
|
4480
|
+
themeName = path9.basename(themePath);
|
|
4482
4481
|
} else {
|
|
4483
4482
|
logger.error(
|
|
4484
4483
|
"Not in a theme directory and no --theme specified. Run from theme root or use --theme flag."
|
|
@@ -4547,9 +4546,9 @@ async function devCommand(options) {
|
|
|
4547
4546
|
watcher.close();
|
|
4548
4547
|
await context2.dispose();
|
|
4549
4548
|
server.close();
|
|
4550
|
-
const shimPath =
|
|
4549
|
+
const shimPath = path9.join(outputDir, ".process-shim.js");
|
|
4551
4550
|
try {
|
|
4552
|
-
await
|
|
4551
|
+
await fs8.unlink(shimPath);
|
|
4553
4552
|
} catch {
|
|
4554
4553
|
}
|
|
4555
4554
|
process.exit(0);
|
|
@@ -4558,8 +4557,8 @@ async function devCommand(options) {
|
|
|
4558
4557
|
|
|
4559
4558
|
// src/commands/config.ts
|
|
4560
4559
|
init_logger();
|
|
4561
|
-
var CONFIG_DIR =
|
|
4562
|
-
var CONFIG_FILE =
|
|
4560
|
+
var CONFIG_DIR = path9.join(os.homedir(), ".onexthm");
|
|
4561
|
+
var CONFIG_FILE = path9.join(CONFIG_DIR, ".env");
|
|
4563
4562
|
var CONFIG_ENTRIES = [
|
|
4564
4563
|
{
|
|
4565
4564
|
key: "AWS_ACCESS_KEY_ID",
|
|
@@ -4826,13 +4825,13 @@ async function publishCommand(options) {
|
|
|
4826
4825
|
logger.info(`Logged in as: ${tokens.user.email}`);
|
|
4827
4826
|
let themePath;
|
|
4828
4827
|
if (options.theme) {
|
|
4829
|
-
themePath =
|
|
4828
|
+
themePath = path9.resolve(options.theme);
|
|
4830
4829
|
} else {
|
|
4831
4830
|
const isThemeDir = [
|
|
4832
4831
|
"theme.config.ts",
|
|
4833
4832
|
"bundle-entry.ts",
|
|
4834
4833
|
"manifest.ts"
|
|
4835
|
-
].some((f) => fs.existsSync(
|
|
4834
|
+
].some((f) => fs.existsSync(path9.join(process.cwd(), f)));
|
|
4836
4835
|
if (isThemeDir) {
|
|
4837
4836
|
themePath = process.cwd();
|
|
4838
4837
|
} else {
|
|
@@ -4842,13 +4841,13 @@ async function publishCommand(options) {
|
|
|
4842
4841
|
process.exit(1);
|
|
4843
4842
|
}
|
|
4844
4843
|
}
|
|
4845
|
-
const pkgPath =
|
|
4844
|
+
const pkgPath = path9.join(themePath, "package.json");
|
|
4846
4845
|
if (!fs.existsSync(pkgPath)) {
|
|
4847
4846
|
logger.error("No package.json found in theme directory");
|
|
4848
4847
|
process.exit(1);
|
|
4849
4848
|
}
|
|
4850
4849
|
const pkg = fs.readJsonSync(pkgPath);
|
|
4851
|
-
const themeId = pkg.name?.replace("@onex-themes/", "") ||
|
|
4850
|
+
const themeId = pkg.name?.replace("@onex-themes/", "") || path9.basename(themePath);
|
|
4852
4851
|
if (options.bump) {
|
|
4853
4852
|
const currentVersion = pkg.version || "1.0.0";
|
|
4854
4853
|
const newVersion = semver.inc(currentVersion, options.bump);
|
|
@@ -4980,13 +4979,13 @@ Or use the --bump flag:
|
|
|
4980
4979
|
try {
|
|
4981
4980
|
const archiver3 = await import('archiver');
|
|
4982
4981
|
const { createWriteStream } = await import('fs');
|
|
4983
|
-
const distDir =
|
|
4982
|
+
const distDir = path9.join(themePath, "dist");
|
|
4984
4983
|
if (!fs.existsSync(distDir)) {
|
|
4985
4984
|
logger.stopSpinner(false, "No dist/ directory");
|
|
4986
4985
|
logger.error("Build the theme first: onexthm build");
|
|
4987
4986
|
process.exit(1);
|
|
4988
4987
|
}
|
|
4989
|
-
const bundleZipPath =
|
|
4988
|
+
const bundleZipPath = path9.join(themePath, "dist", "bundle.zip");
|
|
4990
4989
|
await createZip(distDir, bundleZipPath, [
|
|
4991
4990
|
"bundle.zip",
|
|
4992
4991
|
"source.zip",
|
|
@@ -5011,7 +5010,7 @@ Or use the --bump flag:
|
|
|
5011
5010
|
}
|
|
5012
5011
|
logger.startSpinner("Uploading source...");
|
|
5013
5012
|
try {
|
|
5014
|
-
const sourceZipPath =
|
|
5013
|
+
const sourceZipPath = path9.join(themePath, "dist", "source.zip");
|
|
5015
5014
|
await createZip(themePath, sourceZipPath, [
|
|
5016
5015
|
"node_modules",
|
|
5017
5016
|
"dist",
|
|
@@ -5096,17 +5095,23 @@ async function createZip(sourceDir, outputPath, exclude) {
|
|
|
5096
5095
|
}
|
|
5097
5096
|
|
|
5098
5097
|
// src/cli.ts
|
|
5098
|
+
dotenv.config({
|
|
5099
|
+
path: path9.join(process.cwd(), ".env.local"),
|
|
5100
|
+
override: true
|
|
5101
|
+
});
|
|
5102
|
+
dotenv.config({ path: path9.join(process.cwd(), ".env") });
|
|
5099
5103
|
try {
|
|
5100
5104
|
const projectRoot = getProjectRoot();
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5105
|
+
if (path9.resolve(projectRoot) !== path9.resolve(process.cwd())) {
|
|
5106
|
+
dotenv.config({
|
|
5107
|
+
path: path9.join(projectRoot, ".env.local")
|
|
5108
|
+
});
|
|
5109
|
+
dotenv.config({ path: path9.join(projectRoot, ".env") });
|
|
5110
|
+
}
|
|
5106
5111
|
} catch {
|
|
5107
5112
|
}
|
|
5108
5113
|
dotenv.config({
|
|
5109
|
-
path:
|
|
5114
|
+
path: path9.join(os.homedir(), ".onexthm", ".env"),
|
|
5110
5115
|
quiet: true
|
|
5111
5116
|
});
|
|
5112
5117
|
var require2 = createRequire(import.meta.url);
|