@onexapis/cli 1.1.66 → 1.1.70
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 +901 -695
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +898 -692
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +571 -411
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +568 -408
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/templates/default/package.json +5 -0
package/dist/cli.js
CHANGED
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
|
|
4
4
|
var chalk4 = require('chalk');
|
|
5
5
|
var ora = require('ora');
|
|
6
|
-
var
|
|
6
|
+
var fs3 = require('fs');
|
|
7
|
+
var path13 = require('path');
|
|
7
8
|
var glob = require('glob');
|
|
8
|
-
var
|
|
9
|
+
var fs8 = require('fs-extra');
|
|
9
10
|
var crypto = require('crypto');
|
|
11
|
+
var fs11 = require('fs/promises');
|
|
10
12
|
var esbuild = require('esbuild');
|
|
11
|
-
var fs9 = require('fs/promises');
|
|
12
13
|
var module$1 = require('module');
|
|
13
14
|
var http = require('http');
|
|
14
|
-
var fs3 = require('fs');
|
|
15
15
|
var ws = require('ws');
|
|
16
16
|
var os = require('os');
|
|
17
17
|
var dotenv = require('dotenv');
|
|
@@ -49,13 +49,13 @@ function _interopNamespace(e) {
|
|
|
49
49
|
|
|
50
50
|
var chalk4__default = /*#__PURE__*/_interopDefault(chalk4);
|
|
51
51
|
var ora__default = /*#__PURE__*/_interopDefault(ora);
|
|
52
|
-
var
|
|
53
|
-
var
|
|
52
|
+
var fs3__default = /*#__PURE__*/_interopDefault(fs3);
|
|
53
|
+
var path13__default = /*#__PURE__*/_interopDefault(path13);
|
|
54
|
+
var fs8__default = /*#__PURE__*/_interopDefault(fs8);
|
|
54
55
|
var crypto__default = /*#__PURE__*/_interopDefault(crypto);
|
|
56
|
+
var fs11__default = /*#__PURE__*/_interopDefault(fs11);
|
|
55
57
|
var esbuild__namespace = /*#__PURE__*/_interopNamespace(esbuild);
|
|
56
|
-
var fs9__default = /*#__PURE__*/_interopDefault(fs9);
|
|
57
58
|
var http__default = /*#__PURE__*/_interopDefault(http);
|
|
58
|
-
var fs3__default = /*#__PURE__*/_interopDefault(fs3);
|
|
59
59
|
var os__default = /*#__PURE__*/_interopDefault(os);
|
|
60
60
|
var dotenv__default = /*#__PURE__*/_interopDefault(dotenv);
|
|
61
61
|
var ejs__default = /*#__PURE__*/_interopDefault(ejs);
|
|
@@ -132,6 +132,13 @@ var init_logger = __esm({
|
|
|
132
132
|
logger = new Logger();
|
|
133
133
|
}
|
|
134
134
|
});
|
|
135
|
+
function isNextjsProject(dir) {
|
|
136
|
+
return fs3__default.default.existsSync(path13__default.default.join(dir, "next.config.ts")) || fs3__default.default.existsSync(path13__default.default.join(dir, "next.config.js")) || fs3__default.default.existsSync(path13__default.default.join(dir, "next.config.mjs"));
|
|
137
|
+
}
|
|
138
|
+
var init_detect_nextjs = __esm({
|
|
139
|
+
"src/utils/detect-nextjs.ts"() {
|
|
140
|
+
}
|
|
141
|
+
});
|
|
135
142
|
function sortedCopy(value) {
|
|
136
143
|
if (Array.isArray(value)) {
|
|
137
144
|
return value.map((v) => sortedCopy(v));
|
|
@@ -214,7 +221,7 @@ async function extractSchemas(themePath) {
|
|
|
214
221
|
const sections = {};
|
|
215
222
|
for (const file of schemaFiles) {
|
|
216
223
|
try {
|
|
217
|
-
const mod = await jiti.import(
|
|
224
|
+
const mod = await jiti.import(path13__default.default.join(themePath, file));
|
|
218
225
|
const exports$1 = mod;
|
|
219
226
|
for (const value of Object.values(exports$1)) {
|
|
220
227
|
if (value && typeof value === "object" && typeof value.type === "string" && Array.isArray(value.settings)) {
|
|
@@ -246,24 +253,24 @@ function isVideoAsset(filePath) {
|
|
|
246
253
|
return VIDEO_EXTENSIONS.some((ext) => lower.endsWith(ext));
|
|
247
254
|
}
|
|
248
255
|
function mimeFor(filename) {
|
|
249
|
-
const ext =
|
|
256
|
+
const ext = path13__default.default.extname(filename).toLowerCase();
|
|
250
257
|
return MIME_MAP[ext] || "application/octet-stream";
|
|
251
258
|
}
|
|
252
259
|
async function sha256Prefix(absPath, len) {
|
|
253
|
-
const buf = await
|
|
260
|
+
const buf = await fs8__default.default.readFile(absPath);
|
|
254
261
|
return crypto__default.default.createHash("sha256").update(buf).digest("hex").slice(0, len);
|
|
255
262
|
}
|
|
256
263
|
function insertHashIntoName(relPath, hash) {
|
|
257
|
-
const dir =
|
|
258
|
-
const base =
|
|
259
|
-
const ext =
|
|
264
|
+
const dir = path13__default.default.posix.dirname(relPath);
|
|
265
|
+
const base = path13__default.default.posix.basename(relPath);
|
|
266
|
+
const ext = path13__default.default.posix.extname(base);
|
|
260
267
|
const stem = ext ? base.slice(0, -ext.length) : base;
|
|
261
268
|
const hashed = `${stem}-${hash}${ext}`;
|
|
262
269
|
return dir === "." ? hashed : `${dir}/${hashed}`;
|
|
263
270
|
}
|
|
264
271
|
async function scanThemeAssets(distDir) {
|
|
265
|
-
const assetsDir =
|
|
266
|
-
if (!await
|
|
272
|
+
const assetsDir = path13__default.default.join(distDir, "theme-assets");
|
|
273
|
+
if (!await fs8__default.default.pathExists(assetsDir)) return [];
|
|
267
274
|
const files = await glob.glob("**/*", {
|
|
268
275
|
cwd: assetsDir,
|
|
269
276
|
nodir: true,
|
|
@@ -271,10 +278,10 @@ async function scanThemeAssets(distDir) {
|
|
|
271
278
|
});
|
|
272
279
|
const results = [];
|
|
273
280
|
for (const rel of files) {
|
|
274
|
-
const absPath =
|
|
275
|
-
const stat = await
|
|
281
|
+
const absPath = path13__default.default.join(assetsDir, rel);
|
|
282
|
+
const stat = await fs8__default.default.stat(absPath);
|
|
276
283
|
if (!stat.isFile()) continue;
|
|
277
|
-
const originalPath = rel.split(
|
|
284
|
+
const originalPath = rel.split(path13__default.default.sep).join("/");
|
|
278
285
|
const hash = await sha256Prefix(absPath, HASH_LEN);
|
|
279
286
|
const hashedPath = insertHashIntoName(originalPath, hash);
|
|
280
287
|
const contentType = mimeFor(rel);
|
|
@@ -332,6 +339,101 @@ var init_scan_theme_assets = __esm({
|
|
|
332
339
|
];
|
|
333
340
|
}
|
|
334
341
|
});
|
|
342
|
+
async function scanAppDirectory(themePath) {
|
|
343
|
+
const appDir = path13__default.default.join(themePath, "app");
|
|
344
|
+
let pageFiles;
|
|
345
|
+
try {
|
|
346
|
+
pageFiles = await glob.glob("**/page.{tsx,ts,jsx,js}", { cwd: appDir });
|
|
347
|
+
} catch {
|
|
348
|
+
return [];
|
|
349
|
+
}
|
|
350
|
+
if (pageFiles.length === 0) return [];
|
|
351
|
+
const pages = [];
|
|
352
|
+
for (const pageFile of pageFiles) {
|
|
353
|
+
const routePath = deriveRoutePath(pageFile);
|
|
354
|
+
const absPageFile = path13__default.default.join(appDir, pageFile);
|
|
355
|
+
let source;
|
|
356
|
+
try {
|
|
357
|
+
source = await fs11__default.default.readFile(absPageFile, "utf-8");
|
|
358
|
+
} catch {
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
const sections = await extractSectionsFromPage(source, themePath);
|
|
362
|
+
pages.push({
|
|
363
|
+
routePath,
|
|
364
|
+
sourceFile: path13__default.default.join("app", pageFile),
|
|
365
|
+
sections
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
return pages;
|
|
369
|
+
}
|
|
370
|
+
function deriveRoutePath(pageFile) {
|
|
371
|
+
const dir = path13__default.default.dirname(pageFile);
|
|
372
|
+
if (dir === ".") return "/";
|
|
373
|
+
return "/" + dir;
|
|
374
|
+
}
|
|
375
|
+
async function extractSectionsFromPage(source, themePath) {
|
|
376
|
+
const importRegex = /import\s+\w+\s+from\s+["'](@\/|\.\.?\/)(components\/[^"']+)["']/g;
|
|
377
|
+
const sections = [];
|
|
378
|
+
const seen = /* @__PURE__ */ new Set();
|
|
379
|
+
for (const match of source.matchAll(importRegex)) {
|
|
380
|
+
const rawImportPath = match[2];
|
|
381
|
+
const componentDir = path13__default.default.dirname(rawImportPath);
|
|
382
|
+
const absComponentDir = path13__default.default.join(themePath, componentDir);
|
|
383
|
+
if (seen.has(componentDir)) continue;
|
|
384
|
+
seen.add(componentDir);
|
|
385
|
+
const sectionJsonPath = path13__default.default.join(absComponentDir, "section.json");
|
|
386
|
+
let sectionJson;
|
|
387
|
+
try {
|
|
388
|
+
const raw = await fs11__default.default.readFile(sectionJsonPath, "utf-8");
|
|
389
|
+
sectionJson = JSON.parse(raw);
|
|
390
|
+
} catch {
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
393
|
+
if (sectionJson.type !== "opaque-react") continue;
|
|
394
|
+
if (!sectionJson.entry) continue;
|
|
395
|
+
sections.push({
|
|
396
|
+
type: "opaque-react",
|
|
397
|
+
name: sectionJson.name ?? path13__default.default.basename(componentDir),
|
|
398
|
+
entry: path13__default.default.join(componentDir, sectionJson.entry),
|
|
399
|
+
componentDir
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
return sections;
|
|
403
|
+
}
|
|
404
|
+
function buildNextjsPagesMap(pages, themeId) {
|
|
405
|
+
const result = {};
|
|
406
|
+
for (const page of pages) {
|
|
407
|
+
const id = page.routePath === "/" ? "home" : page.routePath.replace(/\//g, "-").replace(/^-/, "");
|
|
408
|
+
const makeSectionType = (name) => `${themeId}-${name.toLowerCase().replace(/\s+/g, "-")}`;
|
|
409
|
+
result[id] = {
|
|
410
|
+
id,
|
|
411
|
+
name: id.charAt(0).toUpperCase() + id.slice(1),
|
|
412
|
+
path: page.routePath,
|
|
413
|
+
config: {
|
|
414
|
+
id,
|
|
415
|
+
path: page.routePath,
|
|
416
|
+
sections: page.sections.map((s, i) => ({
|
|
417
|
+
id: `${id}-section-${i}`,
|
|
418
|
+
type: makeSectionType(s.name),
|
|
419
|
+
sectionType: "opaque-react",
|
|
420
|
+
settings: {}
|
|
421
|
+
}))
|
|
422
|
+
},
|
|
423
|
+
sections: page.sections.map((s, i) => ({
|
|
424
|
+
id: `${id}-section-${i}`,
|
|
425
|
+
type: makeSectionType(s.name),
|
|
426
|
+
sectionType: "opaque-react",
|
|
427
|
+
settings: {}
|
|
428
|
+
}))
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
return result;
|
|
432
|
+
}
|
|
433
|
+
var init_nextjs_page_scanner = __esm({
|
|
434
|
+
"src/utils/nextjs-page-scanner.ts"() {
|
|
435
|
+
}
|
|
436
|
+
});
|
|
335
437
|
|
|
336
438
|
// src/utils/compile-theme.ts
|
|
337
439
|
var compile_theme_exports = {};
|
|
@@ -347,8 +449,8 @@ async function generateThemeCSS(themePath, outDir) {
|
|
|
347
449
|
const tailwindcss = (await import('tailwindcss')).default;
|
|
348
450
|
const tailwindConfig = {
|
|
349
451
|
content: [
|
|
350
|
-
|
|
351
|
-
|
|
452
|
+
path13__default.default.join(themePath, "sections/**/*.{ts,tsx}"),
|
|
453
|
+
path13__default.default.join(themePath, "components/**/*.{ts,tsx}")
|
|
352
454
|
],
|
|
353
455
|
theme: { extend: {} },
|
|
354
456
|
plugins: []
|
|
@@ -358,7 +460,7 @@ async function generateThemeCSS(themePath, outDir) {
|
|
|
358
460
|
inputCSS,
|
|
359
461
|
{ from: void 0 }
|
|
360
462
|
);
|
|
361
|
-
await
|
|
463
|
+
await fs11__default.default.writeFile(path13__default.default.join(outDir, "bundle.css"), result.css);
|
|
362
464
|
logger.info("Generated bundle.css");
|
|
363
465
|
} catch (err) {
|
|
364
466
|
logger.warning(
|
|
@@ -369,12 +471,12 @@ async function generateThemeCSS(themePath, outDir) {
|
|
|
369
471
|
async function resolveNodeModulesFile(startDir, relativePath) {
|
|
370
472
|
let dir = startDir;
|
|
371
473
|
while (true) {
|
|
372
|
-
const candidate =
|
|
474
|
+
const candidate = path13__default.default.join(dir, "node_modules", relativePath);
|
|
373
475
|
try {
|
|
374
|
-
await
|
|
476
|
+
await fs11__default.default.access(candidate);
|
|
375
477
|
return candidate;
|
|
376
478
|
} catch {
|
|
377
|
-
const parent =
|
|
479
|
+
const parent = path13__default.default.dirname(dir);
|
|
378
480
|
if (parent === dir) break;
|
|
379
481
|
dir = parent;
|
|
380
482
|
}
|
|
@@ -398,7 +500,7 @@ async function scanImportsFromPackage(sourceDir, packageName) {
|
|
|
398
500
|
});
|
|
399
501
|
for (const file of sourceFiles) {
|
|
400
502
|
try {
|
|
401
|
-
const content = await
|
|
503
|
+
const content = await fs11__default.default.readFile(path13__default.default.join(sourceDir, file), "utf-8");
|
|
402
504
|
for (const match of content.matchAll(namespaceImportRegex)) {
|
|
403
505
|
const subpath = match[1] ? match[1].slice(1) : "";
|
|
404
506
|
if (!result[subpath]) result[subpath] = /* @__PURE__ */ new Set();
|
|
@@ -452,17 +554,17 @@ function createCoreGlobalPlugin(themePath) {
|
|
|
452
554
|
const distFileName = subpath ? `${subpath}.mjs` : "index.mjs";
|
|
453
555
|
let distPath = await resolveNodeModulesFile(
|
|
454
556
|
themePath,
|
|
455
|
-
|
|
557
|
+
path13__default.default.join("@onexapis", "core", "dist", distFileName)
|
|
456
558
|
);
|
|
457
559
|
if (!distPath) {
|
|
458
560
|
distPath = await resolveNodeModulesFile(
|
|
459
561
|
__dirname,
|
|
460
|
-
|
|
562
|
+
path13__default.default.join("@onexapis", "core", "dist", distFileName)
|
|
461
563
|
);
|
|
462
564
|
}
|
|
463
565
|
try {
|
|
464
566
|
if (!distPath) throw new Error("not found");
|
|
465
|
-
const distContent = await
|
|
567
|
+
const distContent = await fs11__default.default.readFile(distPath, "utf-8");
|
|
466
568
|
const exportMatches = distContent.matchAll(/export\s*\{([^}]+)\}/g);
|
|
467
569
|
for (const m of exportMatches) {
|
|
468
570
|
const names = m[1].split(",").map((n) => {
|
|
@@ -509,180 +611,6 @@ ${namedExportLines}
|
|
|
509
611
|
}
|
|
510
612
|
};
|
|
511
613
|
}
|
|
512
|
-
function createThemeDepsStubPlugin(themePath) {
|
|
513
|
-
return {
|
|
514
|
-
name: "theme-deps-stub",
|
|
515
|
-
setup(build2) {
|
|
516
|
-
const tryResolveOrStub = (filter, namespace) => {
|
|
517
|
-
build2.onResolve({ filter }, async (args) => {
|
|
518
|
-
if (args.pluginData?.skipStub) return void 0;
|
|
519
|
-
try {
|
|
520
|
-
const result = await build2.resolve(args.path, {
|
|
521
|
-
kind: args.kind,
|
|
522
|
-
resolveDir: args.resolveDir || themePath,
|
|
523
|
-
importer: args.importer,
|
|
524
|
-
namespace: "file",
|
|
525
|
-
pluginData: { skipStub: true }
|
|
526
|
-
});
|
|
527
|
-
if (!result.errors.length) return result;
|
|
528
|
-
} catch {
|
|
529
|
-
}
|
|
530
|
-
try {
|
|
531
|
-
const req = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.js', document.baseURI).href)) || __filename);
|
|
532
|
-
const resolved = req.resolve(args.path);
|
|
533
|
-
if (resolved) return { path: resolved, namespace: "file" };
|
|
534
|
-
} catch {
|
|
535
|
-
}
|
|
536
|
-
return { path: args.path, namespace };
|
|
537
|
-
});
|
|
538
|
-
};
|
|
539
|
-
tryResolveOrStub(/^next\//, "next-stub");
|
|
540
|
-
build2.onLoad({ filter: /.*/, namespace: "next-stub" }, (args) => {
|
|
541
|
-
const stubs = {
|
|
542
|
-
"next/image": `
|
|
543
|
-
import React from 'react';
|
|
544
|
-
const Image = React.forwardRef((props, ref) => {
|
|
545
|
-
const { src, alt, width, height, fill, priority, sizes, quality, placeholder, blurDataURL, onLoad, onError, style, className, ...rest } = props;
|
|
546
|
-
const imgSrc = typeof src === 'object' ? src.src : src;
|
|
547
|
-
const fillStyle = fill ? { position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: style?.objectFit || 'cover', display: 'block' } : {};
|
|
548
|
-
const mergedStyle = { ...fillStyle, ...style };
|
|
549
|
-
return React.createElement('img', {
|
|
550
|
-
ref, src: imgSrc, alt,
|
|
551
|
-
width: fill ? undefined : width, height: fill ? undefined : height,
|
|
552
|
-
loading: priority ? 'eager' : 'lazy',
|
|
553
|
-
style: Object.keys(mergedStyle).length > 0 ? mergedStyle : undefined,
|
|
554
|
-
className, onLoad, onError, ...rest,
|
|
555
|
-
});
|
|
556
|
-
});
|
|
557
|
-
export default Image;
|
|
558
|
-
`,
|
|
559
|
-
"next/link": `
|
|
560
|
-
import React from 'react';
|
|
561
|
-
const Link = ({ href, children, ...rest }) => React.createElement('a', { href, ...rest }, children);
|
|
562
|
-
export default Link;
|
|
563
|
-
`,
|
|
564
|
-
"next/navigation": `
|
|
565
|
-
export function useRouter() { return { push(u){window.location.href=u}, replace(u){window.location.href=u}, back(){window.history.back()}, forward(){window.history.forward()}, refresh(){window.location.reload()}, prefetch(){} }; }
|
|
566
|
-
export function usePathname() { return window.location.pathname; }
|
|
567
|
-
export function useSearchParams() { return new URLSearchParams(window.location.search); }
|
|
568
|
-
export function useParams() { return {}; }
|
|
569
|
-
export function redirect(url) { window.location.href = url; }
|
|
570
|
-
export function notFound() { throw new Error('Not Found'); }
|
|
571
|
-
`,
|
|
572
|
-
"next/headers": `
|
|
573
|
-
export function cookies() { return { get(){}, getAll(){ return []; }, set(){}, delete(){}, has(){ return false; } }; }
|
|
574
|
-
export function headers() { return new Headers(); }
|
|
575
|
-
`
|
|
576
|
-
};
|
|
577
|
-
return {
|
|
578
|
-
contents: stubs[args.path] || "export default {};",
|
|
579
|
-
loader: "jsx",
|
|
580
|
-
resolveDir: themePath
|
|
581
|
-
};
|
|
582
|
-
});
|
|
583
|
-
const lucideImports = /* @__PURE__ */ new Set();
|
|
584
|
-
let lucideThemeScanned = false;
|
|
585
|
-
tryResolveOrStub(/^lucide-react/, "lucide-stub");
|
|
586
|
-
build2.onLoad({ filter: /.*/, namespace: "lucide-stub" }, async () => {
|
|
587
|
-
if (!lucideThemeScanned) {
|
|
588
|
-
lucideThemeScanned = true;
|
|
589
|
-
try {
|
|
590
|
-
const scanned = await scanImportsFromPackage(
|
|
591
|
-
themePath,
|
|
592
|
-
"lucide-react"
|
|
593
|
-
);
|
|
594
|
-
for (const names of Object.values(scanned)) {
|
|
595
|
-
for (const name of names) lucideImports.add(name);
|
|
596
|
-
}
|
|
597
|
-
} catch {
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
const iconNames = [...lucideImports];
|
|
601
|
-
const exports$1 = iconNames.map((n) => `icon as ${n}`).join(", ");
|
|
602
|
-
return {
|
|
603
|
-
contents: `
|
|
604
|
-
const icon = (props) => null;
|
|
605
|
-
export { ${exports$1} };
|
|
606
|
-
export default new Proxy({}, { get: (_, name) => name === '__esModule' ? true : icon });
|
|
607
|
-
`.trim(),
|
|
608
|
-
loader: "jsx"
|
|
609
|
-
};
|
|
610
|
-
});
|
|
611
|
-
tryResolveOrStub(/^framer-motion/, "motion-stub");
|
|
612
|
-
build2.onLoad({ filter: /.*/, namespace: "motion-stub" }, () => ({
|
|
613
|
-
contents: `
|
|
614
|
-
import React from 'react';
|
|
615
|
-
const handler = { get: (_, name) => {
|
|
616
|
-
if (name === '__esModule') return true;
|
|
617
|
-
return React.forwardRef((props, ref) => React.createElement(name, { ...props, ref }));
|
|
618
|
-
}};
|
|
619
|
-
export const motion = new Proxy({}, handler);
|
|
620
|
-
export const AnimatePresence = ({ children }) => children || null;
|
|
621
|
-
export function useInView() { return true; }
|
|
622
|
-
export default { motion, AnimatePresence, useInView };
|
|
623
|
-
`.trim(),
|
|
624
|
-
loader: "jsx",
|
|
625
|
-
resolveDir: themePath
|
|
626
|
-
}));
|
|
627
|
-
tryResolveOrStub(/^sonner$/, "sonner-stub");
|
|
628
|
-
build2.onLoad({ filter: /.*/, namespace: "sonner-stub" }, () => ({
|
|
629
|
-
contents: `
|
|
630
|
-
export const toast = new Proxy(() => {}, { get: () => () => {} });
|
|
631
|
-
export const Toaster = () => null;
|
|
632
|
-
export default { toast, Toaster };
|
|
633
|
-
`.trim(),
|
|
634
|
-
loader: "jsx"
|
|
635
|
-
}));
|
|
636
|
-
tryResolveOrStub(/^react-hook-form$/, "rhf-stub");
|
|
637
|
-
build2.onLoad({ filter: /.*/, namespace: "rhf-stub" }, () => ({
|
|
638
|
-
contents: `
|
|
639
|
-
export function useForm() {
|
|
640
|
-
return {
|
|
641
|
-
register: () => ({}),
|
|
642
|
-
handleSubmit: (fn) => (e) => { e?.preventDefault?.(); fn({}); },
|
|
643
|
-
formState: { errors: {}, isSubmitting: false, isValid: true },
|
|
644
|
-
watch: () => undefined,
|
|
645
|
-
setValue: () => {},
|
|
646
|
-
reset: () => {},
|
|
647
|
-
control: {},
|
|
648
|
-
};
|
|
649
|
-
}
|
|
650
|
-
export function useController() { return { field: {}, fieldState: {} }; }
|
|
651
|
-
export function useFormContext() { return useForm(); }
|
|
652
|
-
`.trim(),
|
|
653
|
-
loader: "js"
|
|
654
|
-
}));
|
|
655
|
-
tryResolveOrStub(/^@hookform\/resolvers/, "hookform-resolvers-stub");
|
|
656
|
-
build2.onLoad(
|
|
657
|
-
{ filter: /.*/, namespace: "hookform-resolvers-stub" },
|
|
658
|
-
() => ({
|
|
659
|
-
contents: `export function zodResolver() { return () => ({ values: {}, errors: {} }); }`,
|
|
660
|
-
loader: "js"
|
|
661
|
-
})
|
|
662
|
-
);
|
|
663
|
-
tryResolveOrStub(/^next-intl$/, "next-intl-stub");
|
|
664
|
-
build2.onLoad({ filter: /.*/, namespace: "next-intl-stub" }, () => ({
|
|
665
|
-
contents: `
|
|
666
|
-
export function useTranslations(ns) {
|
|
667
|
-
return (key) => ns ? ns + '.' + key : key;
|
|
668
|
-
}
|
|
669
|
-
export function useLocale() { return 'en'; }
|
|
670
|
-
export function useMessages() { return {}; }
|
|
671
|
-
`.trim(),
|
|
672
|
-
loader: "js"
|
|
673
|
-
}));
|
|
674
|
-
tryResolveOrStub(/^zod$/, "zod-stub");
|
|
675
|
-
build2.onLoad({ filter: /.*/, namespace: "zod-stub" }, () => ({
|
|
676
|
-
contents: `
|
|
677
|
-
const schema = () => ({ parse: (v) => v, safeParse: (v) => ({ success: true, data: v }), optional: schema, min: schema, max: schema, email: schema, url: schema, regex: schema, refine: schema, transform: schema });
|
|
678
|
-
export const z = { string: schema, number: schema, boolean: schema, object: (s) => ({ ...schema(), shape: s }), array: schema, enum: schema, union: schema, literal: schema, infer: undefined };
|
|
679
|
-
export default z;
|
|
680
|
-
`.trim(),
|
|
681
|
-
loader: "js"
|
|
682
|
-
}));
|
|
683
|
-
}
|
|
684
|
-
};
|
|
685
|
-
}
|
|
686
614
|
async function generateThemeData(themePath, outputDir, themeId) {
|
|
687
615
|
const { createJiti } = await import('jiti');
|
|
688
616
|
const jiti = createJiti((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.js', document.baseURI).href)));
|
|
@@ -691,7 +619,7 @@ async function generateThemeData(themePath, outputDir, themeId) {
|
|
|
691
619
|
const pages = {};
|
|
692
620
|
for (const ext of [".ts", ".js"]) {
|
|
693
621
|
try {
|
|
694
|
-
const mod = await jiti.import(
|
|
622
|
+
const mod = await jiti.import(path13__default.default.join(themePath, `theme.config${ext}`));
|
|
695
623
|
themeConfig = mod.default || mod;
|
|
696
624
|
break;
|
|
697
625
|
} catch {
|
|
@@ -699,20 +627,20 @@ async function generateThemeData(themePath, outputDir, themeId) {
|
|
|
699
627
|
}
|
|
700
628
|
for (const ext of [".ts", ".js"]) {
|
|
701
629
|
try {
|
|
702
|
-
const mod = await jiti.import(
|
|
630
|
+
const mod = await jiti.import(path13__default.default.join(themePath, `theme.layout${ext}`));
|
|
703
631
|
layoutConfig = mod.default || mod;
|
|
704
632
|
break;
|
|
705
633
|
} catch {
|
|
706
634
|
}
|
|
707
635
|
}
|
|
708
636
|
const schemas = {};
|
|
709
|
-
const sectionsDir =
|
|
637
|
+
const sectionsDir = path13__default.default.join(themePath, "sections");
|
|
710
638
|
try {
|
|
711
|
-
const sectionDirs = await
|
|
639
|
+
const sectionDirs = await fs11__default.default.readdir(sectionsDir);
|
|
712
640
|
for (const dir of sectionDirs) {
|
|
713
|
-
const schemaFile =
|
|
641
|
+
const schemaFile = path13__default.default.join(sectionsDir, dir, `${dir}.schema.ts`);
|
|
714
642
|
try {
|
|
715
|
-
await
|
|
643
|
+
await fs11__default.default.access(schemaFile);
|
|
716
644
|
const mod = await jiti.import(schemaFile);
|
|
717
645
|
for (const [key, value] of Object.entries(mod)) {
|
|
718
646
|
if (key.endsWith("Schema") && value && typeof value === "object" && value.type) {
|
|
@@ -724,14 +652,14 @@ async function generateThemeData(themePath, outputDir, themeId) {
|
|
|
724
652
|
}
|
|
725
653
|
} catch {
|
|
726
654
|
}
|
|
727
|
-
const pagesDir =
|
|
655
|
+
const pagesDir = path13__default.default.join(themePath, "pages");
|
|
728
656
|
try {
|
|
729
|
-
const files = await
|
|
657
|
+
const files = await fs11__default.default.readdir(pagesDir);
|
|
730
658
|
for (const file of files) {
|
|
731
659
|
if (!file.match(/\.(ts|js)$/)) continue;
|
|
732
660
|
const name = file.replace(/\.(ts|js)$/, "");
|
|
733
661
|
try {
|
|
734
|
-
const mod = await jiti.import(
|
|
662
|
+
const mod = await jiti.import(path13__default.default.join(pagesDir, file));
|
|
735
663
|
const config = mod.default || mod;
|
|
736
664
|
const sections = (config.sections || []).map((section) => {
|
|
737
665
|
const schema = schemas[section.type];
|
|
@@ -759,8 +687,16 @@ async function generateThemeData(themePath, outputDir, themeId) {
|
|
|
759
687
|
}
|
|
760
688
|
} catch {
|
|
761
689
|
}
|
|
762
|
-
|
|
763
|
-
|
|
690
|
+
if (isNextjsProject(themePath)) {
|
|
691
|
+
const nextjsPages = await scanAppDirectory(themePath);
|
|
692
|
+
if (nextjsPages.length > 0) {
|
|
693
|
+
const nextjsPagesMap = buildNextjsPagesMap(nextjsPages, themeId);
|
|
694
|
+
Object.assign(pages, nextjsPagesMap);
|
|
695
|
+
logger.info(`Scanned ${nextjsPages.length} Next.js app/ pages`);
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
await fs11__default.default.writeFile(
|
|
699
|
+
path13__default.default.join(outputDir, "theme-data.json"),
|
|
764
700
|
JSON.stringify(
|
|
765
701
|
{
|
|
766
702
|
themeId,
|
|
@@ -783,22 +719,22 @@ async function generateThemeData(themePath, outputDir, themeId) {
|
|
|
783
719
|
logger.info(`Generated theme-data.json (${Object.keys(pages).length} pages)`);
|
|
784
720
|
}
|
|
785
721
|
async function contentHashEntry(outputDir) {
|
|
786
|
-
const entryPath =
|
|
787
|
-
const mapPath =
|
|
722
|
+
const entryPath = path13__default.default.join(outputDir, "bundle-entry.js");
|
|
723
|
+
const mapPath = path13__default.default.join(outputDir, "bundle-entry.js.map");
|
|
788
724
|
let entryContent;
|
|
789
725
|
try {
|
|
790
|
-
entryContent = await
|
|
726
|
+
entryContent = await fs11__default.default.readFile(entryPath, "utf-8");
|
|
791
727
|
} catch {
|
|
792
|
-
const indexPath =
|
|
728
|
+
const indexPath = path13__default.default.join(outputDir, "index.js");
|
|
793
729
|
try {
|
|
794
|
-
entryContent = await
|
|
730
|
+
entryContent = await fs11__default.default.readFile(indexPath, "utf-8");
|
|
795
731
|
} catch {
|
|
796
732
|
logger.warning("No entry file found in output, skipping content hash");
|
|
797
733
|
return;
|
|
798
734
|
}
|
|
799
735
|
const hash2 = crypto__default.default.createHash("sha256").update(entryContent).digest("hex").slice(0, 8);
|
|
800
736
|
const hashedName2 = `bundle-entry-${hash2}.js`;
|
|
801
|
-
const indexMapPath =
|
|
737
|
+
const indexMapPath = path13__default.default.join(outputDir, "index.js.map");
|
|
802
738
|
const hashedMapName2 = `bundle-entry-${hash2}.js.map`;
|
|
803
739
|
entryContent = entryContent.replace(
|
|
804
740
|
/\/\/# sourceMappingURL=index\.js\.map/,
|
|
@@ -806,18 +742,18 @@ async function contentHashEntry(outputDir) {
|
|
|
806
742
|
);
|
|
807
743
|
const oldFiles2 = await glob.glob("bundle-entry-*.js*", { cwd: outputDir });
|
|
808
744
|
for (const f of oldFiles2) {
|
|
809
|
-
await
|
|
745
|
+
await fs11__default.default.unlink(path13__default.default.join(outputDir, f));
|
|
810
746
|
}
|
|
811
|
-
await
|
|
812
|
-
await
|
|
747
|
+
await fs11__default.default.writeFile(path13__default.default.join(outputDir, hashedName2), entryContent);
|
|
748
|
+
await fs11__default.default.unlink(indexPath);
|
|
813
749
|
try {
|
|
814
|
-
await
|
|
750
|
+
await fs11__default.default.unlink(entryPath);
|
|
815
751
|
} catch {
|
|
816
752
|
}
|
|
817
|
-
await
|
|
753
|
+
await fs11__default.default.writeFile(entryPath, entryContent);
|
|
818
754
|
try {
|
|
819
|
-
await
|
|
820
|
-
await
|
|
755
|
+
await fs11__default.default.access(indexMapPath);
|
|
756
|
+
await fs11__default.default.rename(indexMapPath, path13__default.default.join(outputDir, hashedMapName2));
|
|
821
757
|
} catch {
|
|
822
758
|
}
|
|
823
759
|
logger.info(`Entry hashed: ${hashedName2}`);
|
|
@@ -832,17 +768,17 @@ async function contentHashEntry(outputDir) {
|
|
|
832
768
|
);
|
|
833
769
|
const oldFiles = await glob.glob("bundle-entry-*.js*", { cwd: outputDir });
|
|
834
770
|
for (const f of oldFiles) {
|
|
835
|
-
await
|
|
771
|
+
await fs11__default.default.unlink(path13__default.default.join(outputDir, f));
|
|
836
772
|
}
|
|
837
|
-
await
|
|
773
|
+
await fs11__default.default.writeFile(path13__default.default.join(outputDir, hashedName), entryContent);
|
|
838
774
|
try {
|
|
839
|
-
await
|
|
775
|
+
await fs11__default.default.unlink(entryPath);
|
|
840
776
|
} catch {
|
|
841
777
|
}
|
|
842
|
-
await
|
|
778
|
+
await fs11__default.default.writeFile(entryPath, entryContent);
|
|
843
779
|
try {
|
|
844
|
-
await
|
|
845
|
-
await
|
|
780
|
+
await fs11__default.default.access(mapPath);
|
|
781
|
+
await fs11__default.default.rename(mapPath, path13__default.default.join(outputDir, hashedMapName));
|
|
846
782
|
} catch {
|
|
847
783
|
}
|
|
848
784
|
logger.info(`Entry hashed: ${hashedName}`);
|
|
@@ -854,7 +790,7 @@ async function extractDataRequirements(themePath) {
|
|
|
854
790
|
const requirements = {};
|
|
855
791
|
for (const file of schemaFiles) {
|
|
856
792
|
try {
|
|
857
|
-
const mod = await jiti.import(
|
|
793
|
+
const mod = await jiti.import(path13__default.default.join(themePath, file));
|
|
858
794
|
const exports$1 = mod;
|
|
859
795
|
for (const value of Object.values(exports$1)) {
|
|
860
796
|
if (value && typeof value === "object" && typeof value.type === "string" && value.dataRequirements && typeof value.dataRequirements === "object") {
|
|
@@ -872,8 +808,8 @@ async function extractDataRequirements(themePath) {
|
|
|
872
808
|
async function writeGateManifests(themePath, outputDir) {
|
|
873
809
|
try {
|
|
874
810
|
const schemas = await extractSchemas(themePath);
|
|
875
|
-
await
|
|
876
|
-
|
|
811
|
+
await fs11__default.default.writeFile(
|
|
812
|
+
path13__default.default.join(outputDir, "schemas.json"),
|
|
877
813
|
serializeManifest(schemas)
|
|
878
814
|
);
|
|
879
815
|
logger.info(
|
|
@@ -892,8 +828,8 @@ async function writeGateManifests(themePath, outputDir) {
|
|
|
892
828
|
size: e.size,
|
|
893
829
|
contentType: e.contentType
|
|
894
830
|
}));
|
|
895
|
-
await
|
|
896
|
-
|
|
831
|
+
await fs11__default.default.writeFile(
|
|
832
|
+
path13__default.default.join(outputDir, "asset-manifest.json"),
|
|
897
833
|
JSON.stringify({ manifestVersion: 1, assets }, null, 2)
|
|
898
834
|
);
|
|
899
835
|
logger.info(`Generated asset-manifest.json (${assets.length} assets)`);
|
|
@@ -903,12 +839,71 @@ async function writeGateManifests(themePath, outputDir) {
|
|
|
903
839
|
);
|
|
904
840
|
}
|
|
905
841
|
}
|
|
842
|
+
async function compileSections(themePath, outputDir) {
|
|
843
|
+
const sectionsDir = path13__default.default.join(themePath, "sections");
|
|
844
|
+
let sectionDirs;
|
|
845
|
+
try {
|
|
846
|
+
sectionDirs = await fs11__default.default.readdir(sectionsDir);
|
|
847
|
+
} catch {
|
|
848
|
+
return;
|
|
849
|
+
}
|
|
850
|
+
for (const dirName of sectionDirs) {
|
|
851
|
+
const sectionSrc = path13__default.default.join(sectionsDir, dirName);
|
|
852
|
+
const sectionOut = path13__default.default.join(outputDir, "sections", dirName);
|
|
853
|
+
let section = null;
|
|
854
|
+
try {
|
|
855
|
+
const raw = await fs11__default.default.readFile(
|
|
856
|
+
path13__default.default.join(sectionSrc, "section.manifest.json"),
|
|
857
|
+
"utf-8"
|
|
858
|
+
);
|
|
859
|
+
section = JSON.parse(raw);
|
|
860
|
+
} catch {
|
|
861
|
+
continue;
|
|
862
|
+
}
|
|
863
|
+
switch (section.type) {
|
|
864
|
+
case "editable":
|
|
865
|
+
case "opaque-react":
|
|
866
|
+
break;
|
|
867
|
+
case "html": {
|
|
868
|
+
await fs11__default.default.mkdir(sectionOut, { recursive: true });
|
|
869
|
+
const htmlSrc = path13__default.default.join(sectionSrc, section.html);
|
|
870
|
+
let htmlContent = await fs11__default.default.readFile(htmlSrc, "utf-8");
|
|
871
|
+
htmlContent = htmlContent.replace(
|
|
872
|
+
/<script[^>]+src=["']https?:\/\/[^"']*["'][^>]*><\/script>/gi,
|
|
873
|
+
""
|
|
874
|
+
);
|
|
875
|
+
await fs11__default.default.writeFile(path13__default.default.join(sectionOut, path13__default.default.basename(section.html)), htmlContent);
|
|
876
|
+
if (section.css) {
|
|
877
|
+
await fs11__default.default.copyFile(
|
|
878
|
+
path13__default.default.join(sectionSrc, section.css),
|
|
879
|
+
path13__default.default.join(sectionOut, path13__default.default.basename(section.css))
|
|
880
|
+
);
|
|
881
|
+
}
|
|
882
|
+
break;
|
|
883
|
+
}
|
|
884
|
+
case "iframe":
|
|
885
|
+
break;
|
|
886
|
+
case "webcomponent": {
|
|
887
|
+
await fs11__default.default.mkdir(sectionOut, { recursive: true });
|
|
888
|
+
await fs11__default.default.copyFile(
|
|
889
|
+
path13__default.default.join(sectionSrc, section.bundle),
|
|
890
|
+
path13__default.default.join(sectionOut, path13__default.default.basename(section.bundle))
|
|
891
|
+
);
|
|
892
|
+
break;
|
|
893
|
+
}
|
|
894
|
+
default:
|
|
895
|
+
throw new Error(
|
|
896
|
+
`Unknown section type. Valid types: editable, opaque-react, html, iframe, webcomponent`
|
|
897
|
+
);
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
}
|
|
906
901
|
async function generateManifest(themeName, themePath, outputDir) {
|
|
907
902
|
let version2 = "1.0.0";
|
|
908
903
|
let themeId = themeName;
|
|
909
904
|
try {
|
|
910
|
-
const pkgContent = await
|
|
911
|
-
|
|
905
|
+
const pkgContent = await fs11__default.default.readFile(
|
|
906
|
+
path13__default.default.join(themePath, "package.json"),
|
|
912
907
|
"utf-8"
|
|
913
908
|
);
|
|
914
909
|
const pkg = JSON.parse(pkgContent);
|
|
@@ -926,7 +921,7 @@ async function generateManifest(themeName, themePath, outputDir) {
|
|
|
926
921
|
const dataRequirements = await extractDataRequirements(themePath);
|
|
927
922
|
let hasThemeConfig = false;
|
|
928
923
|
try {
|
|
929
|
-
await
|
|
924
|
+
await fs11__default.default.access(path13__default.default.join(themePath, "theme.config.ts"));
|
|
930
925
|
hasThemeConfig = true;
|
|
931
926
|
} catch {
|
|
932
927
|
}
|
|
@@ -967,24 +962,34 @@ async function generateManifest(themeName, themePath, outputDir) {
|
|
|
967
962
|
// Section data requirements for server-side prefetching (keyed by section type)
|
|
968
963
|
dataRequirements
|
|
969
964
|
};
|
|
970
|
-
await
|
|
971
|
-
|
|
965
|
+
await fs11__default.default.writeFile(
|
|
966
|
+
path13__default.default.join(outputDir, "manifest.json"),
|
|
972
967
|
JSON.stringify(manifest, null, 2)
|
|
973
968
|
);
|
|
974
969
|
}
|
|
975
970
|
async function compileStandaloneTheme(themePath, themeName) {
|
|
976
|
-
const outputDir =
|
|
977
|
-
const
|
|
978
|
-
|
|
971
|
+
const outputDir = path13__default.default.join(themePath, "dist");
|
|
972
|
+
const isNextjs = isNextjsProject(themePath);
|
|
973
|
+
if (isNextjs) {
|
|
974
|
+
logger.info("Detected Next.js project \u2014 using next/* shims");
|
|
975
|
+
}
|
|
976
|
+
const bundleEntry = path13__default.default.join(themePath, "bundle-entry.ts");
|
|
977
|
+
const indexEntry = path13__default.default.join(themePath, "index.ts");
|
|
979
978
|
let entryPoint = indexEntry;
|
|
980
979
|
try {
|
|
981
|
-
await
|
|
980
|
+
await fs11__default.default.access(bundleEntry);
|
|
982
981
|
entryPoint = bundleEntry;
|
|
983
982
|
} catch {
|
|
984
983
|
}
|
|
985
|
-
const shimPath =
|
|
986
|
-
await
|
|
987
|
-
await
|
|
984
|
+
const shimPath = path13__default.default.join(outputDir, ".process-shim.js");
|
|
985
|
+
await fs11__default.default.mkdir(outputDir, { recursive: true });
|
|
986
|
+
await fs11__default.default.writeFile(shimPath, PROCESS_SHIM);
|
|
987
|
+
const plugins = [
|
|
988
|
+
reactGlobalPlugin,
|
|
989
|
+
reactQueryGlobalPlugin,
|
|
990
|
+
createCoreGlobalPlugin(themePath)
|
|
991
|
+
];
|
|
992
|
+
if (isNextjs) plugins.unshift(nextShimPlugin);
|
|
988
993
|
const buildOptions = {
|
|
989
994
|
entryPoints: [entryPoint],
|
|
990
995
|
bundle: true,
|
|
@@ -996,12 +1001,7 @@ async function compileStandaloneTheme(themePath, themeName) {
|
|
|
996
1001
|
banner: {
|
|
997
1002
|
js: '"use client";'
|
|
998
1003
|
},
|
|
999
|
-
plugins
|
|
1000
|
-
reactGlobalPlugin,
|
|
1001
|
-
reactQueryGlobalPlugin,
|
|
1002
|
-
createCoreGlobalPlugin(themePath),
|
|
1003
|
-
createThemeDepsStubPlugin(themePath)
|
|
1004
|
-
],
|
|
1004
|
+
plugins,
|
|
1005
1005
|
external: [],
|
|
1006
1006
|
alias: {
|
|
1007
1007
|
events: "events/",
|
|
@@ -1035,15 +1035,16 @@ async function compileStandaloneTheme(themePath, themeName) {
|
|
|
1035
1035
|
try {
|
|
1036
1036
|
const result = await esbuild__namespace.build(buildOptions);
|
|
1037
1037
|
try {
|
|
1038
|
-
await
|
|
1038
|
+
await fs11__default.default.unlink(shimPath);
|
|
1039
1039
|
} catch {
|
|
1040
1040
|
}
|
|
1041
|
+
await compileSections(themePath, outputDir);
|
|
1041
1042
|
await contentHashEntry(outputDir);
|
|
1042
|
-
const themeAssetsDir =
|
|
1043
|
-
const distThemeAssets =
|
|
1043
|
+
const themeAssetsDir = path13__default.default.join(themePath, "assets");
|
|
1044
|
+
const distThemeAssets = path13__default.default.join(outputDir, "theme-assets");
|
|
1044
1045
|
try {
|
|
1045
|
-
await
|
|
1046
|
-
await
|
|
1046
|
+
await fs11__default.default.access(themeAssetsDir);
|
|
1047
|
+
await fs11__default.default.cp(themeAssetsDir, distThemeAssets, { recursive: true });
|
|
1047
1048
|
logger.info("Copied static assets to dist/theme-assets/");
|
|
1048
1049
|
} catch {
|
|
1049
1050
|
}
|
|
@@ -1063,7 +1064,7 @@ async function compileStandaloneTheme(themePath, themeName) {
|
|
|
1063
1064
|
return true;
|
|
1064
1065
|
} catch (error) {
|
|
1065
1066
|
try {
|
|
1066
|
-
await
|
|
1067
|
+
await fs11__default.default.unlink(shimPath);
|
|
1067
1068
|
} catch {
|
|
1068
1069
|
}
|
|
1069
1070
|
logger.error(`esbuild compilation failed: ${error}`);
|
|
@@ -1071,18 +1072,25 @@ async function compileStandaloneTheme(themePath, themeName) {
|
|
|
1071
1072
|
}
|
|
1072
1073
|
}
|
|
1073
1074
|
async function compileStandaloneThemeDev(themePath, themeName) {
|
|
1074
|
-
const outputDir =
|
|
1075
|
-
const
|
|
1076
|
-
const
|
|
1075
|
+
const outputDir = path13__default.default.join(themePath, "dist");
|
|
1076
|
+
const isNextjs = isNextjsProject(themePath);
|
|
1077
|
+
const bundleEntry = path13__default.default.join(themePath, "bundle-entry.ts");
|
|
1078
|
+
const indexEntry = path13__default.default.join(themePath, "index.ts");
|
|
1077
1079
|
let entryPoint = indexEntry;
|
|
1078
1080
|
try {
|
|
1079
|
-
await
|
|
1081
|
+
await fs11__default.default.access(bundleEntry);
|
|
1080
1082
|
entryPoint = bundleEntry;
|
|
1081
1083
|
} catch {
|
|
1082
1084
|
}
|
|
1083
|
-
const shimPath =
|
|
1084
|
-
await
|
|
1085
|
-
await
|
|
1085
|
+
const shimPath = path13__default.default.join(outputDir, ".process-shim.js");
|
|
1086
|
+
await fs11__default.default.mkdir(outputDir, { recursive: true });
|
|
1087
|
+
await fs11__default.default.writeFile(shimPath, PROCESS_SHIM);
|
|
1088
|
+
const devPlugins = [
|
|
1089
|
+
reactGlobalPlugin,
|
|
1090
|
+
reactQueryGlobalPlugin,
|
|
1091
|
+
createCoreGlobalPlugin(themePath)
|
|
1092
|
+
];
|
|
1093
|
+
if (isNextjs) devPlugins.unshift(nextShimPlugin);
|
|
1086
1094
|
const buildOptions = {
|
|
1087
1095
|
entryPoints: [entryPoint],
|
|
1088
1096
|
bundle: true,
|
|
@@ -1093,12 +1101,7 @@ async function compileStandaloneThemeDev(themePath, themeName) {
|
|
|
1093
1101
|
banner: {
|
|
1094
1102
|
js: '"use client";'
|
|
1095
1103
|
},
|
|
1096
|
-
plugins:
|
|
1097
|
-
reactGlobalPlugin,
|
|
1098
|
-
reactQueryGlobalPlugin,
|
|
1099
|
-
createCoreGlobalPlugin(themePath),
|
|
1100
|
-
createThemeDepsStubPlugin(themePath)
|
|
1101
|
-
],
|
|
1104
|
+
plugins: devPlugins,
|
|
1102
1105
|
external: [],
|
|
1103
1106
|
alias: {
|
|
1104
1107
|
events: "events/",
|
|
@@ -1136,18 +1139,18 @@ async function compileStandaloneThemeDev(themePath, themeName) {
|
|
|
1136
1139
|
return { context: context2, outputDir };
|
|
1137
1140
|
}
|
|
1138
1141
|
async function compilePreviewRuntime(themePath) {
|
|
1139
|
-
const outputDir =
|
|
1140
|
-
await
|
|
1141
|
-
const outputPath =
|
|
1142
|
+
const outputDir = path13__default.default.join(themePath, "dist");
|
|
1143
|
+
await fs11__default.default.mkdir(outputDir, { recursive: true });
|
|
1144
|
+
const outputPath = path13__default.default.join(outputDir, "preview-runtime.js");
|
|
1142
1145
|
const locations = [
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
+
path13__default.default.join(__dirname, "..", "preview", "preview-app.tsx"),
|
|
1147
|
+
path13__default.default.join(__dirname, "preview", "preview-app.tsx"),
|
|
1148
|
+
path13__default.default.join(__dirname, "..", "..", "src", "preview", "preview-app.tsx")
|
|
1146
1149
|
];
|
|
1147
1150
|
let previewEntryPath = null;
|
|
1148
1151
|
for (const loc of locations) {
|
|
1149
1152
|
try {
|
|
1150
|
-
await
|
|
1153
|
+
await fs11__default.default.access(loc);
|
|
1151
1154
|
previewEntryPath = loc;
|
|
1152
1155
|
break;
|
|
1153
1156
|
} catch {
|
|
@@ -1230,10 +1233,10 @@ ${locations.join("\n")}`
|
|
|
1230
1233
|
if (!lucideScanned) {
|
|
1231
1234
|
lucideScanned = true;
|
|
1232
1235
|
const coreSrcCandidates = [
|
|
1233
|
-
|
|
1234
|
-
|
|
1236
|
+
path13__default.default.join(themePath, "node_modules", "@onexapis", "core", "src"),
|
|
1237
|
+
path13__default.default.join(themePath, "..", "..", "packages", "core", "src"),
|
|
1235
1238
|
// monorepo sibling
|
|
1236
|
-
|
|
1239
|
+
path13__default.default.join(
|
|
1237
1240
|
__dirname,
|
|
1238
1241
|
"..",
|
|
1239
1242
|
"..",
|
|
@@ -1248,7 +1251,7 @@ ${locations.join("\n")}`
|
|
|
1248
1251
|
let coreSourceDir = null;
|
|
1249
1252
|
for (const candidate of coreSrcCandidates) {
|
|
1250
1253
|
try {
|
|
1251
|
-
await
|
|
1254
|
+
await fs11__default.default.access(candidate);
|
|
1252
1255
|
coreSourceDir = candidate;
|
|
1253
1256
|
break;
|
|
1254
1257
|
} catch {
|
|
@@ -1267,21 +1270,21 @@ ${locations.join("\n")}`
|
|
|
1267
1270
|
}
|
|
1268
1271
|
} else {
|
|
1269
1272
|
const coreDistCandidates = [
|
|
1270
|
-
|
|
1273
|
+
path13__default.default.join(themePath, "node_modules", "@onexapis", "core", "dist")
|
|
1271
1274
|
];
|
|
1272
1275
|
const resolvedDist = await resolveNodeModulesFile(
|
|
1273
1276
|
__dirname,
|
|
1274
|
-
|
|
1277
|
+
path13__default.default.join("@onexapis", "core", "dist")
|
|
1275
1278
|
);
|
|
1276
1279
|
if (resolvedDist) coreDistCandidates.push(resolvedDist);
|
|
1277
1280
|
for (const candidate of coreDistCandidates) {
|
|
1278
1281
|
try {
|
|
1279
|
-
await
|
|
1282
|
+
await fs11__default.default.access(candidate);
|
|
1280
1283
|
const mjsFiles = await glob.glob("*.mjs", { cwd: candidate });
|
|
1281
1284
|
const importRegex = /import\s*\{([^}]+)\}\s*from\s*["']lucide-react["']/g;
|
|
1282
1285
|
for (const file of mjsFiles) {
|
|
1283
|
-
const content = await
|
|
1284
|
-
|
|
1286
|
+
const content = await fs11__default.default.readFile(
|
|
1287
|
+
path13__default.default.join(candidate, file),
|
|
1285
1288
|
"utf-8"
|
|
1286
1289
|
);
|
|
1287
1290
|
for (const match of content.matchAll(importRegex)) {
|
|
@@ -1336,7 +1339,7 @@ export default new Proxy({}, { get: (_, name) => name === '__esModule' ? true :
|
|
|
1336
1339
|
const req = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.js', document.baseURI).href)) || __filename);
|
|
1337
1340
|
const cjsPath = req.resolve("framer-motion");
|
|
1338
1341
|
const pkgDir = cjsPath.replace(/[/\\]dist[/\\].*$/, "");
|
|
1339
|
-
const esmEntry =
|
|
1342
|
+
const esmEntry = path13__default.default.join(pkgDir, "dist", "es", "index.mjs");
|
|
1340
1343
|
const { existsSync } = await import('fs');
|
|
1341
1344
|
if (existsSync(esmEntry)) {
|
|
1342
1345
|
return { path: esmEntry, namespace: "file" };
|
|
@@ -1435,8 +1438,8 @@ export function headers() { return new Headers(); }
|
|
|
1435
1438
|
});
|
|
1436
1439
|
}
|
|
1437
1440
|
};
|
|
1438
|
-
const shimPath =
|
|
1439
|
-
await
|
|
1441
|
+
const shimPath = path13__default.default.join(outputDir, ".process-shim-preview.js");
|
|
1442
|
+
await fs11__default.default.writeFile(shimPath, PROCESS_SHIM);
|
|
1440
1443
|
await esbuild__namespace.build({
|
|
1441
1444
|
entryPoints: [previewEntryPath],
|
|
1442
1445
|
bundle: true,
|
|
@@ -1471,17 +1474,19 @@ export function headers() { return new Headers(); }
|
|
|
1471
1474
|
}
|
|
1472
1475
|
});
|
|
1473
1476
|
try {
|
|
1474
|
-
await
|
|
1477
|
+
await fs11__default.default.unlink(shimPath);
|
|
1475
1478
|
} catch {
|
|
1476
1479
|
}
|
|
1477
1480
|
return outputPath;
|
|
1478
1481
|
}
|
|
1479
|
-
var PROCESS_SHIM, reactGlobalPlugin, reactQueryGlobalPlugin;
|
|
1482
|
+
var PROCESS_SHIM, reactGlobalPlugin, reactQueryGlobalPlugin, nextShimPlugin;
|
|
1480
1483
|
var init_compile_theme = __esm({
|
|
1481
1484
|
"src/utils/compile-theme.ts"() {
|
|
1482
1485
|
init_logger();
|
|
1483
1486
|
init_extract_schemas();
|
|
1484
1487
|
init_scan_theme_assets();
|
|
1488
|
+
init_detect_nextjs();
|
|
1489
|
+
init_nextjs_page_scanner();
|
|
1485
1490
|
PROCESS_SHIM = `
|
|
1486
1491
|
if (typeof process === "undefined") {
|
|
1487
1492
|
globalThis.process = {
|
|
@@ -1627,6 +1632,145 @@ export const {
|
|
|
1627
1632
|
}));
|
|
1628
1633
|
}
|
|
1629
1634
|
};
|
|
1635
|
+
nextShimPlugin = {
|
|
1636
|
+
name: "next-shim",
|
|
1637
|
+
setup(build2) {
|
|
1638
|
+
for (const serverModule of ["next/headers", "next/server", "next/cache"]) {
|
|
1639
|
+
build2.onResolve({ filter: new RegExp(`^${serverModule.replace("/", "\\/")}`) }, (args) => ({
|
|
1640
|
+
path: args.path,
|
|
1641
|
+
namespace: "next-server-error"
|
|
1642
|
+
}));
|
|
1643
|
+
}
|
|
1644
|
+
build2.onLoad({ filter: /.*/, namespace: "next-server-error" }, (args) => ({
|
|
1645
|
+
errors: [
|
|
1646
|
+
{
|
|
1647
|
+
text: `"${args.path}" is server-only and cannot be used in a OneX theme bundle. Use client-side equivalents or remove the import.`
|
|
1648
|
+
}
|
|
1649
|
+
]
|
|
1650
|
+
}));
|
|
1651
|
+
build2.onResolve({ filter: /^next\/navigation$/ }, () => ({
|
|
1652
|
+
path: "next-navigation-shim",
|
|
1653
|
+
namespace: "next-shim"
|
|
1654
|
+
}));
|
|
1655
|
+
build2.onLoad({ filter: /^next-navigation-shim$/, namespace: "next-shim" }, () => ({
|
|
1656
|
+
contents: `
|
|
1657
|
+
export function usePathname() {
|
|
1658
|
+
if (typeof window === 'undefined') return '/';
|
|
1659
|
+
return window.location.pathname;
|
|
1660
|
+
}
|
|
1661
|
+
export function useSearchParams() {
|
|
1662
|
+
if (typeof window === 'undefined') return new URLSearchParams();
|
|
1663
|
+
return new URLSearchParams(window.location.search);
|
|
1664
|
+
}
|
|
1665
|
+
export function useParams() {
|
|
1666
|
+
if (typeof window === 'undefined') return {};
|
|
1667
|
+
return (globalThis.__ONEX_ROUTE_PARAMS__) ?? {};
|
|
1668
|
+
}
|
|
1669
|
+
export function useRouter() {
|
|
1670
|
+
return {
|
|
1671
|
+
push(url) { if (typeof window !== 'undefined') window.location.href = url; },
|
|
1672
|
+
replace(url) { if (typeof window !== 'undefined') window.location.replace(url); },
|
|
1673
|
+
back() { if (typeof window !== 'undefined') window.history.back(); },
|
|
1674
|
+
forward() { if (typeof window !== 'undefined') window.history.forward(); },
|
|
1675
|
+
refresh() { if (typeof window !== 'undefined') window.location.reload(); },
|
|
1676
|
+
prefetch() {},
|
|
1677
|
+
};
|
|
1678
|
+
}
|
|
1679
|
+
export function redirect(url) {
|
|
1680
|
+
if (typeof window !== 'undefined') window.location.href = url;
|
|
1681
|
+
throw new Error('redirect');
|
|
1682
|
+
}
|
|
1683
|
+
export function notFound() { throw new Error('not-found'); }
|
|
1684
|
+
`.trim(),
|
|
1685
|
+
loader: "js"
|
|
1686
|
+
}));
|
|
1687
|
+
build2.onResolve({ filter: /^next\/font\// }, () => ({
|
|
1688
|
+
path: "next-font-shim",
|
|
1689
|
+
namespace: "next-shim"
|
|
1690
|
+
}));
|
|
1691
|
+
build2.onLoad({ filter: /^next-font-shim$/, namespace: "next-shim" }, () => ({
|
|
1692
|
+
contents: `
|
|
1693
|
+
function makeFont(family) {
|
|
1694
|
+
return function(_opts) {
|
|
1695
|
+
return {
|
|
1696
|
+
className: '',
|
|
1697
|
+
style: { fontFamily: family + ', system-ui, sans-serif' },
|
|
1698
|
+
variable: '--font-' + family.toLowerCase().replace(/\\s+/g, '-'),
|
|
1699
|
+
};
|
|
1700
|
+
};
|
|
1701
|
+
}
|
|
1702
|
+
export const Inter = makeFont('Inter');
|
|
1703
|
+
export const Roboto = makeFont('Roboto');
|
|
1704
|
+
export const Open_Sans = makeFont('Open Sans');
|
|
1705
|
+
export const Lato = makeFont('Lato');
|
|
1706
|
+
export const Montserrat = makeFont('Montserrat');
|
|
1707
|
+
export const Poppins = makeFont('Poppins');
|
|
1708
|
+
export const Raleway = makeFont('Raleway');
|
|
1709
|
+
export const Nunito = makeFont('Nunito');
|
|
1710
|
+
export const Geist = makeFont('Geist');
|
|
1711
|
+
export const Geist_Mono = makeFont('Geist Mono');
|
|
1712
|
+
export const DM_Sans = makeFont('DM Sans');
|
|
1713
|
+
export const Plus_Jakarta_Sans = makeFont('Plus Jakarta Sans');
|
|
1714
|
+
export function localFont(_opts) {
|
|
1715
|
+
return { className: '', style: { fontFamily: 'system-ui, sans-serif' }, variable: '--font-local' };
|
|
1716
|
+
}
|
|
1717
|
+
`.trim(),
|
|
1718
|
+
loader: "js"
|
|
1719
|
+
}));
|
|
1720
|
+
build2.onResolve({ filter: /^next\/dynamic$/ }, () => ({
|
|
1721
|
+
path: "next-dynamic-shim",
|
|
1722
|
+
namespace: "next-shim"
|
|
1723
|
+
}));
|
|
1724
|
+
build2.onLoad({ filter: /^next-dynamic-shim$/, namespace: "next-shim" }, () => ({
|
|
1725
|
+
contents: `
|
|
1726
|
+
import { lazy, Suspense, createElement } from 'react';
|
|
1727
|
+
export default function dynamic(loader, opts) {
|
|
1728
|
+
const Lazy = lazy(loader);
|
|
1729
|
+
return function DynamicComponent(props) {
|
|
1730
|
+
return createElement(Suspense, { fallback: opts?.loading ? createElement(opts.loading) : null },
|
|
1731
|
+
createElement(Lazy, props));
|
|
1732
|
+
};
|
|
1733
|
+
}
|
|
1734
|
+
`.trim(),
|
|
1735
|
+
loader: "js"
|
|
1736
|
+
}));
|
|
1737
|
+
build2.onResolve({ filter: /^next\/image$/ }, () => ({
|
|
1738
|
+
path: "next-image-shim",
|
|
1739
|
+
namespace: "next-shim"
|
|
1740
|
+
}));
|
|
1741
|
+
build2.onLoad({ filter: /^next-image-shim$/, namespace: "next-shim" }, () => ({
|
|
1742
|
+
contents: `
|
|
1743
|
+
import { createElement } from 'react';
|
|
1744
|
+
export default function Image({ src, alt, width, height, style, className, ...rest }) {
|
|
1745
|
+
return createElement('img', { src, alt, width, height, style, className, ...rest });
|
|
1746
|
+
}
|
|
1747
|
+
`.trim(),
|
|
1748
|
+
loader: "js"
|
|
1749
|
+
}));
|
|
1750
|
+
build2.onResolve({ filter: /^next\/link$/ }, () => ({
|
|
1751
|
+
path: "next-link-shim",
|
|
1752
|
+
namespace: "next-shim"
|
|
1753
|
+
}));
|
|
1754
|
+
build2.onLoad({ filter: /^next-link-shim$/, namespace: "next-shim" }, () => ({
|
|
1755
|
+
contents: `
|
|
1756
|
+
import { createElement } from 'react';
|
|
1757
|
+
export default function Link({ href, children, className, style, ...rest }) {
|
|
1758
|
+
return createElement('a', { href, className, style, ...rest }, children);
|
|
1759
|
+
}
|
|
1760
|
+
`.trim(),
|
|
1761
|
+
loader: "js"
|
|
1762
|
+
}));
|
|
1763
|
+
build2.onResolve({ filter: /^next\// }, () => ({
|
|
1764
|
+
path: "next-noop-shim",
|
|
1765
|
+
namespace: "next-shim"
|
|
1766
|
+
}));
|
|
1767
|
+
build2.onLoad({ filter: /^next-noop-shim$/, namespace: "next-shim" }, () => ({
|
|
1768
|
+
contents: `export default {};
|
|
1769
|
+
`,
|
|
1770
|
+
loader: "js"
|
|
1771
|
+
}));
|
|
1772
|
+
}
|
|
1773
|
+
};
|
|
1630
1774
|
}
|
|
1631
1775
|
});
|
|
1632
1776
|
|
|
@@ -1637,7 +1781,7 @@ __export(dev_server_exports, {
|
|
|
1637
1781
|
});
|
|
1638
1782
|
function createDevServer(options) {
|
|
1639
1783
|
const clients = /* @__PURE__ */ new Set();
|
|
1640
|
-
const themeDataPath =
|
|
1784
|
+
const themeDataPath = path13__default.default.join(options.distDir, "theme-data.json");
|
|
1641
1785
|
const server = http__default.default.createServer((req, res) => {
|
|
1642
1786
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
1643
1787
|
res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
|
|
@@ -1663,8 +1807,8 @@ function createDevServer(options) {
|
|
|
1663
1807
|
if (pathname.startsWith("/_assets/")) {
|
|
1664
1808
|
const parts = pathname.replace(/^\/_assets\//, "").split("/");
|
|
1665
1809
|
const assetSubpath = parts.slice(1).join("/");
|
|
1666
|
-
const assetPath =
|
|
1667
|
-
if (!assetPath.startsWith(
|
|
1810
|
+
const assetPath = path13__default.default.join(options.themePath, "assets", assetSubpath);
|
|
1811
|
+
if (!assetPath.startsWith(path13__default.default.join(options.themePath, "assets"))) {
|
|
1668
1812
|
res.writeHead(403);
|
|
1669
1813
|
res.end("Forbidden");
|
|
1670
1814
|
return;
|
|
@@ -1675,8 +1819,8 @@ function createDevServer(options) {
|
|
|
1675
1819
|
if (pathname.startsWith("/themes/")) {
|
|
1676
1820
|
const match = pathname.match(/^\/themes\/[^/]+\/assets\/(.+)/);
|
|
1677
1821
|
if (match) {
|
|
1678
|
-
const assetPath =
|
|
1679
|
-
if (!assetPath.startsWith(
|
|
1822
|
+
const assetPath = path13__default.default.join(options.themePath, "assets", match[1]);
|
|
1823
|
+
if (!assetPath.startsWith(path13__default.default.join(options.themePath, "assets"))) {
|
|
1680
1824
|
res.writeHead(403);
|
|
1681
1825
|
res.end("Forbidden");
|
|
1682
1826
|
return;
|
|
@@ -1688,26 +1832,26 @@ function createDevServer(options) {
|
|
|
1688
1832
|
if (pathname.startsWith("/assets/")) {
|
|
1689
1833
|
const subpath = pathname.replace(/^\/assets\//, "");
|
|
1690
1834
|
const segments = subpath.split("/");
|
|
1691
|
-
const assetsBase =
|
|
1835
|
+
const assetsBase = path13__default.default.join(options.themePath, "assets");
|
|
1692
1836
|
let assetPath;
|
|
1693
1837
|
if (segments[0] === options.themeName || segments[0] === options.themeName.replace(/^my-/, "")) {
|
|
1694
|
-
assetPath =
|
|
1838
|
+
assetPath = path13__default.default.join(assetsBase, segments.slice(1).join("/"));
|
|
1695
1839
|
} else {
|
|
1696
|
-
assetPath =
|
|
1840
|
+
assetPath = path13__default.default.join(assetsBase, subpath);
|
|
1697
1841
|
}
|
|
1698
1842
|
if (assetPath.startsWith(assetsBase) && fs3__default.default.existsSync(assetPath)) {
|
|
1699
1843
|
serveFile(res, assetPath);
|
|
1700
1844
|
return;
|
|
1701
1845
|
}
|
|
1702
1846
|
if (segments.length > 1) {
|
|
1703
|
-
const fallbackPath =
|
|
1847
|
+
const fallbackPath = path13__default.default.join(assetsBase, segments.slice(1).join("/"));
|
|
1704
1848
|
if (fallbackPath.startsWith(assetsBase) && fs3__default.default.existsSync(fallbackPath)) {
|
|
1705
1849
|
serveFile(res, fallbackPath);
|
|
1706
1850
|
return;
|
|
1707
1851
|
}
|
|
1708
1852
|
}
|
|
1709
1853
|
}
|
|
1710
|
-
const filePath =
|
|
1854
|
+
const filePath = path13__default.default.join(options.distDir, pathname);
|
|
1711
1855
|
if (!filePath.startsWith(options.distDir)) {
|
|
1712
1856
|
res.writeHead(403);
|
|
1713
1857
|
res.end("Forbidden");
|
|
@@ -1750,7 +1894,7 @@ function serveFile(res, filePath) {
|
|
|
1750
1894
|
res.end("Not Found");
|
|
1751
1895
|
return;
|
|
1752
1896
|
}
|
|
1753
|
-
const ext =
|
|
1897
|
+
const ext = path13__default.default.extname(filePath);
|
|
1754
1898
|
const contentType = MIME_TYPES[ext] || "application/octet-stream";
|
|
1755
1899
|
const content = fs3__default.default.readFileSync(filePath);
|
|
1756
1900
|
res.writeHead(200, { "Content-Type": contentType });
|
|
@@ -1867,26 +2011,26 @@ var init_dev_server = __esm({
|
|
|
1867
2011
|
// src/utils/file-helpers.ts
|
|
1868
2012
|
init_logger();
|
|
1869
2013
|
async function renderTemplate(templatePath, data) {
|
|
1870
|
-
const template = await
|
|
2014
|
+
const template = await fs8__default.default.readFile(templatePath, "utf-8");
|
|
1871
2015
|
return ejs__default.default.render(template, data);
|
|
1872
2016
|
}
|
|
1873
2017
|
async function writeFile(filePath, content) {
|
|
1874
|
-
await
|
|
1875
|
-
await
|
|
2018
|
+
await fs8__default.default.ensureDir(path13__default.default.dirname(filePath));
|
|
2019
|
+
await fs8__default.default.writeFile(filePath, content, "utf-8");
|
|
1876
2020
|
}
|
|
1877
2021
|
function getTemplatesDir() {
|
|
1878
2022
|
const locations = [
|
|
1879
|
-
|
|
2023
|
+
path13__default.default.join(__dirname, "../../templates"),
|
|
1880
2024
|
// Development
|
|
1881
|
-
|
|
2025
|
+
path13__default.default.join(__dirname, "../templates"),
|
|
1882
2026
|
// Production (dist/)
|
|
1883
|
-
|
|
2027
|
+
path13__default.default.join(process.cwd(), "templates"),
|
|
1884
2028
|
// Fallback
|
|
1885
|
-
|
|
2029
|
+
path13__default.default.join(process.cwd(), "packages/cli/templates")
|
|
1886
2030
|
// Monorepo
|
|
1887
2031
|
];
|
|
1888
2032
|
for (const location of locations) {
|
|
1889
|
-
if (
|
|
2033
|
+
if (fs8__default.default.existsSync(location)) {
|
|
1890
2034
|
return location;
|
|
1891
2035
|
}
|
|
1892
2036
|
}
|
|
@@ -1894,18 +2038,18 @@ function getTemplatesDir() {
|
|
|
1894
2038
|
}
|
|
1895
2039
|
async function copyTemplate(templateName, targetDir, data) {
|
|
1896
2040
|
const templatesDir = getTemplatesDir();
|
|
1897
|
-
const templateDir =
|
|
1898
|
-
if (!
|
|
2041
|
+
const templateDir = path13__default.default.join(templatesDir, templateName);
|
|
2042
|
+
if (!fs8__default.default.existsSync(templateDir)) {
|
|
1899
2043
|
throw new Error(
|
|
1900
|
-
`Template "${templateName}" not found at ${templateDir}. Available templates: ${
|
|
2044
|
+
`Template "${templateName}" not found at ${templateDir}. Available templates: ${fs8__default.default.readdirSync(templatesDir).join(", ")}`
|
|
1901
2045
|
);
|
|
1902
2046
|
}
|
|
1903
|
-
await
|
|
1904
|
-
const files = await
|
|
2047
|
+
await fs8__default.default.ensureDir(targetDir);
|
|
2048
|
+
const files = await fs8__default.default.readdir(templateDir);
|
|
1905
2049
|
for (const file of files) {
|
|
1906
|
-
const templatePath =
|
|
1907
|
-
const targetPath =
|
|
1908
|
-
const stat = await
|
|
2050
|
+
const templatePath = path13__default.default.join(templateDir, file);
|
|
2051
|
+
const targetPath = path13__default.default.join(targetDir, file);
|
|
2052
|
+
const stat = await fs8__default.default.stat(templatePath);
|
|
1909
2053
|
if (stat.isDirectory()) {
|
|
1910
2054
|
await copyTemplateDir(templatePath, targetPath, data);
|
|
1911
2055
|
} else if (file.endsWith(".ejs")) {
|
|
@@ -1913,17 +2057,17 @@ async function copyTemplate(templateName, targetDir, data) {
|
|
|
1913
2057
|
const outputPath = targetPath.replace(/\.ejs$/, "");
|
|
1914
2058
|
await writeFile(outputPath, content);
|
|
1915
2059
|
} else {
|
|
1916
|
-
await
|
|
2060
|
+
await fs8__default.default.copy(templatePath, targetPath);
|
|
1917
2061
|
}
|
|
1918
2062
|
}
|
|
1919
2063
|
}
|
|
1920
2064
|
async function copyTemplateDir(templateDir, targetDir, data) {
|
|
1921
|
-
await
|
|
1922
|
-
const files = await
|
|
2065
|
+
await fs8__default.default.ensureDir(targetDir);
|
|
2066
|
+
const files = await fs8__default.default.readdir(templateDir);
|
|
1923
2067
|
for (const file of files) {
|
|
1924
|
-
const templatePath =
|
|
1925
|
-
const targetPath =
|
|
1926
|
-
const stat = await
|
|
2068
|
+
const templatePath = path13__default.default.join(templateDir, file);
|
|
2069
|
+
const targetPath = path13__default.default.join(targetDir, file);
|
|
2070
|
+
const stat = await fs8__default.default.stat(templatePath);
|
|
1927
2071
|
if (stat.isDirectory()) {
|
|
1928
2072
|
await copyTemplateDir(templatePath, targetPath, data);
|
|
1929
2073
|
} else if (file.endsWith(".ejs")) {
|
|
@@ -1931,38 +2075,38 @@ async function copyTemplateDir(templateDir, targetDir, data) {
|
|
|
1931
2075
|
const outputPath = targetPath.replace(/\.ejs$/, "");
|
|
1932
2076
|
await writeFile(outputPath, content);
|
|
1933
2077
|
} else {
|
|
1934
|
-
await
|
|
2078
|
+
await fs8__default.default.copy(templatePath, targetPath);
|
|
1935
2079
|
}
|
|
1936
2080
|
}
|
|
1937
2081
|
}
|
|
1938
2082
|
function getProjectRoot() {
|
|
1939
2083
|
let currentDir = process.cwd();
|
|
1940
|
-
while (currentDir !==
|
|
1941
|
-
const packageJsonPath =
|
|
1942
|
-
if (
|
|
1943
|
-
const packageJson =
|
|
1944
|
-
if (packageJson.workspaces ||
|
|
2084
|
+
while (currentDir !== path13__default.default.parse(currentDir).root) {
|
|
2085
|
+
const packageJsonPath = path13__default.default.join(currentDir, "package.json");
|
|
2086
|
+
if (fs8__default.default.existsSync(packageJsonPath)) {
|
|
2087
|
+
const packageJson = fs8__default.default.readJsonSync(packageJsonPath);
|
|
2088
|
+
if (packageJson.workspaces || fs8__default.default.existsSync(path13__default.default.join(currentDir, "src/themes")) || fs8__default.default.existsSync(path13__default.default.join(currentDir, "themes"))) {
|
|
1945
2089
|
return currentDir;
|
|
1946
2090
|
}
|
|
1947
2091
|
}
|
|
1948
|
-
currentDir =
|
|
2092
|
+
currentDir = path13__default.default.dirname(currentDir);
|
|
1949
2093
|
}
|
|
1950
2094
|
return process.cwd();
|
|
1951
2095
|
}
|
|
1952
2096
|
function getThemesDir() {
|
|
1953
2097
|
const root = getProjectRoot();
|
|
1954
|
-
if (
|
|
1955
|
-
return
|
|
1956
|
-
if (
|
|
1957
|
-
return
|
|
1958
|
-
return
|
|
2098
|
+
if (fs8__default.default.existsSync(path13__default.default.join(root, "themes")))
|
|
2099
|
+
return path13__default.default.join(root, "themes");
|
|
2100
|
+
if (fs8__default.default.existsSync(path13__default.default.join(root, "src/themes")))
|
|
2101
|
+
return path13__default.default.join(root, "src/themes");
|
|
2102
|
+
return path13__default.default.dirname(root);
|
|
1959
2103
|
}
|
|
1960
2104
|
function getFeaturesDir() {
|
|
1961
|
-
return
|
|
2105
|
+
return path13__default.default.join(getProjectRoot(), "src/features");
|
|
1962
2106
|
}
|
|
1963
2107
|
function isOneXProject() {
|
|
1964
2108
|
const root = getProjectRoot();
|
|
1965
|
-
return
|
|
2109
|
+
return fs8__default.default.existsSync(path13__default.default.join(root, "themes")) || fs8__default.default.existsSync(path13__default.default.join(root, "src/themes")) || fs8__default.default.existsSync(path13__default.default.join(root, "theme.config.ts")) || fs8__default.default.existsSync(path13__default.default.join(root, "bundle-entry.ts"));
|
|
1966
2110
|
}
|
|
1967
2111
|
function ensureOneXProject() {
|
|
1968
2112
|
if (!isOneXProject()) {
|
|
@@ -1974,17 +2118,17 @@ function ensureOneXProject() {
|
|
|
1974
2118
|
}
|
|
1975
2119
|
function listThemes() {
|
|
1976
2120
|
const themesDir = getThemesDir();
|
|
1977
|
-
if (!
|
|
2121
|
+
if (!fs8__default.default.existsSync(themesDir)) {
|
|
1978
2122
|
return [];
|
|
1979
2123
|
}
|
|
1980
|
-
return
|
|
1981
|
-
const themePath =
|
|
1982
|
-
return
|
|
2124
|
+
return fs8__default.default.readdirSync(themesDir).filter((name) => {
|
|
2125
|
+
const themePath = path13__default.default.join(themesDir, name);
|
|
2126
|
+
return fs8__default.default.statSync(themePath).isDirectory() && (fs8__default.default.existsSync(path13__default.default.join(themePath, "theme.config.ts")) || fs8__default.default.existsSync(path13__default.default.join(themePath, "bundle-entry.ts")) || fs8__default.default.existsSync(path13__default.default.join(themePath, "manifest.ts")));
|
|
1983
2127
|
});
|
|
1984
2128
|
}
|
|
1985
2129
|
function themeExists(themeName) {
|
|
1986
|
-
const themePath =
|
|
1987
|
-
return
|
|
2130
|
+
const themePath = path13__default.default.join(getThemesDir(), themeName);
|
|
2131
|
+
return fs8__default.default.existsSync(themePath) && (fs8__default.default.existsSync(path13__default.default.join(themePath, "theme.config.ts")) || fs8__default.default.existsSync(path13__default.default.join(themePath, "bundle-entry.ts")) || fs8__default.default.existsSync(path13__default.default.join(themePath, "manifest.ts")));
|
|
1988
2132
|
}
|
|
1989
2133
|
function detectPackageManager() {
|
|
1990
2134
|
const userAgent = process.env.npm_config_user_agent || "";
|
|
@@ -1992,9 +2136,9 @@ function detectPackageManager() {
|
|
|
1992
2136
|
if (userAgent.includes("yarn")) return "yarn";
|
|
1993
2137
|
if (userAgent.includes("bun")) return "bun";
|
|
1994
2138
|
const cwd = process.cwd();
|
|
1995
|
-
if (
|
|
1996
|
-
if (
|
|
1997
|
-
if (
|
|
2139
|
+
if (fs8__default.default.existsSync(path13__default.default.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
2140
|
+
if (fs8__default.default.existsSync(path13__default.default.join(cwd, "yarn.lock"))) return "yarn";
|
|
2141
|
+
if (fs8__default.default.existsSync(path13__default.default.join(cwd, "bun.lockb"))) return "bun";
|
|
1998
2142
|
return "npm";
|
|
1999
2143
|
}
|
|
2000
2144
|
async function installDependencies(projectPath, packageManager = "npm") {
|
|
@@ -2043,23 +2187,23 @@ function getValidCategories() {
|
|
|
2043
2187
|
"contact"
|
|
2044
2188
|
];
|
|
2045
2189
|
}
|
|
2046
|
-
var AUTH_DIR =
|
|
2190
|
+
var AUTH_DIR = path13__default.default.join(os__default.default.homedir(), ".onexthm");
|
|
2047
2191
|
var ENV_URLS = {
|
|
2048
2192
|
dev: "https://platform-dev.onexeos.com",
|
|
2049
2193
|
staging: "https://platform-staging.onexeos.com",
|
|
2050
2194
|
prod: "https://platform-apis.onexeos.com"
|
|
2051
2195
|
};
|
|
2052
2196
|
function getAuthFile(env = "dev") {
|
|
2053
|
-
const newFile =
|
|
2197
|
+
const newFile = path13__default.default.join(AUTH_DIR, `auth-${env}.json`);
|
|
2054
2198
|
if (env === "dev") {
|
|
2055
|
-
const legacyFile =
|
|
2056
|
-
if (
|
|
2199
|
+
const legacyFile = path13__default.default.join(AUTH_DIR, "auth.json");
|
|
2200
|
+
if (fs8__default.default.existsSync(legacyFile) && !fs8__default.default.existsSync(newFile)) {
|
|
2057
2201
|
try {
|
|
2058
|
-
|
|
2202
|
+
fs8__default.default.moveSync(legacyFile, newFile);
|
|
2059
2203
|
} catch {
|
|
2060
2204
|
try {
|
|
2061
|
-
|
|
2062
|
-
|
|
2205
|
+
fs8__default.default.copySync(legacyFile, newFile);
|
|
2206
|
+
fs8__default.default.removeSync(legacyFile);
|
|
2063
2207
|
} catch {
|
|
2064
2208
|
}
|
|
2065
2209
|
}
|
|
@@ -2071,17 +2215,17 @@ function getApiUrl(env = "dev") {
|
|
|
2071
2215
|
return process.env.ONEXTHM_API_URL || ENV_URLS[env];
|
|
2072
2216
|
}
|
|
2073
2217
|
async function saveAuthTokens(tokens, env = "dev") {
|
|
2074
|
-
await
|
|
2218
|
+
await fs8__default.default.ensureDir(AUTH_DIR);
|
|
2075
2219
|
const key = getMachineKey();
|
|
2076
2220
|
const data = JSON.stringify(tokens);
|
|
2077
2221
|
const encrypted = encrypt(data, key);
|
|
2078
|
-
await
|
|
2222
|
+
await fs8__default.default.writeFile(getAuthFile(env), encrypted, "utf-8");
|
|
2079
2223
|
}
|
|
2080
2224
|
function loadAuthTokens(env = "dev") {
|
|
2081
2225
|
try {
|
|
2082
2226
|
const file = getAuthFile(env);
|
|
2083
|
-
if (!
|
|
2084
|
-
const encrypted =
|
|
2227
|
+
if (!fs8__default.default.existsSync(file)) return null;
|
|
2228
|
+
const encrypted = fs8__default.default.readFileSync(file, "utf-8");
|
|
2085
2229
|
const key = getMachineKey();
|
|
2086
2230
|
const data = decrypt(encrypted, key);
|
|
2087
2231
|
return JSON.parse(data);
|
|
@@ -2091,7 +2235,7 @@ function loadAuthTokens(env = "dev") {
|
|
|
2091
2235
|
}
|
|
2092
2236
|
async function clearAuthTokens(env = "dev") {
|
|
2093
2237
|
try {
|
|
2094
|
-
await
|
|
2238
|
+
await fs8__default.default.remove(getAuthFile(env));
|
|
2095
2239
|
} catch {
|
|
2096
2240
|
}
|
|
2097
2241
|
}
|
|
@@ -2150,7 +2294,7 @@ function getMachineKey() {
|
|
|
2150
2294
|
seed = `onexthm:${os__default.default.hostname()}:${os__default.default.userInfo().username}`;
|
|
2151
2295
|
} else if (process.platform === "linux") {
|
|
2152
2296
|
try {
|
|
2153
|
-
seed = `onexthm:${
|
|
2297
|
+
seed = `onexthm:${fs8__default.default.readFileSync("/etc/machine-id", "utf-8").trim()}`;
|
|
2154
2298
|
} catch {
|
|
2155
2299
|
seed = `onexthm:${os__default.default.hostname()}:${os__default.default.userInfo().username}`;
|
|
2156
2300
|
}
|
|
@@ -2188,7 +2332,7 @@ function parseJwtClaims(idToken) {
|
|
|
2188
2332
|
}
|
|
2189
2333
|
|
|
2190
2334
|
// src/commands/init.ts
|
|
2191
|
-
async function initCommand(projectName, options
|
|
2335
|
+
async function initCommand(projectName, options) {
|
|
2192
2336
|
logger.header("Create New OneX Theme Project");
|
|
2193
2337
|
let name;
|
|
2194
2338
|
if (!projectName) {
|
|
@@ -2203,7 +2347,7 @@ async function initCommand(projectName, options = {}) {
|
|
|
2203
2347
|
if (!validateThemeName(kebabName)) {
|
|
2204
2348
|
return "Invalid project name. Use lowercase letters, numbers, and hyphens only.";
|
|
2205
2349
|
}
|
|
2206
|
-
if (fs3__default.default.existsSync(
|
|
2350
|
+
if (fs3__default.default.existsSync(path13__default.default.join(process.cwd(), kebabName))) {
|
|
2207
2351
|
return `Directory "${kebabName}" already exists`;
|
|
2208
2352
|
}
|
|
2209
2353
|
return true;
|
|
@@ -2214,14 +2358,14 @@ async function initCommand(projectName, options = {}) {
|
|
|
2214
2358
|
} else {
|
|
2215
2359
|
name = toKebabCase(projectName);
|
|
2216
2360
|
}
|
|
2217
|
-
const projectPath =
|
|
2361
|
+
const projectPath = path13__default.default.join(process.cwd(), name);
|
|
2218
2362
|
if (fs3__default.default.existsSync(projectPath)) {
|
|
2219
2363
|
logger.error(`Directory "${name}" already exists.`);
|
|
2220
2364
|
process.exit(1);
|
|
2221
2365
|
}
|
|
2222
2366
|
if (!options.yes) {
|
|
2223
2367
|
try {
|
|
2224
|
-
const apiUrl = getApiUrl(options.env
|
|
2368
|
+
const apiUrl = getApiUrl(options.env);
|
|
2225
2369
|
const controller = new AbortController();
|
|
2226
2370
|
const timeout = setTimeout(() => controller.abort(), 3e3);
|
|
2227
2371
|
const response = await fetch(
|
|
@@ -2330,7 +2474,7 @@ async function initCommand(projectName, options = {}) {
|
|
|
2330
2474
|
description,
|
|
2331
2475
|
author
|
|
2332
2476
|
);
|
|
2333
|
-
const mcpJsonPath =
|
|
2477
|
+
const mcpJsonPath = path13__default.default.join(projectPath, ".mcp.json");
|
|
2334
2478
|
if (fs3__default.default.existsSync(mcpJsonPath)) {
|
|
2335
2479
|
let mcpContent = fs3__default.default.readFileSync(mcpJsonPath, "utf-8");
|
|
2336
2480
|
if (figmaApiKey) {
|
|
@@ -2410,7 +2554,7 @@ async function initCommand(projectName, options = {}) {
|
|
|
2410
2554
|
}
|
|
2411
2555
|
}
|
|
2412
2556
|
async function renameThemeInFiles(projectPath, themeName, displayName, description, author) {
|
|
2413
|
-
const configPath =
|
|
2557
|
+
const configPath = path13__default.default.join(projectPath, "theme.config.ts");
|
|
2414
2558
|
if (fs3__default.default.existsSync(configPath)) {
|
|
2415
2559
|
let content = fs3__default.default.readFileSync(configPath, "utf-8");
|
|
2416
2560
|
content = content.replace(
|
|
@@ -2423,7 +2567,7 @@ async function renameThemeInFiles(projectPath, themeName, displayName, descripti
|
|
|
2423
2567
|
);
|
|
2424
2568
|
fs3__default.default.writeFileSync(configPath, content, "utf-8");
|
|
2425
2569
|
}
|
|
2426
|
-
const pkgPath =
|
|
2570
|
+
const pkgPath = path13__default.default.join(projectPath, "package.json");
|
|
2427
2571
|
if (fs3__default.default.existsSync(pkgPath)) {
|
|
2428
2572
|
let content = fs3__default.default.readFileSync(pkgPath, "utf-8");
|
|
2429
2573
|
content = content.replace(
|
|
@@ -2445,10 +2589,10 @@ async function createSectionCommand(name, options) {
|
|
|
2445
2589
|
ensureOneXProject();
|
|
2446
2590
|
if (!options.theme) {
|
|
2447
2591
|
const isStandaloneTheme = ["theme.config.ts", "bundle-entry.ts"].some(
|
|
2448
|
-
(f) =>
|
|
2592
|
+
(f) => fs8__default.default.existsSync(path13__default.default.join(process.cwd(), f))
|
|
2449
2593
|
);
|
|
2450
2594
|
if (isStandaloneTheme) {
|
|
2451
|
-
options.theme =
|
|
2595
|
+
options.theme = path13__default.default.basename(process.cwd());
|
|
2452
2596
|
}
|
|
2453
2597
|
}
|
|
2454
2598
|
const sectionName = toKebabCase(name);
|
|
@@ -2511,35 +2655,35 @@ async function createSectionCommand(name, options) {
|
|
|
2511
2655
|
};
|
|
2512
2656
|
logger.startSpinner("Creating section files...");
|
|
2513
2657
|
try {
|
|
2514
|
-
const themePath =
|
|
2515
|
-
const sectionPath =
|
|
2658
|
+
const themePath = path13__default.default.join(getThemesDir(), themeName);
|
|
2659
|
+
const sectionPath = path13__default.default.join(themePath, "sections", sectionName);
|
|
2516
2660
|
const schemaContent = generateSectionSchema(data);
|
|
2517
2661
|
await writeFile(
|
|
2518
|
-
|
|
2662
|
+
path13__default.default.join(sectionPath, `${sectionName}.schema.ts`),
|
|
2519
2663
|
schemaContent
|
|
2520
2664
|
);
|
|
2521
2665
|
if (createTemplate) {
|
|
2522
2666
|
const templateContent = generateSectionTemplate(data);
|
|
2523
2667
|
await writeFile(
|
|
2524
|
-
|
|
2668
|
+
path13__default.default.join(sectionPath, `${sectionName}-default.tsx`),
|
|
2525
2669
|
templateContent
|
|
2526
2670
|
);
|
|
2527
2671
|
}
|
|
2528
2672
|
const indexContent = generateSectionIndex(data, createTemplate);
|
|
2529
|
-
await writeFile(
|
|
2673
|
+
await writeFile(path13__default.default.join(sectionPath, "index.ts"), indexContent);
|
|
2530
2674
|
logger.stopSpinner(true, "Section files created successfully!");
|
|
2531
2675
|
logger.newLine();
|
|
2532
2676
|
logger.section("Next steps:");
|
|
2533
2677
|
logger.log(
|
|
2534
|
-
` 1. Edit schema: ${
|
|
2678
|
+
` 1. Edit schema: ${path13__default.default.relative(process.cwd(), path13__default.default.join(sectionPath, `${sectionName}.schema.ts`))}`
|
|
2535
2679
|
);
|
|
2536
2680
|
if (createTemplate) {
|
|
2537
2681
|
logger.log(
|
|
2538
|
-
` 2. Edit template: ${
|
|
2682
|
+
` 2. Edit template: ${path13__default.default.relative(process.cwd(), path13__default.default.join(sectionPath, `${sectionName}-default.tsx`))}`
|
|
2539
2683
|
);
|
|
2540
2684
|
}
|
|
2541
2685
|
logger.log(
|
|
2542
|
-
` 3. Add to theme manifest: ${
|
|
2686
|
+
` 3. Add to theme manifest: ${path13__default.default.relative(process.cwd(), path13__default.default.join(themePath, "manifest.ts"))}`
|
|
2543
2687
|
);
|
|
2544
2688
|
logger.newLine();
|
|
2545
2689
|
logger.success("Section created successfully!");
|
|
@@ -2687,10 +2831,10 @@ async function createBlockCommand(name, options) {
|
|
|
2687
2831
|
ensureOneXProject();
|
|
2688
2832
|
if (!options.theme) {
|
|
2689
2833
|
const isStandaloneTheme = ["theme.config.ts", "bundle-entry.ts"].some(
|
|
2690
|
-
(f) =>
|
|
2834
|
+
(f) => fs8__default.default.existsSync(path13__default.default.join(process.cwd(), f))
|
|
2691
2835
|
);
|
|
2692
2836
|
if (isStandaloneTheme) {
|
|
2693
|
-
options.theme =
|
|
2837
|
+
options.theme = path13__default.default.basename(process.cwd());
|
|
2694
2838
|
}
|
|
2695
2839
|
}
|
|
2696
2840
|
const blockName = toKebabCase(name);
|
|
@@ -2765,24 +2909,24 @@ async function createBlockCommand(name, options) {
|
|
|
2765
2909
|
};
|
|
2766
2910
|
logger.startSpinner("Creating block files...");
|
|
2767
2911
|
try {
|
|
2768
|
-
const blockPath = scope === "shared" ?
|
|
2912
|
+
const blockPath = scope === "shared" ? path13__default.default.join(getFeaturesDir(), "blocks", blockName) : path13__default.default.join(getThemesDir(), themeName, "blocks", blockName);
|
|
2769
2913
|
const schemaContent = generateBlockSchema(data);
|
|
2770
2914
|
await writeFile(
|
|
2771
|
-
|
|
2915
|
+
path13__default.default.join(blockPath, `${blockName}.schema.ts`),
|
|
2772
2916
|
schemaContent
|
|
2773
2917
|
);
|
|
2774
2918
|
const componentContent = generateBlockComponent(data);
|
|
2775
|
-
await writeFile(
|
|
2919
|
+
await writeFile(path13__default.default.join(blockPath, `${blockName}.tsx`), componentContent);
|
|
2776
2920
|
const indexContent = generateBlockIndex(data);
|
|
2777
|
-
await writeFile(
|
|
2921
|
+
await writeFile(path13__default.default.join(blockPath, "index.ts"), indexContent);
|
|
2778
2922
|
logger.stopSpinner(true, "Block files created successfully!");
|
|
2779
2923
|
logger.newLine();
|
|
2780
2924
|
logger.section("Next steps:");
|
|
2781
2925
|
logger.log(
|
|
2782
|
-
` 1. Edit schema: ${
|
|
2926
|
+
` 1. Edit schema: ${path13__default.default.relative(process.cwd(), path13__default.default.join(blockPath, `${blockName}.schema.ts`))}`
|
|
2783
2927
|
);
|
|
2784
2928
|
logger.log(
|
|
2785
|
-
` 2. Edit component: ${
|
|
2929
|
+
` 2. Edit component: ${path13__default.default.relative(process.cwd(), path13__default.default.join(blockPath, `${blockName}.tsx`))}`
|
|
2786
2930
|
);
|
|
2787
2931
|
logger.log(
|
|
2788
2932
|
` 3. Register in block registry: src/lib/registry/block-registry.ts`
|
|
@@ -2960,31 +3104,31 @@ async function createComponentCommand(name, options) {
|
|
|
2960
3104
|
};
|
|
2961
3105
|
logger.startSpinner("Creating component files...");
|
|
2962
3106
|
try {
|
|
2963
|
-
const componentPath =
|
|
3107
|
+
const componentPath = path13__default.default.join(
|
|
2964
3108
|
getFeaturesDir(),
|
|
2965
3109
|
"components",
|
|
2966
3110
|
componentName
|
|
2967
3111
|
);
|
|
2968
3112
|
const schemaContent = generateComponentSchema(data);
|
|
2969
3113
|
await writeFile(
|
|
2970
|
-
|
|
3114
|
+
path13__default.default.join(componentPath, `${componentName}.schema.ts`),
|
|
2971
3115
|
schemaContent
|
|
2972
3116
|
);
|
|
2973
3117
|
const componentContent = generateComponent(data);
|
|
2974
3118
|
await writeFile(
|
|
2975
|
-
|
|
3119
|
+
path13__default.default.join(componentPath, `${componentName}.tsx`),
|
|
2976
3120
|
componentContent
|
|
2977
3121
|
);
|
|
2978
3122
|
const indexContent = generateComponentIndex(data);
|
|
2979
|
-
await writeFile(
|
|
3123
|
+
await writeFile(path13__default.default.join(componentPath, "index.ts"), indexContent);
|
|
2980
3124
|
logger.stopSpinner(true, "Component files created successfully!");
|
|
2981
3125
|
logger.newLine();
|
|
2982
3126
|
logger.section("Next steps:");
|
|
2983
3127
|
logger.log(
|
|
2984
|
-
` 1. Edit schema: ${
|
|
3128
|
+
` 1. Edit schema: ${path13__default.default.relative(process.cwd(), path13__default.default.join(componentPath, `${componentName}.schema.ts`))}`
|
|
2985
3129
|
);
|
|
2986
3130
|
logger.log(
|
|
2987
|
-
` 2. Edit component: ${
|
|
3131
|
+
` 2. Edit component: ${path13__default.default.relative(process.cwd(), path13__default.default.join(componentPath, `${componentName}.tsx`))}`
|
|
2988
3132
|
);
|
|
2989
3133
|
logger.log(
|
|
2990
3134
|
` 3. Register in component registry: src/lib/registry/component-registry.ts`
|
|
@@ -3141,13 +3285,13 @@ async function listSections(themeFilter) {
|
|
|
3141
3285
|
return;
|
|
3142
3286
|
}
|
|
3143
3287
|
for (const theme of themes) {
|
|
3144
|
-
const sectionsDir =
|
|
3145
|
-
if (!
|
|
3288
|
+
const sectionsDir = path13__default.default.join(getThemesDir(), theme, "sections");
|
|
3289
|
+
if (!fs8__default.default.existsSync(sectionsDir)) {
|
|
3146
3290
|
continue;
|
|
3147
3291
|
}
|
|
3148
|
-
const sections =
|
|
3149
|
-
const sectionPath =
|
|
3150
|
-
return
|
|
3292
|
+
const sections = fs8__default.default.readdirSync(sectionsDir).filter((name) => {
|
|
3293
|
+
const sectionPath = path13__default.default.join(sectionsDir, name);
|
|
3294
|
+
return fs8__default.default.statSync(sectionPath).isDirectory() && fs8__default.default.existsSync(path13__default.default.join(sectionPath, "index.ts"));
|
|
3151
3295
|
});
|
|
3152
3296
|
if (sections.length > 0) {
|
|
3153
3297
|
logger.log(chalk4__default.default.cyan(`
|
|
@@ -3161,11 +3305,11 @@ async function listSections(themeFilter) {
|
|
|
3161
3305
|
}
|
|
3162
3306
|
async function listBlocks(themeFilter) {
|
|
3163
3307
|
logger.section("\u{1F9F1} Blocks");
|
|
3164
|
-
const sharedBlocksDir =
|
|
3165
|
-
if (
|
|
3166
|
-
const sharedBlocks =
|
|
3167
|
-
const blockPath =
|
|
3168
|
-
return
|
|
3308
|
+
const sharedBlocksDir = path13__default.default.join(getFeaturesDir(), "blocks");
|
|
3309
|
+
if (fs8__default.default.existsSync(sharedBlocksDir)) {
|
|
3310
|
+
const sharedBlocks = fs8__default.default.readdirSync(sharedBlocksDir).filter((name) => {
|
|
3311
|
+
const blockPath = path13__default.default.join(sharedBlocksDir, name);
|
|
3312
|
+
return fs8__default.default.statSync(blockPath).isDirectory() && fs8__default.default.existsSync(path13__default.default.join(blockPath, "index.ts"));
|
|
3169
3313
|
});
|
|
3170
3314
|
if (sharedBlocks.length > 0) {
|
|
3171
3315
|
logger.log(chalk4__default.default.cyan("\n Shared:"));
|
|
@@ -3176,13 +3320,13 @@ async function listBlocks(themeFilter) {
|
|
|
3176
3320
|
}
|
|
3177
3321
|
const themes = themeFilter ? [themeFilter] : listThemes();
|
|
3178
3322
|
for (const theme of themes) {
|
|
3179
|
-
const blocksDir =
|
|
3180
|
-
if (!
|
|
3323
|
+
const blocksDir = path13__default.default.join(getThemesDir(), theme, "blocks");
|
|
3324
|
+
if (!fs8__default.default.existsSync(blocksDir)) {
|
|
3181
3325
|
continue;
|
|
3182
3326
|
}
|
|
3183
|
-
const blocks =
|
|
3184
|
-
const blockPath =
|
|
3185
|
-
return
|
|
3327
|
+
const blocks = fs8__default.default.readdirSync(blocksDir).filter((name) => {
|
|
3328
|
+
const blockPath = path13__default.default.join(blocksDir, name);
|
|
3329
|
+
return fs8__default.default.statSync(blockPath).isDirectory() && fs8__default.default.existsSync(path13__default.default.join(blockPath, "index.ts"));
|
|
3186
3330
|
});
|
|
3187
3331
|
if (blocks.length > 0) {
|
|
3188
3332
|
logger.log(chalk4__default.default.cyan(`
|
|
@@ -3196,14 +3340,14 @@ async function listBlocks(themeFilter) {
|
|
|
3196
3340
|
}
|
|
3197
3341
|
async function listComponents() {
|
|
3198
3342
|
logger.section("\u2699\uFE0F Components");
|
|
3199
|
-
const componentsDir =
|
|
3200
|
-
if (!
|
|
3343
|
+
const componentsDir = path13__default.default.join(getFeaturesDir(), "components");
|
|
3344
|
+
if (!fs8__default.default.existsSync(componentsDir)) {
|
|
3201
3345
|
logger.warning("No components directory found");
|
|
3202
3346
|
return;
|
|
3203
3347
|
}
|
|
3204
|
-
const components =
|
|
3205
|
-
const componentPath =
|
|
3206
|
-
return
|
|
3348
|
+
const components = fs8__default.default.readdirSync(componentsDir).filter((name) => {
|
|
3349
|
+
const componentPath = path13__default.default.join(componentsDir, name);
|
|
3350
|
+
return fs8__default.default.statSync(componentPath).isDirectory() && fs8__default.default.existsSync(path13__default.default.join(componentPath, "index.ts"));
|
|
3207
3351
|
});
|
|
3208
3352
|
if (components.length === 0) {
|
|
3209
3353
|
logger.warning("No components found");
|
|
@@ -3224,13 +3368,13 @@ async function listThemesInfo() {
|
|
|
3224
3368
|
}
|
|
3225
3369
|
logger.log("");
|
|
3226
3370
|
for (const theme of themes) {
|
|
3227
|
-
const themeDir =
|
|
3371
|
+
const themeDir = path13__default.default.join(getThemesDir(), theme);
|
|
3228
3372
|
const candidates = ["theme.config.ts", "bundle-entry.ts", "manifest.ts"];
|
|
3229
3373
|
let manifestContent = "";
|
|
3230
3374
|
for (const candidate of candidates) {
|
|
3231
|
-
const candidatePath =
|
|
3232
|
-
if (
|
|
3233
|
-
manifestContent =
|
|
3375
|
+
const candidatePath = path13__default.default.join(themeDir, candidate);
|
|
3376
|
+
if (fs8__default.default.existsSync(candidatePath)) {
|
|
3377
|
+
manifestContent = fs8__default.default.readFileSync(candidatePath, "utf-8");
|
|
3234
3378
|
break;
|
|
3235
3379
|
}
|
|
3236
3380
|
}
|
|
@@ -3250,6 +3394,7 @@ async function listThemesInfo() {
|
|
|
3250
3394
|
|
|
3251
3395
|
// src/commands/validate.ts
|
|
3252
3396
|
init_logger();
|
|
3397
|
+
init_detect_nextjs();
|
|
3253
3398
|
async function validateCommand(options) {
|
|
3254
3399
|
logger.header("Validate Theme");
|
|
3255
3400
|
ensureOneXProject();
|
|
@@ -3265,10 +3410,13 @@ async function validateCommand(options) {
|
|
|
3265
3410
|
const isThemeDir2 = [
|
|
3266
3411
|
"theme.config.ts",
|
|
3267
3412
|
"bundle-entry.ts",
|
|
3268
|
-
"manifest.ts"
|
|
3269
|
-
|
|
3413
|
+
"manifest.ts",
|
|
3414
|
+
"next.config.ts",
|
|
3415
|
+
"next.config.js",
|
|
3416
|
+
"next.config.mjs"
|
|
3417
|
+
].some((f) => fs8__default.default.existsSync(path13__default.default.join(process.cwd(), f)));
|
|
3270
3418
|
if (isThemeDir2) {
|
|
3271
|
-
themeToValidate =
|
|
3419
|
+
themeToValidate = path13__default.default.basename(process.cwd());
|
|
3272
3420
|
logger.info(`Validating current theme: ${themeToValidate}`);
|
|
3273
3421
|
} else {
|
|
3274
3422
|
logger.error(
|
|
@@ -3277,11 +3425,11 @@ async function validateCommand(options) {
|
|
|
3277
3425
|
process.exit(1);
|
|
3278
3426
|
}
|
|
3279
3427
|
}
|
|
3280
|
-
const themePath =
|
|
3428
|
+
const themePath = path13__default.default.join(getThemesDir(), themeToValidate);
|
|
3281
3429
|
logger.startSpinner("Running validation checks...");
|
|
3282
3430
|
const entryFiles = ["manifest.ts", "theme.config.ts", "bundle-entry.ts"];
|
|
3283
3431
|
const foundEntry = entryFiles.find(
|
|
3284
|
-
(f) =>
|
|
3432
|
+
(f) => fs8__default.default.existsSync(path13__default.default.join(themePath, f))
|
|
3285
3433
|
);
|
|
3286
3434
|
if (!foundEntry) {
|
|
3287
3435
|
issues.push({
|
|
@@ -3290,8 +3438,8 @@ async function validateCommand(options) {
|
|
|
3290
3438
|
message: "No theme entry file found (need at least one of: manifest.ts, theme.config.ts, bundle-entry.ts)"
|
|
3291
3439
|
});
|
|
3292
3440
|
} else if (foundEntry === "manifest.ts") {
|
|
3293
|
-
const manifestContent =
|
|
3294
|
-
|
|
3441
|
+
const manifestContent = fs8__default.default.readFileSync(
|
|
3442
|
+
path13__default.default.join(themePath, foundEntry),
|
|
3295
3443
|
"utf-8"
|
|
3296
3444
|
);
|
|
3297
3445
|
if (!manifestContent.includes("export const") && !manifestContent.includes("export default") && !manifestContent.includes("export interface")) {
|
|
@@ -3302,56 +3450,56 @@ async function validateCommand(options) {
|
|
|
3302
3450
|
});
|
|
3303
3451
|
}
|
|
3304
3452
|
}
|
|
3305
|
-
const configPath =
|
|
3306
|
-
if (!
|
|
3453
|
+
const configPath = path13__default.default.join(themePath, "theme.config.ts");
|
|
3454
|
+
if (!fs8__default.default.existsSync(configPath)) {
|
|
3307
3455
|
issues.push({
|
|
3308
3456
|
type: "warning",
|
|
3309
3457
|
file: "theme.config.ts",
|
|
3310
3458
|
message: "Theme config file not found (recommended)"
|
|
3311
3459
|
});
|
|
3312
3460
|
}
|
|
3313
|
-
const indexPath =
|
|
3314
|
-
if (!
|
|
3461
|
+
const indexPath = path13__default.default.join(themePath, "index.ts");
|
|
3462
|
+
if (!fs8__default.default.existsSync(indexPath)) {
|
|
3315
3463
|
issues.push({
|
|
3316
3464
|
type: "warning",
|
|
3317
3465
|
file: "index.ts",
|
|
3318
3466
|
message: "Index file not found (recommended)"
|
|
3319
3467
|
});
|
|
3320
3468
|
}
|
|
3321
|
-
const sectionsDir =
|
|
3322
|
-
if (!
|
|
3469
|
+
const sectionsDir = path13__default.default.join(themePath, "sections");
|
|
3470
|
+
if (!fs8__default.default.existsSync(sectionsDir)) {
|
|
3323
3471
|
issues.push({
|
|
3324
3472
|
type: "warning",
|
|
3325
3473
|
file: "sections/",
|
|
3326
3474
|
message: "Sections directory not found"
|
|
3327
3475
|
});
|
|
3328
3476
|
} else {
|
|
3329
|
-
const sections =
|
|
3330
|
-
(name) =>
|
|
3477
|
+
const sections = fs8__default.default.readdirSync(sectionsDir).filter(
|
|
3478
|
+
(name) => fs8__default.default.statSync(path13__default.default.join(sectionsDir, name)).isDirectory()
|
|
3331
3479
|
);
|
|
3332
3480
|
for (const sectionName of sections) {
|
|
3333
|
-
const sectionPath =
|
|
3334
|
-
const schemaFile =
|
|
3335
|
-
const defaultTemplate =
|
|
3481
|
+
const sectionPath = path13__default.default.join(sectionsDir, sectionName);
|
|
3482
|
+
const schemaFile = path13__default.default.join(sectionPath, `${sectionName}.schema.ts`);
|
|
3483
|
+
const defaultTemplate = path13__default.default.join(
|
|
3336
3484
|
sectionPath,
|
|
3337
3485
|
`${sectionName}-default.tsx`
|
|
3338
3486
|
);
|
|
3339
|
-
const indexFile =
|
|
3340
|
-
if (!
|
|
3487
|
+
const indexFile = path13__default.default.join(sectionPath, "index.ts");
|
|
3488
|
+
if (!fs8__default.default.existsSync(schemaFile)) {
|
|
3341
3489
|
issues.push({
|
|
3342
3490
|
type: "error",
|
|
3343
3491
|
file: `sections/${sectionName}/${sectionName}.schema.ts`,
|
|
3344
3492
|
message: "Section schema file missing"
|
|
3345
3493
|
});
|
|
3346
3494
|
}
|
|
3347
|
-
if (!
|
|
3495
|
+
if (!fs8__default.default.existsSync(indexFile)) {
|
|
3348
3496
|
issues.push({
|
|
3349
3497
|
type: "error",
|
|
3350
3498
|
file: `sections/${sectionName}/index.ts`,
|
|
3351
3499
|
message: "Section index file missing"
|
|
3352
3500
|
});
|
|
3353
3501
|
}
|
|
3354
|
-
if (!
|
|
3502
|
+
if (!fs8__default.default.existsSync(defaultTemplate)) {
|
|
3355
3503
|
issues.push({
|
|
3356
3504
|
type: "warning",
|
|
3357
3505
|
file: `sections/${sectionName}/${sectionName}-default.tsx`,
|
|
@@ -3360,29 +3508,29 @@ async function validateCommand(options) {
|
|
|
3360
3508
|
}
|
|
3361
3509
|
}
|
|
3362
3510
|
}
|
|
3363
|
-
const blocksDir =
|
|
3364
|
-
if (
|
|
3365
|
-
const blocks =
|
|
3511
|
+
const blocksDir = path13__default.default.join(themePath, "blocks");
|
|
3512
|
+
if (fs8__default.default.existsSync(blocksDir)) {
|
|
3513
|
+
const blocks = fs8__default.default.readdirSync(blocksDir).filter((name) => fs8__default.default.statSync(path13__default.default.join(blocksDir, name)).isDirectory());
|
|
3366
3514
|
for (const blockName of blocks) {
|
|
3367
|
-
const blockPath =
|
|
3368
|
-
const schemaFile =
|
|
3369
|
-
const componentFile =
|
|
3370
|
-
const indexFile =
|
|
3371
|
-
if (!
|
|
3515
|
+
const blockPath = path13__default.default.join(blocksDir, blockName);
|
|
3516
|
+
const schemaFile = path13__default.default.join(blockPath, `${blockName}.schema.ts`);
|
|
3517
|
+
const componentFile = path13__default.default.join(blockPath, `${blockName}.tsx`);
|
|
3518
|
+
const indexFile = path13__default.default.join(blockPath, "index.ts");
|
|
3519
|
+
if (!fs8__default.default.existsSync(schemaFile)) {
|
|
3372
3520
|
issues.push({
|
|
3373
3521
|
type: "error",
|
|
3374
3522
|
file: `blocks/${blockName}/${blockName}.schema.ts`,
|
|
3375
3523
|
message: "Block schema file missing"
|
|
3376
3524
|
});
|
|
3377
3525
|
}
|
|
3378
|
-
if (!
|
|
3526
|
+
if (!fs8__default.default.existsSync(componentFile)) {
|
|
3379
3527
|
issues.push({
|
|
3380
3528
|
type: "error",
|
|
3381
3529
|
file: `blocks/${blockName}/${blockName}.tsx`,
|
|
3382
3530
|
message: "Block component file missing"
|
|
3383
3531
|
});
|
|
3384
3532
|
}
|
|
3385
|
-
if (!
|
|
3533
|
+
if (!fs8__default.default.existsSync(indexFile)) {
|
|
3386
3534
|
issues.push({
|
|
3387
3535
|
type: "error",
|
|
3388
3536
|
file: `blocks/${blockName}/index.ts`,
|
|
@@ -3391,16 +3539,16 @@ async function validateCommand(options) {
|
|
|
3391
3539
|
}
|
|
3392
3540
|
}
|
|
3393
3541
|
}
|
|
3394
|
-
if (
|
|
3395
|
-
const sections =
|
|
3396
|
-
(name) =>
|
|
3542
|
+
if (fs8__default.default.existsSync(sectionsDir)) {
|
|
3543
|
+
const sections = fs8__default.default.readdirSync(sectionsDir).filter(
|
|
3544
|
+
(name) => fs8__default.default.statSync(path13__default.default.join(sectionsDir, name)).isDirectory()
|
|
3397
3545
|
);
|
|
3398
3546
|
for (const sectionName of sections) {
|
|
3399
|
-
const sectionPath =
|
|
3400
|
-
const tsxFiles =
|
|
3547
|
+
const sectionPath = path13__default.default.join(sectionsDir, sectionName);
|
|
3548
|
+
const tsxFiles = fs8__default.default.readdirSync(sectionPath).filter((f) => f.endsWith(".tsx") && !f.endsWith(".schema.ts"));
|
|
3401
3549
|
for (const tsxFile of tsxFiles) {
|
|
3402
|
-
const filePath =
|
|
3403
|
-
const content =
|
|
3550
|
+
const filePath = path13__default.default.join(sectionPath, tsxFile);
|
|
3551
|
+
const content = fs8__default.default.readFileSync(filePath, "utf-8");
|
|
3404
3552
|
const relPath = `sections/${sectionName}/${tsxFile}`;
|
|
3405
3553
|
if (!content.includes('"use client"') && !content.includes("'use client'")) {
|
|
3406
3554
|
issues.push({
|
|
@@ -3447,12 +3595,12 @@ async function validateCommand(options) {
|
|
|
3447
3595
|
}
|
|
3448
3596
|
}
|
|
3449
3597
|
}
|
|
3450
|
-
const registryPath =
|
|
3451
|
-
const bundleEntryPath =
|
|
3452
|
-
const registryContent =
|
|
3453
|
-
if (
|
|
3454
|
-
const sections =
|
|
3455
|
-
(name) =>
|
|
3598
|
+
const registryPath = path13__default.default.join(themePath, "sections-registry.ts");
|
|
3599
|
+
const bundleEntryPath = path13__default.default.join(themePath, "bundle-entry.ts");
|
|
3600
|
+
const registryContent = fs8__default.default.existsSync(registryPath) ? fs8__default.default.readFileSync(registryPath, "utf-8") : fs8__default.default.existsSync(bundleEntryPath) ? fs8__default.default.readFileSync(bundleEntryPath, "utf-8") : "";
|
|
3601
|
+
if (fs8__default.default.existsSync(sectionsDir) && registryContent) {
|
|
3602
|
+
const sections = fs8__default.default.readdirSync(sectionsDir).filter(
|
|
3603
|
+
(name) => fs8__default.default.statSync(path13__default.default.join(sectionsDir, name)).isDirectory()
|
|
3456
3604
|
);
|
|
3457
3605
|
for (const sectionName of sections) {
|
|
3458
3606
|
if (!registryContent.includes(`sections/${sectionName}`) && !registryContent.includes(`"${sectionName}"`)) {
|
|
@@ -3464,7 +3612,7 @@ async function validateCommand(options) {
|
|
|
3464
3612
|
}
|
|
3465
3613
|
}
|
|
3466
3614
|
}
|
|
3467
|
-
if (
|
|
3615
|
+
if (fs8__default.default.existsSync(sectionsDir)) {
|
|
3468
3616
|
const schemaTypes = await loadSchemaTypes(themePath, sectionsDir);
|
|
3469
3617
|
for (const { folderName, schemaType } of schemaTypes) {
|
|
3470
3618
|
if (schemaType && schemaType !== folderName) {
|
|
@@ -3475,8 +3623,8 @@ async function validateCommand(options) {
|
|
|
3475
3623
|
});
|
|
3476
3624
|
}
|
|
3477
3625
|
}
|
|
3478
|
-
const pagesDir =
|
|
3479
|
-
if (
|
|
3626
|
+
const pagesDir = path13__default.default.join(themePath, "pages");
|
|
3627
|
+
if (fs8__default.default.existsSync(pagesDir)) {
|
|
3480
3628
|
const allSchemaTypeSet = new Set(
|
|
3481
3629
|
schemaTypes.map((s) => s.schemaType || s.folderName)
|
|
3482
3630
|
);
|
|
@@ -3487,6 +3635,10 @@ async function validateCommand(options) {
|
|
|
3487
3635
|
issues.push(...pageIssues);
|
|
3488
3636
|
}
|
|
3489
3637
|
}
|
|
3638
|
+
if (isNextjsProject(themePath)) {
|
|
3639
|
+
const nextjsIssues = await validateNextjsComponents(themePath);
|
|
3640
|
+
issues.push(...nextjsIssues);
|
|
3641
|
+
}
|
|
3490
3642
|
logger.stopSpinner(true, "Validation complete");
|
|
3491
3643
|
const errors = issues.filter((i) => i.type === "error");
|
|
3492
3644
|
const warnings = issues.filter((i) => i.type === "warning");
|
|
@@ -3527,18 +3679,18 @@ async function validateCommand(options) {
|
|
|
3527
3679
|
}
|
|
3528
3680
|
async function loadSchemaTypes(themePath, sectionsDir) {
|
|
3529
3681
|
const results = [];
|
|
3530
|
-
const sections =
|
|
3682
|
+
const sections = fs8__default.default.readdirSync(sectionsDir).filter((name) => fs8__default.default.statSync(path13__default.default.join(sectionsDir, name)).isDirectory());
|
|
3531
3683
|
for (const sectionName of sections) {
|
|
3532
|
-
const schemaFile =
|
|
3684
|
+
const schemaFile = path13__default.default.join(
|
|
3533
3685
|
sectionsDir,
|
|
3534
3686
|
sectionName,
|
|
3535
3687
|
`${sectionName}.schema.ts`
|
|
3536
3688
|
);
|
|
3537
|
-
if (!
|
|
3689
|
+
if (!fs8__default.default.existsSync(schemaFile)) {
|
|
3538
3690
|
results.push({ folderName: sectionName, schemaType: null });
|
|
3539
3691
|
continue;
|
|
3540
3692
|
}
|
|
3541
|
-
const content =
|
|
3693
|
+
const content = fs8__default.default.readFileSync(schemaFile, "utf-8");
|
|
3542
3694
|
let schemaType = null;
|
|
3543
3695
|
const schemaExportMatch = content.match(
|
|
3544
3696
|
/:\s*SectionSchema\s*=\s*\{[\s\S]*?\btype:\s*["']([^"']+)["']/
|
|
@@ -3565,9 +3717,9 @@ async function loadSchemaTypes(themePath, sectionsDir) {
|
|
|
3565
3717
|
}
|
|
3566
3718
|
async function validatePageSectionTypes(pagesDir, validTypes) {
|
|
3567
3719
|
const issues = [];
|
|
3568
|
-
const files =
|
|
3720
|
+
const files = fs8__default.default.readdirSync(pagesDir).filter((f) => f.match(/\.(ts|js)$/));
|
|
3569
3721
|
for (const file of files) {
|
|
3570
|
-
const content =
|
|
3722
|
+
const content = fs8__default.default.readFileSync(path13__default.default.join(pagesDir, file), "utf-8");
|
|
3571
3723
|
const pageName = file.replace(/\.(ts|js)$/, "");
|
|
3572
3724
|
const sectionsMatch = content.match(/\bsections:\s*\[/);
|
|
3573
3725
|
if (!sectionsMatch || sectionsMatch.index === void 0) continue;
|
|
@@ -3697,9 +3849,70 @@ var BLOCK_TYPES = /* @__PURE__ */ new Set([
|
|
|
3697
3849
|
"team-member",
|
|
3698
3850
|
"hero-content"
|
|
3699
3851
|
]);
|
|
3852
|
+
var SERVER_ONLY_APIS = [
|
|
3853
|
+
"next/headers",
|
|
3854
|
+
"next/server",
|
|
3855
|
+
"next/cache",
|
|
3856
|
+
"cookies()",
|
|
3857
|
+
"headers()",
|
|
3858
|
+
"draftMode()"
|
|
3859
|
+
];
|
|
3860
|
+
async function validateNextjsComponents(themePath) {
|
|
3861
|
+
const issues = [];
|
|
3862
|
+
const { glob: glob6 } = await import('glob');
|
|
3863
|
+
const componentFiles = await glob6("components/**/*.{tsx,ts}", {
|
|
3864
|
+
cwd: themePath,
|
|
3865
|
+
ignore: ["**/node_modules/**"]
|
|
3866
|
+
});
|
|
3867
|
+
for (const relFile of componentFiles) {
|
|
3868
|
+
const absFile = path13__default.default.join(themePath, relFile);
|
|
3869
|
+
const content = fs8__default.default.readFileSync(absFile, "utf-8");
|
|
3870
|
+
const dir = path13__default.default.dirname(absFile);
|
|
3871
|
+
const hasSectionJson = fs8__default.default.existsSync(path13__default.default.join(dir, "section.json"));
|
|
3872
|
+
if (!hasSectionJson) continue;
|
|
3873
|
+
for (const api of SERVER_ONLY_APIS) {
|
|
3874
|
+
if (content.includes(`"${api}"`) || content.includes(`'${api}'`)) {
|
|
3875
|
+
issues.push({
|
|
3876
|
+
type: "error",
|
|
3877
|
+
file: relFile,
|
|
3878
|
+
message: `"${api}" is server-only and cannot be used in a OneX theme bundle. Remove this import or move data fetching to a client-side useEffect/useQuery.`
|
|
3879
|
+
});
|
|
3880
|
+
}
|
|
3881
|
+
if (content.includes(api.replace("()", "") + "(")) {
|
|
3882
|
+
issues.push({
|
|
3883
|
+
type: "error",
|
|
3884
|
+
file: relFile,
|
|
3885
|
+
message: `${api} is server-only and cannot be called in a browser bundle. Use useQuery or fetch() inside useEffect instead.`
|
|
3886
|
+
});
|
|
3887
|
+
}
|
|
3888
|
+
}
|
|
3889
|
+
const isAsyncComponent = /export\s+default\s+async\s+function/.test(content) || /export\s+default\s+async\s+\(/.test(content);
|
|
3890
|
+
if (isAsyncComponent) {
|
|
3891
|
+
const hasUseClient2 = content.includes('"use client"') || content.includes("'use client'");
|
|
3892
|
+
if (!hasUseClient2) {
|
|
3893
|
+
issues.push({
|
|
3894
|
+
type: "error",
|
|
3895
|
+
file: relFile,
|
|
3896
|
+
message: 'Async Server Components cannot be compiled to a browser bundle. Add "use client" at the top and convert data fetching to useQuery or useEffect.'
|
|
3897
|
+
});
|
|
3898
|
+
}
|
|
3899
|
+
}
|
|
3900
|
+
const usesHooks = /\buse[A-Z]\w+\s*\(/.test(content);
|
|
3901
|
+
const hasUseClient = content.includes('"use client"') || content.includes("'use client'");
|
|
3902
|
+
if (usesHooks && !hasUseClient) {
|
|
3903
|
+
issues.push({
|
|
3904
|
+
type: "warning",
|
|
3905
|
+
file: relFile,
|
|
3906
|
+
message: 'Component uses React hooks but is missing "use client" directive. Add "use client" at the top of the file.'
|
|
3907
|
+
});
|
|
3908
|
+
}
|
|
3909
|
+
}
|
|
3910
|
+
return issues;
|
|
3911
|
+
}
|
|
3700
3912
|
|
|
3701
3913
|
// src/commands/build.ts
|
|
3702
3914
|
init_logger();
|
|
3915
|
+
init_detect_nextjs();
|
|
3703
3916
|
async function buildCommand(options) {
|
|
3704
3917
|
logger.header("Build Theme");
|
|
3705
3918
|
let themePath;
|
|
@@ -3707,16 +3920,16 @@ async function buildCommand(options) {
|
|
|
3707
3920
|
if (options.theme) {
|
|
3708
3921
|
themeName = options.theme;
|
|
3709
3922
|
try {
|
|
3710
|
-
const workspaceThemePath =
|
|
3711
|
-
if (
|
|
3923
|
+
const workspaceThemePath = path13__default.default.join(getThemesDir(), themeName);
|
|
3924
|
+
if (fs8__default.default.existsSync(workspaceThemePath)) {
|
|
3712
3925
|
themePath = workspaceThemePath;
|
|
3713
3926
|
} else {
|
|
3714
|
-
themePath =
|
|
3927
|
+
themePath = path13__default.default.join(process.cwd(), themeName);
|
|
3715
3928
|
}
|
|
3716
3929
|
} catch {
|
|
3717
|
-
themePath =
|
|
3930
|
+
themePath = path13__default.default.join(process.cwd(), themeName);
|
|
3718
3931
|
}
|
|
3719
|
-
if (!
|
|
3932
|
+
if (!fs8__default.default.existsSync(themePath)) {
|
|
3720
3933
|
logger.error(`Theme "${themeName}" not found.`);
|
|
3721
3934
|
process.exit(1);
|
|
3722
3935
|
}
|
|
@@ -3724,11 +3937,14 @@ async function buildCommand(options) {
|
|
|
3724
3937
|
const isThemeDir2 = [
|
|
3725
3938
|
"theme.config.ts",
|
|
3726
3939
|
"bundle-entry.ts",
|
|
3727
|
-
"manifest.ts"
|
|
3728
|
-
|
|
3940
|
+
"manifest.ts",
|
|
3941
|
+
"next.config.ts",
|
|
3942
|
+
"next.config.js",
|
|
3943
|
+
"next.config.mjs"
|
|
3944
|
+
].some((f) => fs8__default.default.existsSync(path13__default.default.join(process.cwd(), f)));
|
|
3729
3945
|
if (isThemeDir2) {
|
|
3730
3946
|
themePath = process.cwd();
|
|
3731
|
-
themeName =
|
|
3947
|
+
themeName = path13__default.default.basename(themePath);
|
|
3732
3948
|
logger.info(`Building current theme: ${themeName}`);
|
|
3733
3949
|
} else {
|
|
3734
3950
|
logger.error(
|
|
@@ -3737,8 +3953,8 @@ async function buildCommand(options) {
|
|
|
3737
3953
|
process.exit(1);
|
|
3738
3954
|
}
|
|
3739
3955
|
}
|
|
3740
|
-
const packageJsonPath =
|
|
3741
|
-
const hasPkgJson =
|
|
3956
|
+
const packageJsonPath = path13__default.default.join(themePath, "package.json");
|
|
3957
|
+
const hasPkgJson = fs8__default.default.existsSync(packageJsonPath);
|
|
3742
3958
|
if (!hasPkgJson) {
|
|
3743
3959
|
logger.warning(
|
|
3744
3960
|
"No package.json found in theme. Skipping build (themes in monorepo are built via turbo)."
|
|
@@ -3753,30 +3969,42 @@ async function buildCommand(options) {
|
|
|
3753
3969
|
}
|
|
3754
3970
|
logger.newLine();
|
|
3755
3971
|
logger.section("Build Steps");
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
logger.
|
|
3768
|
-
|
|
3769
|
-
|
|
3972
|
+
const pkgJson = fs8__default.default.readJsonSync(packageJsonPath);
|
|
3973
|
+
if (pkgJson.scripts?.["type-check"]) {
|
|
3974
|
+
logger.startSpinner("Running type check...");
|
|
3975
|
+
const typeCheckSuccess = await runCommand("pnpm", ["type-check"], themePath);
|
|
3976
|
+
if (!typeCheckSuccess) {
|
|
3977
|
+
logger.stopSpinner(false, "Type check failed");
|
|
3978
|
+
logger.error("Fix type errors before building.");
|
|
3979
|
+
process.exit(1);
|
|
3980
|
+
}
|
|
3981
|
+
logger.stopSpinner(true, "Type check passed");
|
|
3982
|
+
} else {
|
|
3983
|
+
logger.info("Skipping type check (no type-check script in package.json)");
|
|
3984
|
+
}
|
|
3985
|
+
const isNextjsForLint = isNextjsProject(themePath);
|
|
3986
|
+
if (!isNextjsForLint && pkgJson.scripts?.lint) {
|
|
3987
|
+
logger.startSpinner("Running linter...");
|
|
3988
|
+
const lintSuccess = await runCommand("pnpm", ["lint"], themePath);
|
|
3989
|
+
if (!lintSuccess) {
|
|
3990
|
+
logger.stopSpinner(false, "Lint failed");
|
|
3991
|
+
logger.error("Fix lint errors before building.");
|
|
3992
|
+
process.exit(1);
|
|
3993
|
+
}
|
|
3994
|
+
logger.stopSpinner(true, "Lint passed");
|
|
3995
|
+
} else if (isNextjsForLint) {
|
|
3996
|
+
logger.info("Skipping lint (Next.js project compiled via esbuild)");
|
|
3997
|
+
} else {
|
|
3998
|
+
logger.info("Skipping lint (no lint script in package.json)");
|
|
3770
3999
|
}
|
|
3771
|
-
logger.stopSpinner(true, "Lint passed");
|
|
3772
|
-
const pkgJson = fs__default.default.readJsonSync(packageJsonPath);
|
|
3773
4000
|
const buildScript = pkgJson.scripts?.build || "";
|
|
3774
4001
|
const isRecursive = buildScript.includes("onexthm build") || buildScript.includes("onex build") || buildScript.includes("onex-cli build");
|
|
4002
|
+
const isNextjs = isNextjsProject(themePath);
|
|
3775
4003
|
logger.startSpinner(
|
|
3776
4004
|
options.watch ? "Building (watch mode)..." : "Building..."
|
|
3777
4005
|
);
|
|
3778
4006
|
let buildSuccess;
|
|
3779
|
-
if (isRecursive) {
|
|
4007
|
+
if (isRecursive || isNextjs) {
|
|
3780
4008
|
const { compileStandaloneTheme: compileStandaloneTheme2 } = await Promise.resolve().then(() => (init_compile_theme(), compile_theme_exports));
|
|
3781
4009
|
buildSuccess = await compileStandaloneTheme2(themePath, themeName);
|
|
3782
4010
|
} else {
|
|
@@ -3793,10 +4021,10 @@ async function buildCommand(options) {
|
|
|
3793
4021
|
logger.success("\u2713 Theme built successfully!");
|
|
3794
4022
|
logger.newLine();
|
|
3795
4023
|
logger.info(`Theme: ${themeName}`);
|
|
3796
|
-
const distPath =
|
|
3797
|
-
if (
|
|
3798
|
-
logger.log(`Output: ${
|
|
3799
|
-
const files =
|
|
4024
|
+
const distPath = path13__default.default.join(themePath, "dist");
|
|
4025
|
+
if (fs8__default.default.existsSync(distPath)) {
|
|
4026
|
+
logger.log(`Output: ${path13__default.default.relative(process.cwd(), distPath)}`);
|
|
4027
|
+
const files = fs8__default.default.readdirSync(distPath);
|
|
3800
4028
|
logger.log(`Files: ${files.length}`);
|
|
3801
4029
|
}
|
|
3802
4030
|
}
|
|
@@ -3851,8 +4079,8 @@ async function packageCommand(options) {
|
|
|
3851
4079
|
let themeName;
|
|
3852
4080
|
if (options.theme) {
|
|
3853
4081
|
themeName = options.theme;
|
|
3854
|
-
themePath =
|
|
3855
|
-
if (!
|
|
4082
|
+
themePath = path13__default.default.join(getThemesDir(), themeName);
|
|
4083
|
+
if (!fs8__default.default.existsSync(themePath)) {
|
|
3856
4084
|
logger.error(`Theme "${themeName}" not found.`);
|
|
3857
4085
|
process.exit(1);
|
|
3858
4086
|
}
|
|
@@ -3860,11 +4088,14 @@ async function packageCommand(options) {
|
|
|
3860
4088
|
const isThemeDir2 = [
|
|
3861
4089
|
"theme.config.ts",
|
|
3862
4090
|
"bundle-entry.ts",
|
|
3863
|
-
"manifest.ts"
|
|
3864
|
-
|
|
4091
|
+
"manifest.ts",
|
|
4092
|
+
"next.config.ts",
|
|
4093
|
+
"next.config.js",
|
|
4094
|
+
"next.config.mjs"
|
|
4095
|
+
].some((f) => fs8__default.default.existsSync(path13__default.default.join(process.cwd(), f)));
|
|
3865
4096
|
if (isThemeDir2) {
|
|
3866
4097
|
themePath = process.cwd();
|
|
3867
|
-
themeName =
|
|
4098
|
+
themeName = path13__default.default.basename(themePath);
|
|
3868
4099
|
logger.info(`Packaging current theme: ${themeName}`);
|
|
3869
4100
|
} else {
|
|
3870
4101
|
logger.error(
|
|
@@ -3873,22 +4104,19 @@ async function packageCommand(options) {
|
|
|
3873
4104
|
process.exit(1);
|
|
3874
4105
|
}
|
|
3875
4106
|
}
|
|
3876
|
-
const packageJsonPath =
|
|
4107
|
+
const packageJsonPath = path13__default.default.join(themePath, "package.json");
|
|
3877
4108
|
let version2 = "1.0.0";
|
|
3878
|
-
if (
|
|
3879
|
-
const packageJson = await
|
|
4109
|
+
if (fs8__default.default.existsSync(packageJsonPath)) {
|
|
4110
|
+
const packageJson = await fs8__default.default.readJson(packageJsonPath);
|
|
3880
4111
|
version2 = packageJson.version || "1.0.0";
|
|
3881
4112
|
}
|
|
3882
4113
|
logger.newLine();
|
|
3883
4114
|
logger.info(`Theme: ${themeName}`);
|
|
3884
4115
|
logger.info(`Version: ${version2}`);
|
|
3885
4116
|
logger.newLine();
|
|
3886
|
-
const
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
themeName,
|
|
3890
|
-
"dist"
|
|
3891
|
-
);
|
|
4117
|
+
const standaloneDistPath = path13__default.default.join(themePath, "dist");
|
|
4118
|
+
const monorepoDistPath = path13__default.default.join(process.cwd(), "themes", themeName, "dist");
|
|
4119
|
+
const compiledThemePath = fs8__default.default.existsSync(standaloneDistPath) ? standaloneDistPath : monorepoDistPath;
|
|
3892
4120
|
if (!options.skipBuild) {
|
|
3893
4121
|
logger.section("Step 1: Compile Theme");
|
|
3894
4122
|
logger.startSpinner("Compiling theme with esbuild...");
|
|
@@ -3909,7 +4137,7 @@ async function packageCommand(options) {
|
|
|
3909
4137
|
} else {
|
|
3910
4138
|
logger.info("Skipping build (--skip-build flag)");
|
|
3911
4139
|
}
|
|
3912
|
-
if (!
|
|
4140
|
+
if (!fs8__default.default.existsSync(compiledThemePath)) {
|
|
3913
4141
|
logger.error(`Compiled theme not found at: ${compiledThemePath}`);
|
|
3914
4142
|
logger.info("Run without --skip-build to compile first.");
|
|
3915
4143
|
process.exit(1);
|
|
@@ -3917,25 +4145,25 @@ async function packageCommand(options) {
|
|
|
3917
4145
|
logger.newLine();
|
|
3918
4146
|
logger.section("Step 2: Create Package");
|
|
3919
4147
|
const packageName = options.name || `${themeName}-${version2}`;
|
|
3920
|
-
const outputDir = options.output ||
|
|
3921
|
-
const outputPath =
|
|
3922
|
-
await
|
|
4148
|
+
const outputDir = options.output || path13__default.default.join(process.cwd(), "dist");
|
|
4149
|
+
const outputPath = path13__default.default.join(outputDir, `${packageName}.zip`);
|
|
4150
|
+
await fs8__default.default.ensureDir(outputDir);
|
|
3923
4151
|
logger.startSpinner("Creating zip archive...");
|
|
3924
4152
|
try {
|
|
3925
4153
|
await createZipArchive(compiledThemePath, outputPath);
|
|
3926
4154
|
logger.stopSpinner(true, "Package created");
|
|
3927
|
-
const stats = await
|
|
4155
|
+
const stats = await fs8__default.default.stat(outputPath);
|
|
3928
4156
|
const sizeMB = (stats.size / 1024 / 1024).toFixed(2);
|
|
3929
4157
|
logger.newLine();
|
|
3930
4158
|
logger.success("\u2713 Theme packaged successfully!");
|
|
3931
4159
|
logger.newLine();
|
|
3932
4160
|
logger.info(`Package: ${packageName}.zip`);
|
|
3933
4161
|
logger.log(`Size: ${sizeMB} MB`);
|
|
3934
|
-
logger.log(`Location: ${
|
|
4162
|
+
logger.log(`Location: ${path13__default.default.relative(process.cwd(), outputPath)}`);
|
|
3935
4163
|
logger.newLine();
|
|
3936
4164
|
logger.section("Next steps:");
|
|
3937
4165
|
logger.log(
|
|
3938
|
-
` onexthm deploy --package ${
|
|
4166
|
+
` onexthm deploy --package ${path13__default.default.relative(process.cwd(), outputPath)}`
|
|
3939
4167
|
);
|
|
3940
4168
|
} catch (error) {
|
|
3941
4169
|
logger.stopSpinner(false, "Failed to create package");
|
|
@@ -3969,7 +4197,7 @@ function runCommand2(command, args) {
|
|
|
3969
4197
|
}
|
|
3970
4198
|
async function createZipArchive(compiledThemePath, outputPath) {
|
|
3971
4199
|
return new Promise((resolve, reject) => {
|
|
3972
|
-
const output =
|
|
4200
|
+
const output = fs8__default.default.createWriteStream(outputPath);
|
|
3973
4201
|
const archive = archiver__default.default("zip", {
|
|
3974
4202
|
zlib: { level: 9 }
|
|
3975
4203
|
// Maximum compression
|
|
@@ -3993,14 +4221,14 @@ async function deployCommand(options) {
|
|
|
3993
4221
|
ensureOneXProject();
|
|
3994
4222
|
let packagePath;
|
|
3995
4223
|
if (options.package) {
|
|
3996
|
-
packagePath =
|
|
4224
|
+
packagePath = path13__default.default.resolve(options.package);
|
|
3997
4225
|
} else if (options.theme) {
|
|
3998
|
-
const distDir =
|
|
3999
|
-
if (!
|
|
4226
|
+
const distDir = path13__default.default.join(process.cwd(), "dist");
|
|
4227
|
+
if (!fs8__default.default.existsSync(distDir)) {
|
|
4000
4228
|
logger.error("No dist/ directory found. Run 'onexthm package' first.");
|
|
4001
4229
|
process.exit(1);
|
|
4002
4230
|
}
|
|
4003
|
-
const files =
|
|
4231
|
+
const files = fs8__default.default.readdirSync(distDir);
|
|
4004
4232
|
const packageFiles = files.filter(
|
|
4005
4233
|
(f) => f.startsWith(options.theme) && f.endsWith(".zip")
|
|
4006
4234
|
);
|
|
@@ -4010,7 +4238,7 @@ async function deployCommand(options) {
|
|
|
4010
4238
|
process.exit(1);
|
|
4011
4239
|
}
|
|
4012
4240
|
packageFiles.sort().reverse();
|
|
4013
|
-
packagePath =
|
|
4241
|
+
packagePath = path13__default.default.join(distDir, packageFiles[0]);
|
|
4014
4242
|
} else {
|
|
4015
4243
|
logger.error("Either --package or --theme must be specified.");
|
|
4016
4244
|
logger.info("Examples:");
|
|
@@ -4018,17 +4246,17 @@ async function deployCommand(options) {
|
|
|
4018
4246
|
logger.log(" onexthm deploy --theme tinan");
|
|
4019
4247
|
process.exit(1);
|
|
4020
4248
|
}
|
|
4021
|
-
if (!
|
|
4249
|
+
if (!fs8__default.default.existsSync(packagePath)) {
|
|
4022
4250
|
logger.error(`Package not found: ${packagePath}`);
|
|
4023
4251
|
process.exit(1);
|
|
4024
4252
|
}
|
|
4025
|
-
const stats = await
|
|
4253
|
+
const stats = await fs8__default.default.stat(packagePath);
|
|
4026
4254
|
const sizeMB = (stats.size / 1024 / 1024).toFixed(2);
|
|
4027
|
-
const fileName =
|
|
4255
|
+
const fileName = path13__default.default.basename(packagePath);
|
|
4028
4256
|
logger.newLine();
|
|
4029
4257
|
logger.info(`Package: ${fileName}`);
|
|
4030
4258
|
logger.log(`Size: ${sizeMB} MB`);
|
|
4031
|
-
logger.log(`Path: ${
|
|
4259
|
+
logger.log(`Path: ${path13__default.default.relative(process.cwd(), packagePath)}`);
|
|
4032
4260
|
logger.newLine();
|
|
4033
4261
|
const apiUrl = options.apiUrl || process.env.ONEX_API_URL || "http://localhost:3001";
|
|
4034
4262
|
const uploadEndpoint = `${apiUrl}/website-api/themes/upload`;
|
|
@@ -4038,7 +4266,7 @@ async function deployCommand(options) {
|
|
|
4038
4266
|
logger.startSpinner("Uploading theme package...");
|
|
4039
4267
|
try {
|
|
4040
4268
|
const formData = new FormData__default.default();
|
|
4041
|
-
formData.append("theme",
|
|
4269
|
+
formData.append("theme", fs8__default.default.createReadStream(packagePath), {
|
|
4042
4270
|
filename: fileName,
|
|
4043
4271
|
contentType: "application/zip"
|
|
4044
4272
|
});
|
|
@@ -4185,24 +4413,24 @@ async function downloadBundleZip(apiUrl, themeId, version2) {
|
|
|
4185
4413
|
async function createCompatibilityFiles(outputDir, manifest) {
|
|
4186
4414
|
const entryFile = manifest.output?.entry || "bundle-entry.js";
|
|
4187
4415
|
if (entryFile !== "bundle-entry.js" && entryFile.startsWith("bundle-entry-")) {
|
|
4188
|
-
const hashedPath =
|
|
4189
|
-
const stablePath =
|
|
4190
|
-
if (await
|
|
4191
|
-
await
|
|
4416
|
+
const hashedPath = path13__default.default.join(outputDir, entryFile);
|
|
4417
|
+
const stablePath = path13__default.default.join(outputDir, "bundle-entry.js");
|
|
4418
|
+
if (await fs8__default.default.pathExists(hashedPath)) {
|
|
4419
|
+
await fs8__default.default.copy(hashedPath, stablePath);
|
|
4192
4420
|
const mapPath = hashedPath + ".map";
|
|
4193
|
-
if (await
|
|
4194
|
-
await
|
|
4421
|
+
if (await fs8__default.default.pathExists(mapPath)) {
|
|
4422
|
+
await fs8__default.default.copy(mapPath, stablePath + ".map");
|
|
4195
4423
|
}
|
|
4196
4424
|
}
|
|
4197
4425
|
}
|
|
4198
|
-
const sectionsRegistryPath =
|
|
4426
|
+
const sectionsRegistryPath = path13__default.default.join(outputDir, "sections-registry.js");
|
|
4199
4427
|
const content = `// Re-export all sections from bundle-entry
|
|
4200
4428
|
// This file exists to maintain compatibility with the import path
|
|
4201
4429
|
export * from './bundle-entry.js';
|
|
4202
4430
|
`;
|
|
4203
|
-
await
|
|
4204
|
-
const pkgJsonPath =
|
|
4205
|
-
await
|
|
4431
|
+
await fs8__default.default.writeFile(sectionsRegistryPath, content, "utf-8");
|
|
4432
|
+
const pkgJsonPath = path13__default.default.join(outputDir, "package.json");
|
|
4433
|
+
await fs8__default.default.writeFile(pkgJsonPath, '{\n "type": "module"\n}\n', "utf-8");
|
|
4206
4434
|
}
|
|
4207
4435
|
function showDownloadFailureHelp(themeId, apiUrl) {
|
|
4208
4436
|
console.log();
|
|
@@ -4242,7 +4470,7 @@ function showDownloadFailureHelp(themeId, apiUrl) {
|
|
|
4242
4470
|
}
|
|
4243
4471
|
async function downloadCommand(options) {
|
|
4244
4472
|
logger.header("Download Theme");
|
|
4245
|
-
const env = options.env
|
|
4473
|
+
const env = options.env;
|
|
4246
4474
|
const apiUrl = getApiUrl(env);
|
|
4247
4475
|
logger.info(`Environment: ${env} (${apiUrl})`);
|
|
4248
4476
|
const spinner = ora__default.default("Initializing download...").start();
|
|
@@ -4294,14 +4522,14 @@ async function downloadCommand(options) {
|
|
|
4294
4522
|
const sizeMB = (zipBuffer.length / 1024 / 1024).toFixed(2);
|
|
4295
4523
|
spinner.succeed(`Downloaded bundle.zip (${sizeMB} MB)`);
|
|
4296
4524
|
spinner.start("Extracting bundle...");
|
|
4297
|
-
await
|
|
4298
|
-
await
|
|
4525
|
+
await fs8__default.default.remove(outputDir);
|
|
4526
|
+
await fs8__default.default.ensureDir(outputDir);
|
|
4299
4527
|
const zip = new AdmZip__default.default(zipBuffer);
|
|
4300
4528
|
zip.extractAllTo(outputDir, true);
|
|
4301
4529
|
const entries = zip.getEntries().filter((e) => !e.isDirectory);
|
|
4302
4530
|
spinner.succeed(`Extracted ${entries.length} files to ${outputDir}`);
|
|
4303
|
-
const manifestPath =
|
|
4304
|
-
const manifest = await
|
|
4531
|
+
const manifestPath = path13__default.default.join(outputDir, "manifest.json");
|
|
4532
|
+
const manifest = await fs8__default.default.readJson(manifestPath);
|
|
4305
4533
|
await createCompatibilityFiles(outputDir, manifest);
|
|
4306
4534
|
console.log();
|
|
4307
4535
|
logger.success(chalk4__default.default.green.bold("Theme downloaded successfully!"));
|
|
@@ -4421,9 +4649,9 @@ async function renameTheme(themeDir, oldName, newName) {
|
|
|
4421
4649
|
const oldPrefix = `${oldName}-`;
|
|
4422
4650
|
const newPrefix = `${newName}-`;
|
|
4423
4651
|
const newDisplayName = newName.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
4424
|
-
const pkgPath =
|
|
4425
|
-
if (await
|
|
4426
|
-
const pkg = await
|
|
4652
|
+
const pkgPath = path13__default.default.join(themeDir, "package.json");
|
|
4653
|
+
if (await fs8__default.default.pathExists(pkgPath)) {
|
|
4654
|
+
const pkg = await fs8__default.default.readJson(pkgPath);
|
|
4427
4655
|
pkg.name = `@onex-themes/${newName}`;
|
|
4428
4656
|
if (pkg.description) {
|
|
4429
4657
|
pkg.description = pkg.description.replace(
|
|
@@ -4435,33 +4663,33 @@ async function renameTheme(themeDir, oldName, newName) {
|
|
|
4435
4663
|
if (pkg.devDependencies?.["@onexapis/cli"]) {
|
|
4436
4664
|
delete pkg.devDependencies["@onexapis/cli"];
|
|
4437
4665
|
}
|
|
4438
|
-
await
|
|
4666
|
+
await fs8__default.default.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
4439
4667
|
}
|
|
4440
|
-
const configPath =
|
|
4441
|
-
if (await
|
|
4442
|
-
let content = await
|
|
4668
|
+
const configPath = path13__default.default.join(themeDir, "theme.config.ts");
|
|
4669
|
+
if (await fs8__default.default.pathExists(configPath)) {
|
|
4670
|
+
let content = await fs8__default.default.readFile(configPath, "utf-8");
|
|
4443
4671
|
content = content.replace(/id:\s*"[^"]*"/, `id: "${newName}"`);
|
|
4444
4672
|
content = content.replace(
|
|
4445
4673
|
/name:\s*"[^"]*Theme"/,
|
|
4446
4674
|
`name: "${newDisplayName} Theme"`
|
|
4447
4675
|
);
|
|
4448
|
-
await
|
|
4676
|
+
await fs8__default.default.writeFile(configPath, content);
|
|
4449
4677
|
}
|
|
4450
|
-
const layoutPath =
|
|
4451
|
-
if (await
|
|
4452
|
-
let content = await
|
|
4678
|
+
const layoutPath = path13__default.default.join(themeDir, "theme.layout.ts");
|
|
4679
|
+
if (await fs8__default.default.pathExists(layoutPath)) {
|
|
4680
|
+
let content = await fs8__default.default.readFile(layoutPath, "utf-8");
|
|
4453
4681
|
content = content.replace(/id:\s*"[^"]*"/, `id: "${newName}"`);
|
|
4454
4682
|
content = content.replace(
|
|
4455
4683
|
/name:\s*"[^"]*Theme"/,
|
|
4456
4684
|
`name: "${newDisplayName} Theme"`
|
|
4457
4685
|
);
|
|
4458
|
-
await
|
|
4686
|
+
await fs8__default.default.writeFile(layoutPath, content);
|
|
4459
4687
|
}
|
|
4460
4688
|
const oldDisplayName = oldName.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
4461
4689
|
const tsFiles = await glob.glob("**/*.ts", { cwd: themeDir, nodir: true });
|
|
4462
4690
|
for (const file of tsFiles) {
|
|
4463
|
-
const filePath =
|
|
4464
|
-
let content = await
|
|
4691
|
+
const filePath = path13__default.default.join(themeDir, file);
|
|
4692
|
+
let content = await fs8__default.default.readFile(filePath, "utf-8");
|
|
4465
4693
|
const original = content;
|
|
4466
4694
|
content = content.replace(
|
|
4467
4695
|
new RegExp(`"${oldPrefix}`, "g"),
|
|
@@ -4476,13 +4704,13 @@ async function renameTheme(themeDir, oldName, newName) {
|
|
|
4476
4704
|
`${newDisplayName} Theme`
|
|
4477
4705
|
);
|
|
4478
4706
|
if (content !== original) {
|
|
4479
|
-
await
|
|
4707
|
+
await fs8__default.default.writeFile(filePath, content);
|
|
4480
4708
|
}
|
|
4481
4709
|
}
|
|
4482
4710
|
}
|
|
4483
4711
|
async function cloneCommand(themeName, options) {
|
|
4484
4712
|
logger.header("Clone Theme Source");
|
|
4485
|
-
const env = options.env
|
|
4713
|
+
const env = options.env;
|
|
4486
4714
|
const apiUrl = getApiUrl(env);
|
|
4487
4715
|
logger.info(`Environment: ${env} (${apiUrl})`);
|
|
4488
4716
|
if (options.bucket) {
|
|
@@ -4503,8 +4731,8 @@ async function cloneCommand(themeName, options) {
|
|
|
4503
4731
|
}
|
|
4504
4732
|
const spinner = ora__default.default("Initializing clone...").start();
|
|
4505
4733
|
try {
|
|
4506
|
-
const outputDir = options.output ||
|
|
4507
|
-
if (await
|
|
4734
|
+
const outputDir = options.output || path13__default.default.resolve(process.cwd(), newName);
|
|
4735
|
+
if (await fs8__default.default.pathExists(outputDir)) {
|
|
4508
4736
|
spinner.fail(chalk4__default.default.red(`Directory already exists: ${outputDir}`));
|
|
4509
4737
|
logger.info(
|
|
4510
4738
|
chalk4__default.default.gray(
|
|
@@ -4537,7 +4765,7 @@ async function cloneCommand(themeName, options) {
|
|
|
4537
4765
|
const sizeMB = (zipBuffer.length / 1024 / 1024).toFixed(2);
|
|
4538
4766
|
spinner.succeed(`Downloaded source.zip (${sizeMB} MB)`);
|
|
4539
4767
|
spinner.start(`Extracting to ${outputDir}...`);
|
|
4540
|
-
await
|
|
4768
|
+
await fs8__default.default.ensureDir(outputDir);
|
|
4541
4769
|
const zip = new AdmZip__default.default(zipBuffer);
|
|
4542
4770
|
zip.extractAllTo(outputDir, true);
|
|
4543
4771
|
const entries = zip.getEntries().filter((e) => !e.isDirectory);
|
|
@@ -4549,9 +4777,9 @@ async function cloneCommand(themeName, options) {
|
|
|
4549
4777
|
spinner.succeed(
|
|
4550
4778
|
`Renamed theme: ${chalk4__default.default.gray(themeName)} \u2192 ${chalk4__default.default.cyan(newName)}`
|
|
4551
4779
|
);
|
|
4552
|
-
const envExamplePath =
|
|
4553
|
-
if (!await
|
|
4554
|
-
await
|
|
4780
|
+
const envExamplePath = path13__default.default.join(outputDir, ".env.example");
|
|
4781
|
+
if (!await fs8__default.default.pathExists(envExamplePath)) {
|
|
4782
|
+
await fs8__default.default.writeFile(
|
|
4555
4783
|
envExamplePath,
|
|
4556
4784
|
[
|
|
4557
4785
|
"# API Configuration (enables real data in preview)",
|
|
@@ -4562,8 +4790,8 @@ async function cloneCommand(themeName, options) {
|
|
|
4562
4790
|
].join("\n")
|
|
4563
4791
|
);
|
|
4564
4792
|
}
|
|
4565
|
-
const mcpJsonPath =
|
|
4566
|
-
if (await
|
|
4793
|
+
const mcpJsonPath = path13__default.default.join(outputDir, ".mcp.json");
|
|
4794
|
+
if (await fs8__default.default.pathExists(mcpJsonPath)) {
|
|
4567
4795
|
const { default: inquirerMod } = await import('inquirer');
|
|
4568
4796
|
const { figmaApiKey } = await inquirerMod.prompt([
|
|
4569
4797
|
{
|
|
@@ -4572,7 +4800,7 @@ async function cloneCommand(themeName, options) {
|
|
|
4572
4800
|
message: "Figma API Key (optional, for Figma-to-code MCP \u2014 press Enter to skip):"
|
|
4573
4801
|
}
|
|
4574
4802
|
]);
|
|
4575
|
-
let mcpContent = await
|
|
4803
|
+
let mcpContent = await fs8__default.default.readFile(mcpJsonPath, "utf-8");
|
|
4576
4804
|
if (figmaApiKey) {
|
|
4577
4805
|
mcpContent = mcpContent.replace("__FIGMA_API_KEY__", figmaApiKey);
|
|
4578
4806
|
} else {
|
|
@@ -4583,11 +4811,11 @@ async function cloneCommand(themeName, options) {
|
|
|
4583
4811
|
} catch {
|
|
4584
4812
|
}
|
|
4585
4813
|
}
|
|
4586
|
-
await
|
|
4814
|
+
await fs8__default.default.writeFile(mcpJsonPath, mcpContent, "utf-8");
|
|
4587
4815
|
}
|
|
4588
4816
|
if (options.install !== false) {
|
|
4589
|
-
const hasPkgJson = await
|
|
4590
|
-
|
|
4817
|
+
const hasPkgJson = await fs8__default.default.pathExists(
|
|
4818
|
+
path13__default.default.join(outputDir, "package.json")
|
|
4591
4819
|
);
|
|
4592
4820
|
if (hasPkgJson) {
|
|
4593
4821
|
spinner.start("Installing dependencies...");
|
|
@@ -4615,7 +4843,7 @@ async function cloneCommand(themeName, options) {
|
|
|
4615
4843
|
console.log(chalk4__default.default.cyan(" Files: ") + chalk4__default.default.white(entries.length));
|
|
4616
4844
|
console.log();
|
|
4617
4845
|
console.log(chalk4__default.default.cyan("Next steps:"));
|
|
4618
|
-
console.log(chalk4__default.default.gray(` cd ${
|
|
4846
|
+
console.log(chalk4__default.default.gray(` cd ${path13__default.default.relative(process.cwd(), outputDir)}`));
|
|
4619
4847
|
console.log(
|
|
4620
4848
|
chalk4__default.default.gray(" cp .env.example .env # then add your Company ID")
|
|
4621
4849
|
);
|
|
@@ -4642,16 +4870,16 @@ async function devCommand(options) {
|
|
|
4642
4870
|
if (options.theme) {
|
|
4643
4871
|
themeName = options.theme;
|
|
4644
4872
|
try {
|
|
4645
|
-
const workspaceThemePath =
|
|
4646
|
-
if (
|
|
4873
|
+
const workspaceThemePath = path13__default.default.join(getThemesDir(), themeName);
|
|
4874
|
+
if (fs8__default.default.existsSync(workspaceThemePath)) {
|
|
4647
4875
|
themePath = workspaceThemePath;
|
|
4648
4876
|
} else {
|
|
4649
|
-
themePath =
|
|
4877
|
+
themePath = path13__default.default.join(process.cwd(), themeName);
|
|
4650
4878
|
}
|
|
4651
4879
|
} catch {
|
|
4652
|
-
themePath =
|
|
4880
|
+
themePath = path13__default.default.join(process.cwd(), themeName);
|
|
4653
4881
|
}
|
|
4654
|
-
if (!
|
|
4882
|
+
if (!fs8__default.default.existsSync(themePath)) {
|
|
4655
4883
|
logger.error(`Theme "${themeName}" not found.`);
|
|
4656
4884
|
process.exit(1);
|
|
4657
4885
|
}
|
|
@@ -4659,11 +4887,14 @@ async function devCommand(options) {
|
|
|
4659
4887
|
const isThemeDir2 = [
|
|
4660
4888
|
"theme.config.ts",
|
|
4661
4889
|
"bundle-entry.ts",
|
|
4662
|
-
"manifest.ts"
|
|
4663
|
-
|
|
4890
|
+
"manifest.ts",
|
|
4891
|
+
"next.config.ts",
|
|
4892
|
+
"next.config.js",
|
|
4893
|
+
"next.config.mjs"
|
|
4894
|
+
].some((f) => fs8__default.default.existsSync(path13__default.default.join(process.cwd(), f)));
|
|
4664
4895
|
if (isThemeDir2) {
|
|
4665
4896
|
themePath = process.cwd();
|
|
4666
|
-
themeName =
|
|
4897
|
+
themeName = path13__default.default.basename(themePath);
|
|
4667
4898
|
} else {
|
|
4668
4899
|
logger.error(
|
|
4669
4900
|
"Not in a theme directory and no --theme specified. Run from theme root or use --theme flag."
|
|
@@ -4732,9 +4963,9 @@ async function devCommand(options) {
|
|
|
4732
4963
|
watcher.close();
|
|
4733
4964
|
await context2.dispose();
|
|
4734
4965
|
server.close();
|
|
4735
|
-
const shimPath =
|
|
4966
|
+
const shimPath = path13__default.default.join(outputDir, ".process-shim.js");
|
|
4736
4967
|
try {
|
|
4737
|
-
await
|
|
4968
|
+
await fs11__default.default.unlink(shimPath);
|
|
4738
4969
|
} catch {
|
|
4739
4970
|
}
|
|
4740
4971
|
process.exit(0);
|
|
@@ -4743,8 +4974,8 @@ async function devCommand(options) {
|
|
|
4743
4974
|
|
|
4744
4975
|
// src/commands/config.ts
|
|
4745
4976
|
init_logger();
|
|
4746
|
-
var CONFIG_DIR =
|
|
4747
|
-
var CONFIG_FILE =
|
|
4977
|
+
var CONFIG_DIR = path13__default.default.join(os__default.default.homedir(), ".onexthm");
|
|
4978
|
+
var CONFIG_FILE = path13__default.default.join(CONFIG_DIR, ".env");
|
|
4748
4979
|
var CONFIG_ENTRIES = [
|
|
4749
4980
|
{
|
|
4750
4981
|
key: "AWS_ACCESS_KEY_ID",
|
|
@@ -4830,7 +5061,7 @@ async function configCommand() {
|
|
|
4830
5061
|
logger.header("OneX CLI Configuration");
|
|
4831
5062
|
let existing = {};
|
|
4832
5063
|
try {
|
|
4833
|
-
const content = await
|
|
5064
|
+
const content = await fs8__default.default.readFile(CONFIG_FILE, "utf-8");
|
|
4834
5065
|
existing = parseEnvFile(content);
|
|
4835
5066
|
logger.info(`Existing config found at: ${CONFIG_FILE}`);
|
|
4836
5067
|
logger.newLine();
|
|
@@ -4866,8 +5097,8 @@ async function configCommand() {
|
|
|
4866
5097
|
for (const key of Object.keys(merged)) {
|
|
4867
5098
|
if (!merged[key]) delete merged[key];
|
|
4868
5099
|
}
|
|
4869
|
-
await
|
|
4870
|
-
await
|
|
5100
|
+
await fs8__default.default.ensureDir(CONFIG_DIR);
|
|
5101
|
+
await fs8__default.default.writeFile(CONFIG_FILE, serializeEnv(merged));
|
|
4871
5102
|
logger.newLine();
|
|
4872
5103
|
logger.success(`Config saved to: ${CONFIG_FILE}`);
|
|
4873
5104
|
logger.newLine();
|
|
@@ -4886,8 +5117,8 @@ async function configCommand() {
|
|
|
4886
5117
|
|
|
4887
5118
|
// src/commands/login.ts
|
|
4888
5119
|
init_logger();
|
|
4889
|
-
async function loginCommand(options
|
|
4890
|
-
const env = options.env
|
|
5120
|
+
async function loginCommand(options) {
|
|
5121
|
+
const env = options.env;
|
|
4891
5122
|
const apiUrl = getApiUrl(env);
|
|
4892
5123
|
logger.header("OneX Theme Developer Login");
|
|
4893
5124
|
logger.info(`Environment: ${env} (${apiUrl})`);
|
|
@@ -4976,8 +5207,8 @@ async function loginCommand(options = {}) {
|
|
|
4976
5207
|
|
|
4977
5208
|
// src/commands/logout.ts
|
|
4978
5209
|
init_logger();
|
|
4979
|
-
async function logoutCommand(options
|
|
4980
|
-
const env = options.env
|
|
5210
|
+
async function logoutCommand(options) {
|
|
5211
|
+
const env = options.env;
|
|
4981
5212
|
const tokens = loadAuthTokens(env);
|
|
4982
5213
|
if (!tokens) {
|
|
4983
5214
|
logger.info(`Not logged in to ${env} environment.`);
|
|
@@ -4989,8 +5220,8 @@ async function logoutCommand(options = {}) {
|
|
|
4989
5220
|
|
|
4990
5221
|
// src/commands/whoami.ts
|
|
4991
5222
|
init_logger();
|
|
4992
|
-
async function whoamiCommand(options
|
|
4993
|
-
const env = options.env
|
|
5223
|
+
async function whoamiCommand(options) {
|
|
5224
|
+
const env = options.env;
|
|
4994
5225
|
const tokens = loadAuthTokens(env);
|
|
4995
5226
|
if (!tokens) {
|
|
4996
5227
|
logger.error(
|
|
@@ -5243,11 +5474,11 @@ function diffFieldList(prior, current, pathPrefix, out) {
|
|
|
5243
5474
|
}
|
|
5244
5475
|
}
|
|
5245
5476
|
}
|
|
5246
|
-
function diffFieldPair(p, c,
|
|
5477
|
+
function diffFieldPair(p, c, path25, out) {
|
|
5247
5478
|
if (p.type !== c.type) {
|
|
5248
5479
|
out.push({
|
|
5249
5480
|
kind: "breaking",
|
|
5250
|
-
path:
|
|
5481
|
+
path: path25,
|
|
5251
5482
|
detail: `Type changed (${p.type} \u2192 ${c.type}). Saved values may misrender.`
|
|
5252
5483
|
});
|
|
5253
5484
|
return;
|
|
@@ -5255,7 +5486,7 @@ function diffFieldPair(p, c, path23, out) {
|
|
|
5255
5486
|
if (p.required !== true && c.required === true) {
|
|
5256
5487
|
out.push({
|
|
5257
5488
|
kind: "breaking",
|
|
5258
|
-
path:
|
|
5489
|
+
path: path25,
|
|
5259
5490
|
detail: "Field became required. Existing empty instances now invalid."
|
|
5260
5491
|
});
|
|
5261
5492
|
}
|
|
@@ -5263,7 +5494,7 @@ function diffFieldPair(p, c, path23, out) {
|
|
|
5263
5494
|
if ((c.maxLength ?? Infinity) < (p.maxLength ?? Infinity)) {
|
|
5264
5495
|
out.push({
|
|
5265
5496
|
kind: "breaking",
|
|
5266
|
-
path:
|
|
5497
|
+
path: path25,
|
|
5267
5498
|
detail: `maxLength tightened (${p.maxLength ?? "\u221E"} \u2192 ${c.maxLength}).`
|
|
5268
5499
|
});
|
|
5269
5500
|
}
|
|
@@ -5272,7 +5503,7 @@ function diffFieldPair(p, c, path23, out) {
|
|
|
5272
5503
|
if ((c.min ?? -Infinity) > (p.min ?? -Infinity)) {
|
|
5273
5504
|
out.push({
|
|
5274
5505
|
kind: "breaking",
|
|
5275
|
-
path:
|
|
5506
|
+
path: path25,
|
|
5276
5507
|
detail: `min raised (${p.min ?? "-\u221E"} \u2192 ${c.min}).`
|
|
5277
5508
|
});
|
|
5278
5509
|
}
|
|
@@ -5281,7 +5512,7 @@ function diffFieldPair(p, c, path23, out) {
|
|
|
5281
5512
|
if ((c.max ?? Infinity) < (p.max ?? Infinity)) {
|
|
5282
5513
|
out.push({
|
|
5283
5514
|
kind: "breaking",
|
|
5284
|
-
path:
|
|
5515
|
+
path: path25,
|
|
5285
5516
|
detail: `max lowered (${p.max ?? "\u221E"} \u2192 ${c.max}).`
|
|
5286
5517
|
});
|
|
5287
5518
|
}
|
|
@@ -5294,14 +5525,14 @@ function diffFieldPair(p, c, path23, out) {
|
|
|
5294
5525
|
if (removed.length > 0) {
|
|
5295
5526
|
out.push({
|
|
5296
5527
|
kind: "breaking",
|
|
5297
|
-
path:
|
|
5528
|
+
path: path25,
|
|
5298
5529
|
detail: `Option(s) removed: ${removed.join(", ")}. Existing saved values may be orphaned.`
|
|
5299
5530
|
});
|
|
5300
5531
|
}
|
|
5301
5532
|
if (added.length > 0) {
|
|
5302
5533
|
out.push({
|
|
5303
5534
|
kind: "additive",
|
|
5304
|
-
path:
|
|
5535
|
+
path: path25,
|
|
5305
5536
|
detail: `Option(s) added: ${added.join(", ")}.`
|
|
5306
5537
|
});
|
|
5307
5538
|
}
|
|
@@ -5309,7 +5540,7 @@ function diffFieldPair(p, c, path23, out) {
|
|
|
5309
5540
|
if (!deepEqual(p.default, c.default)) {
|
|
5310
5541
|
out.push({
|
|
5311
5542
|
kind: "defaults-only",
|
|
5312
|
-
path:
|
|
5543
|
+
path: path25,
|
|
5313
5544
|
detail: `Default changed: ${JSON.stringify(p.default)} \u2192 ${JSON.stringify(c.default)}.`
|
|
5314
5545
|
});
|
|
5315
5546
|
}
|
|
@@ -5367,7 +5598,7 @@ function deepEqual(a, b) {
|
|
|
5367
5598
|
|
|
5368
5599
|
// src/commands/publish.ts
|
|
5369
5600
|
async function publishCommand(options) {
|
|
5370
|
-
const env = options.env
|
|
5601
|
+
const env = options.env;
|
|
5371
5602
|
logger.header("OneX Theme Publish");
|
|
5372
5603
|
logger.info(`Environment: ${env} (${getApiUrl(env)})`);
|
|
5373
5604
|
logger.newLine();
|
|
@@ -5381,13 +5612,13 @@ async function publishCommand(options) {
|
|
|
5381
5612
|
logger.info(`Logged in as: ${tokens.user.email}`);
|
|
5382
5613
|
let themePath;
|
|
5383
5614
|
if (options.theme) {
|
|
5384
|
-
themePath =
|
|
5615
|
+
themePath = path13__default.default.resolve(options.theme);
|
|
5385
5616
|
} else {
|
|
5386
5617
|
const isThemeDir2 = [
|
|
5387
5618
|
"theme.config.ts",
|
|
5388
5619
|
"bundle-entry.ts",
|
|
5389
5620
|
"manifest.ts"
|
|
5390
|
-
].some((f) =>
|
|
5621
|
+
].some((f) => fs8__default.default.existsSync(path13__default.default.join(process.cwd(), f)));
|
|
5391
5622
|
if (isThemeDir2) {
|
|
5392
5623
|
themePath = process.cwd();
|
|
5393
5624
|
} else {
|
|
@@ -5397,13 +5628,13 @@ async function publishCommand(options) {
|
|
|
5397
5628
|
process.exit(1);
|
|
5398
5629
|
}
|
|
5399
5630
|
}
|
|
5400
|
-
const pkgPath =
|
|
5401
|
-
if (!
|
|
5631
|
+
const pkgPath = path13__default.default.join(themePath, "package.json");
|
|
5632
|
+
if (!fs8__default.default.existsSync(pkgPath)) {
|
|
5402
5633
|
logger.error("No package.json found in theme directory");
|
|
5403
5634
|
process.exit(1);
|
|
5404
5635
|
}
|
|
5405
|
-
const pkg =
|
|
5406
|
-
const themeId = pkg.name?.replace("@onex-themes/", "") ||
|
|
5636
|
+
const pkg = fs8__default.default.readJsonSync(pkgPath);
|
|
5637
|
+
const themeId = pkg.name?.replace("@onex-themes/", "") || path13__default.default.basename(themePath);
|
|
5407
5638
|
if (options.bump) {
|
|
5408
5639
|
const currentVersion = pkg.version || "1.0.0";
|
|
5409
5640
|
const newVersion = semver__default.default.inc(currentVersion, options.bump);
|
|
@@ -5412,7 +5643,7 @@ async function publishCommand(options) {
|
|
|
5412
5643
|
process.exit(1);
|
|
5413
5644
|
}
|
|
5414
5645
|
pkg.version = newVersion;
|
|
5415
|
-
|
|
5646
|
+
fs8__default.default.writeJsonSync(pkgPath, pkg, { spaces: 2 });
|
|
5416
5647
|
logger.info(`Bumped version: ${currentVersion} -> ${newVersion}`);
|
|
5417
5648
|
}
|
|
5418
5649
|
const version2 = pkg.version || "1.0.0";
|
|
@@ -5519,7 +5750,7 @@ Or use the --bump flag:
|
|
|
5519
5750
|
logger.error(error instanceof Error ? error.message : "Build error");
|
|
5520
5751
|
process.exit(1);
|
|
5521
5752
|
}
|
|
5522
|
-
const distDir =
|
|
5753
|
+
const distDir = path13__default.default.join(themePath, "dist");
|
|
5523
5754
|
const classification = await runSchemaDiffGate(
|
|
5524
5755
|
themeId,
|
|
5525
5756
|
distDir,
|
|
@@ -5568,8 +5799,8 @@ Or use the --bump flag:
|
|
|
5568
5799
|
for (const [originalPath, url] of Object.entries(videoUrls)) {
|
|
5569
5800
|
assetMap[originalPath] = url;
|
|
5570
5801
|
}
|
|
5571
|
-
const assetMapPath =
|
|
5572
|
-
await
|
|
5802
|
+
const assetMapPath = path13__default.default.join(distDir, "asset-map.json");
|
|
5803
|
+
await fs8__default.default.writeFile(assetMapPath, JSON.stringify(assetMap, null, 2));
|
|
5573
5804
|
} catch (error) {
|
|
5574
5805
|
logger.error(
|
|
5575
5806
|
`Failed to write asset-map.json: ${error instanceof Error ? error.message : "unknown"}`
|
|
@@ -5644,7 +5875,7 @@ Or use the --bump flag:
|
|
|
5644
5875
|
continue;
|
|
5645
5876
|
}
|
|
5646
5877
|
try {
|
|
5647
|
-
const buf = await
|
|
5878
|
+
const buf = await fs8__default.default.promises.readFile(entry.absPath);
|
|
5648
5879
|
const res = await fetch(item.upload_url, {
|
|
5649
5880
|
method: "PUT",
|
|
5650
5881
|
headers: {
|
|
@@ -5686,12 +5917,12 @@ Or use the --bump flag:
|
|
|
5686
5917
|
}
|
|
5687
5918
|
logger.startSpinner("Uploading bundle...");
|
|
5688
5919
|
try {
|
|
5689
|
-
if (!
|
|
5920
|
+
if (!fs8__default.default.existsSync(distDir)) {
|
|
5690
5921
|
logger.stopSpinner(false, "No dist/ directory");
|
|
5691
5922
|
logger.error("Build the theme first: onexthm build");
|
|
5692
5923
|
process.exit(1);
|
|
5693
5924
|
}
|
|
5694
|
-
const bundleZipPath =
|
|
5925
|
+
const bundleZipPath = path13__default.default.join(themePath, "dist", "bundle.zip");
|
|
5695
5926
|
await createZip(distDir, bundleZipPath, [
|
|
5696
5927
|
"bundle.zip",
|
|
5697
5928
|
"source.zip",
|
|
@@ -5700,7 +5931,7 @@ Or use the --bump flag:
|
|
|
5700
5931
|
"theme-assets",
|
|
5701
5932
|
"theme-assets/**"
|
|
5702
5933
|
]);
|
|
5703
|
-
const bundleBuffer =
|
|
5934
|
+
const bundleBuffer = fs8__default.default.readFileSync(bundleZipPath);
|
|
5704
5935
|
const bundleRes = await fetch(bundleUploadUrl, {
|
|
5705
5936
|
method: "PUT",
|
|
5706
5937
|
headers: { "Content-Type": "application/zip" },
|
|
@@ -5718,7 +5949,7 @@ Or use the --bump flag:
|
|
|
5718
5949
|
}
|
|
5719
5950
|
logger.startSpinner("Uploading source...");
|
|
5720
5951
|
try {
|
|
5721
|
-
const sourceZipPath =
|
|
5952
|
+
const sourceZipPath = path13__default.default.join(themePath, "dist", "source.zip");
|
|
5722
5953
|
await createZip(themePath, sourceZipPath, [
|
|
5723
5954
|
"node_modules",
|
|
5724
5955
|
"dist",
|
|
@@ -5726,7 +5957,7 @@ Or use the --bump flag:
|
|
|
5726
5957
|
".env",
|
|
5727
5958
|
".env.local"
|
|
5728
5959
|
]);
|
|
5729
|
-
const sourceBuffer =
|
|
5960
|
+
const sourceBuffer = fs8__default.default.readFileSync(sourceZipPath);
|
|
5730
5961
|
const sourceRes = await fetch(sourceUploadUrl, {
|
|
5731
5962
|
method: "PUT",
|
|
5732
5963
|
headers: { "Content-Type": "application/zip" },
|
|
@@ -5804,9 +6035,9 @@ async function uploadThumbnail(apiUrl, themeId, themePath, distDir, env = "dev")
|
|
|
5804
6035
|
let imageBase64 = null;
|
|
5805
6036
|
let mimeType = "image/png";
|
|
5806
6037
|
for (const { file, mime } of THUMBNAIL_CANDIDATES) {
|
|
5807
|
-
const candidate =
|
|
5808
|
-
if (
|
|
5809
|
-
const buf =
|
|
6038
|
+
const candidate = path13__default.default.join(themePath, file);
|
|
6039
|
+
if (fs8__default.default.existsSync(candidate)) {
|
|
6040
|
+
const buf = fs8__default.default.readFileSync(candidate);
|
|
5810
6041
|
imageBase64 = `data:${mime};base64,${buf.toString("base64")}`;
|
|
5811
6042
|
mimeType = mime;
|
|
5812
6043
|
logger.info(`Using local thumbnail: ${file}`);
|
|
@@ -5906,7 +6137,7 @@ async function screenshotHomePage(themePath, distDir) {
|
|
|
5906
6137
|
const { compilePreviewRuntime: compilePreviewRuntime2 } = await Promise.resolve().then(() => (init_compile_theme(), compile_theme_exports));
|
|
5907
6138
|
const { createDevServer: createDevServer2 } = await Promise.resolve().then(() => (init_dev_server(), dev_server_exports));
|
|
5908
6139
|
const previewRuntimePath = await compilePreviewRuntime2(themePath);
|
|
5909
|
-
const themeName =
|
|
6140
|
+
const themeName = path13__default.default.basename(themePath);
|
|
5910
6141
|
const port = await findFreePort(4500);
|
|
5911
6142
|
const server = createDevServer2({
|
|
5912
6143
|
port,
|
|
@@ -5963,7 +6194,7 @@ async function findFreePort(start) {
|
|
|
5963
6194
|
});
|
|
5964
6195
|
}
|
|
5965
6196
|
async function uploadVideoMultipart(apiUrl, themeId, video, env = "dev") {
|
|
5966
|
-
const fileName =
|
|
6197
|
+
const fileName = path13__default.default.basename(video.originalPath);
|
|
5967
6198
|
const videoInitUrl = `${apiUrl}/media/videos/multipart/init`;
|
|
5968
6199
|
const videoInitBody = {
|
|
5969
6200
|
file_name: fileName,
|
|
@@ -5999,7 +6230,7 @@ async function uploadVideoMultipart(apiUrl, themeId, video, env = "dev") {
|
|
|
5999
6230
|
);
|
|
6000
6231
|
}
|
|
6001
6232
|
const { upload_id, file_key, chunk_size, chunk_urls } = initBody;
|
|
6002
|
-
const fileBuffer = await
|
|
6233
|
+
const fileBuffer = await fs8__default.default.promises.readFile(video.absPath);
|
|
6003
6234
|
const CHUNK_CONCURRENCY = 4;
|
|
6004
6235
|
const queue = [...chunk_urls];
|
|
6005
6236
|
const parts = [];
|
|
@@ -6108,7 +6339,7 @@ async function runSchemaDiffGate(themeId, distDir, env, options) {
|
|
|
6108
6339
|
let currentAssets;
|
|
6109
6340
|
try {
|
|
6110
6341
|
currentSchemas = JSON.parse(
|
|
6111
|
-
await
|
|
6342
|
+
await fs8__default.default.readFile(path13__default.default.join(distDir, "schemas.json"), "utf-8")
|
|
6112
6343
|
);
|
|
6113
6344
|
} catch (err) {
|
|
6114
6345
|
logger.warning(
|
|
@@ -6118,7 +6349,7 @@ async function runSchemaDiffGate(themeId, distDir, env, options) {
|
|
|
6118
6349
|
}
|
|
6119
6350
|
try {
|
|
6120
6351
|
currentAssets = JSON.parse(
|
|
6121
|
-
await
|
|
6352
|
+
await fs8__default.default.readFile(path13__default.default.join(distDir, "asset-manifest.json"), "utf-8")
|
|
6122
6353
|
);
|
|
6123
6354
|
} catch {
|
|
6124
6355
|
currentAssets = { manifestVersion: 1, assets: [] };
|
|
@@ -6188,24 +6419,24 @@ var AI_CONTEXT_FILES = [
|
|
|
6188
6419
|
".mcp.json"
|
|
6189
6420
|
];
|
|
6190
6421
|
function resolveTargetDir(opts) {
|
|
6191
|
-
return
|
|
6422
|
+
return path13__default.default.resolve(opts.cwd ?? process.cwd());
|
|
6192
6423
|
}
|
|
6193
6424
|
function resolveDefaultTemplateDir() {
|
|
6194
|
-
return
|
|
6425
|
+
return path13__default.default.join(getTemplatesDir(), "default");
|
|
6195
6426
|
}
|
|
6196
6427
|
function isThemeDir(dir) {
|
|
6197
|
-
return
|
|
6428
|
+
return fs8__default.default.existsSync(path13__default.default.join(dir, "theme.config.ts")) || fs8__default.default.existsSync(path13__default.default.join(dir, "theme.config.js"));
|
|
6198
6429
|
}
|
|
6199
6430
|
function inspectFiles(templateDir, targetDir) {
|
|
6200
6431
|
return AI_CONTEXT_FILES.map((name) => {
|
|
6201
|
-
const templatePath =
|
|
6202
|
-
const targetPath =
|
|
6203
|
-
const exists =
|
|
6432
|
+
const templatePath = path13__default.default.join(templateDir, name);
|
|
6433
|
+
const targetPath = path13__default.default.join(targetDir, name);
|
|
6434
|
+
const exists = fs8__default.default.existsSync(targetPath);
|
|
6204
6435
|
let identical = false;
|
|
6205
|
-
if (exists &&
|
|
6436
|
+
if (exists && fs8__default.default.existsSync(templatePath)) {
|
|
6206
6437
|
try {
|
|
6207
|
-
const a =
|
|
6208
|
-
const b =
|
|
6438
|
+
const a = fs8__default.default.readFileSync(templatePath, "utf-8");
|
|
6439
|
+
const b = fs8__default.default.readFileSync(targetPath, "utf-8");
|
|
6209
6440
|
identical = a.replace(/\r\n/g, "\n") === b.replace(/\r\n/g, "\n");
|
|
6210
6441
|
} catch {
|
|
6211
6442
|
identical = false;
|
|
@@ -6255,11 +6486,11 @@ async function mcpSetupCommand(options = {}) {
|
|
|
6255
6486
|
}
|
|
6256
6487
|
}
|
|
6257
6488
|
for (const s of missing) {
|
|
6258
|
-
if (!
|
|
6489
|
+
if (!fs8__default.default.existsSync(s.templatePath)) {
|
|
6259
6490
|
logger.warning(` ! ${s.name} not in template \u2014 skipped`);
|
|
6260
6491
|
continue;
|
|
6261
6492
|
}
|
|
6262
|
-
await
|
|
6493
|
+
await fs8__default.default.copy(s.templatePath, s.targetPath);
|
|
6263
6494
|
logger.success(` \u2713 ${s.name}`);
|
|
6264
6495
|
}
|
|
6265
6496
|
logger.log("");
|
|
@@ -6320,11 +6551,11 @@ async function mcpUpgradeCommand(options = {}) {
|
|
|
6320
6551
|
}
|
|
6321
6552
|
}
|
|
6322
6553
|
for (const s of toUpgrade) {
|
|
6323
|
-
if (!
|
|
6554
|
+
if (!fs8__default.default.existsSync(s.templatePath)) {
|
|
6324
6555
|
logger.warning(` ! ${s.name} not in template \u2014 skipped`);
|
|
6325
6556
|
continue;
|
|
6326
6557
|
}
|
|
6327
|
-
await
|
|
6558
|
+
await fs8__default.default.copy(s.templatePath, s.targetPath, { overwrite: true });
|
|
6328
6559
|
logger.success(` \u2713 ${s.name}`);
|
|
6329
6560
|
}
|
|
6330
6561
|
logger.log("");
|
|
@@ -6342,12 +6573,12 @@ async function mcpDoctorCommand(options = {}) {
|
|
|
6342
6573
|
return;
|
|
6343
6574
|
}
|
|
6344
6575
|
logger.success("theme.config.ts present");
|
|
6345
|
-
const mcpJsonPath =
|
|
6346
|
-
if (!
|
|
6576
|
+
const mcpJsonPath = path13__default.default.join(targetDir, ".mcp.json");
|
|
6577
|
+
if (!fs8__default.default.existsSync(mcpJsonPath)) {
|
|
6347
6578
|
logger.error(".mcp.json missing \u2014 run `onexthm mcp setup`");
|
|
6348
6579
|
} else {
|
|
6349
6580
|
try {
|
|
6350
|
-
const mcpJson = JSON.parse(
|
|
6581
|
+
const mcpJson = JSON.parse(fs8__default.default.readFileSync(mcpJsonPath, "utf-8"));
|
|
6351
6582
|
const servers = mcpJson?.mcpServers ?? {};
|
|
6352
6583
|
if (servers.onexthm) {
|
|
6353
6584
|
logger.success(".mcp.json registers `onexthm`");
|
|
@@ -6380,8 +6611,8 @@ async function mcpDoctorCommand(options = {}) {
|
|
|
6380
6611
|
logger.success(`${s.name} up to date`);
|
|
6381
6612
|
}
|
|
6382
6613
|
}
|
|
6383
|
-
const registryPath =
|
|
6384
|
-
if (
|
|
6614
|
+
const registryPath = path13__default.default.join(targetDir, "sections-registry.ts");
|
|
6615
|
+
if (fs8__default.default.existsSync(registryPath)) {
|
|
6385
6616
|
logger.success("sections-registry.ts present");
|
|
6386
6617
|
} else {
|
|
6387
6618
|
logger.warning(
|
|
@@ -6392,24 +6623,27 @@ async function mcpDoctorCommand(options = {}) {
|
|
|
6392
6623
|
|
|
6393
6624
|
// src/cli.ts
|
|
6394
6625
|
dotenv__default.default.config({
|
|
6395
|
-
path:
|
|
6626
|
+
path: path13__default.default.join(process.cwd(), ".env.local"),
|
|
6396
6627
|
override: true
|
|
6397
6628
|
});
|
|
6398
|
-
dotenv__default.default.config({ path:
|
|
6629
|
+
dotenv__default.default.config({ path: path13__default.default.join(process.cwd(), ".env") });
|
|
6399
6630
|
try {
|
|
6400
6631
|
const projectRoot = getProjectRoot();
|
|
6401
|
-
if (
|
|
6632
|
+
if (path13__default.default.resolve(projectRoot) !== path13__default.default.resolve(process.cwd())) {
|
|
6402
6633
|
dotenv__default.default.config({
|
|
6403
|
-
path:
|
|
6634
|
+
path: path13__default.default.join(projectRoot, ".env.local")
|
|
6404
6635
|
});
|
|
6405
|
-
dotenv__default.default.config({ path:
|
|
6636
|
+
dotenv__default.default.config({ path: path13__default.default.join(projectRoot, ".env") });
|
|
6406
6637
|
}
|
|
6407
6638
|
} catch {
|
|
6408
6639
|
}
|
|
6409
6640
|
dotenv__default.default.config({
|
|
6410
|
-
path:
|
|
6641
|
+
path: path13__default.default.join(os__default.default.homedir(), ".onexthm", ".env"),
|
|
6411
6642
|
quiet: true
|
|
6412
6643
|
});
|
|
6644
|
+
function envOpt() {
|
|
6645
|
+
return new commander.Option("--env <env>", "Target environment: dev, staging, or prod").choices(["dev", "staging", "prod"]).makeOptionMandatory();
|
|
6646
|
+
}
|
|
6413
6647
|
var require2 = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.js', document.baseURI).href)));
|
|
6414
6648
|
var { version } = require2("../package.json");
|
|
6415
6649
|
var program = new commander.Command();
|
|
@@ -6418,11 +6652,7 @@ program.command("init").description("Create a new OneX theme project").argument(
|
|
|
6418
6652
|
"-t, --template <template>",
|
|
6419
6653
|
"Template to use (default, minimal)",
|
|
6420
6654
|
"default"
|
|
6421
|
-
).option("--no-install", "Skip installing dependencies").option("--git", "Initialize git repository").option("-y, --yes", "Skip prompts and use defaults").
|
|
6422
|
-
"--env <env>",
|
|
6423
|
-
"Target environment: dev, staging, or prod (default: dev)",
|
|
6424
|
-
"dev"
|
|
6425
|
-
).action(initCommand);
|
|
6655
|
+
).option("--no-install", "Skip installing dependencies").option("--git", "Initialize git repository").option("-y, --yes", "Skip prompts and use defaults").addOption(envOpt()).action(initCommand);
|
|
6426
6656
|
program.command("create:section").alias("cs").description("Create a new section").argument("<name>", "Name of the section (e.g., hero, features)").option("-t, --theme <theme>", "Theme to create section in").option(
|
|
6427
6657
|
"-c, --category <category>",
|
|
6428
6658
|
"Section category (headers, content, footers)"
|
|
@@ -6449,36 +6679,16 @@ program.command("download").description("Download a published theme via the webs
|
|
|
6449
6679
|
"-v, --version <version>",
|
|
6450
6680
|
"Theme version (default: latest)",
|
|
6451
6681
|
"latest"
|
|
6452
|
-
).option(
|
|
6453
|
-
"--env <env>",
|
|
6454
|
-
"Target environment: dev, staging, or prod (default: dev)",
|
|
6455
|
-
"dev"
|
|
6456
|
-
).option("-b, --bucket <name>", "[deprecated] ignored").option("-o, --output <dir>", "Output directory", "./active-theme").action(downloadCommand);
|
|
6682
|
+
).addOption(envOpt()).option("-b, --bucket <name>", "[deprecated] ignored").option("-o, --output <dir>", "Output directory", "./active-theme").action(downloadCommand);
|
|
6457
6683
|
program.command("clone").description("Clone theme source code via the website-api").argument("<theme-name>", "Theme to clone").option(
|
|
6458
6684
|
"-v, --version <version>",
|
|
6459
6685
|
"Theme version (default: latest)",
|
|
6460
6686
|
"latest"
|
|
6461
|
-
).option("-n, --name <name>", "New theme name (skips interactive prompt)").option("-o, --output <dir>", "Output directory").option(
|
|
6462
|
-
"--env <env>",
|
|
6463
|
-
"Target environment: dev, staging, or prod (default: dev)",
|
|
6464
|
-
"dev"
|
|
6465
|
-
).option("-b, --bucket <name>", "[deprecated] ignored").option("--no-install", "Skip running pnpm install after clone").action(cloneCommand);
|
|
6687
|
+
).option("-n, --name <name>", "New theme name (skips interactive prompt)").option("-o, --output <dir>", "Output directory").addOption(envOpt()).option("-b, --bucket <name>", "[deprecated] ignored").option("--no-install", "Skip running pnpm install after clone").action(cloneCommand);
|
|
6466
6688
|
program.command("config").description("Configure OneX CLI credentials (AWS, API keys)").action(configCommand);
|
|
6467
|
-
program.command("login").description("Login to OneX platform").
|
|
6468
|
-
|
|
6469
|
-
|
|
6470
|
-
"dev"
|
|
6471
|
-
).action(loginCommand);
|
|
6472
|
-
program.command("logout").description("Logout from OneX platform").option(
|
|
6473
|
-
"--env <env>",
|
|
6474
|
-
"Target environment: dev, staging, or prod (default: dev)",
|
|
6475
|
-
"dev"
|
|
6476
|
-
).action(logoutCommand);
|
|
6477
|
-
program.command("whoami").description("Show current logged-in developer").option(
|
|
6478
|
-
"--env <env>",
|
|
6479
|
-
"Target environment: dev, staging, or prod (default: dev)",
|
|
6480
|
-
"dev"
|
|
6481
|
-
).action(whoamiCommand);
|
|
6689
|
+
program.command("login").description("Login to OneX platform").addOption(envOpt()).action(loginCommand);
|
|
6690
|
+
program.command("logout").description("Logout from OneX platform").addOption(envOpt()).action(logoutCommand);
|
|
6691
|
+
program.command("whoami").description("Show current logged-in developer").addOption(envOpt()).action(whoamiCommand);
|
|
6482
6692
|
var mcpCmd = program.command("mcp").description("Manage MCP server registration and AI-context files");
|
|
6483
6693
|
mcpCmd.command("setup").description(
|
|
6484
6694
|
"Install .mcp.json + CLAUDE.md + AGENTS.md + .cursorrules into the current theme"
|
|
@@ -6490,11 +6700,7 @@ mcpCmd.command("doctor").description("Diagnose MCP setup in the current theme di
|
|
|
6490
6700
|
program.command("publish").description("Build, scan, and publish theme to marketplace (requires login)").option("-t, --theme <path>", "Theme directory path").option(
|
|
6491
6701
|
"--bump <type>",
|
|
6492
6702
|
"Auto-bump version before publish (patch|minor|major)"
|
|
6493
|
-
).option(
|
|
6494
|
-
"--env <env>",
|
|
6495
|
-
"Target environment: dev, staging, or prod (default: dev)",
|
|
6496
|
-
"dev"
|
|
6497
|
-
).option(
|
|
6703
|
+
).addOption(envOpt()).option(
|
|
6498
6704
|
"--dry-run",
|
|
6499
6705
|
"Build locally and print the schema-diff classification without publishing"
|
|
6500
6706
|
).option(
|