@onexapis/cli 1.1.65 → 1.1.66
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/README.md +1 -1
- package/dist/cli.js +1098 -417
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +1093 -412
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +413 -194
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +409 -190
- package/dist/index.mjs.map +1 -1
- package/dist/preview/preview-app.tsx +89 -7
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -3,18 +3,18 @@
|
|
|
3
3
|
|
|
4
4
|
var chalk4 = require('chalk');
|
|
5
5
|
var ora = require('ora');
|
|
6
|
-
var
|
|
7
|
-
var path9 = require('path');
|
|
8
|
-
var fs8 = require('fs/promises');
|
|
9
|
-
var crypto = require('crypto');
|
|
6
|
+
var path11 = require('path');
|
|
10
7
|
var glob = require('glob');
|
|
8
|
+
var fs = require('fs-extra');
|
|
9
|
+
var crypto = require('crypto');
|
|
10
|
+
var esbuild = require('esbuild');
|
|
11
|
+
var fs9 = require('fs/promises');
|
|
11
12
|
var module$1 = require('module');
|
|
12
13
|
var http = require('http');
|
|
13
14
|
var fs3 = require('fs');
|
|
14
15
|
var ws = require('ws');
|
|
15
16
|
var os = require('os');
|
|
16
17
|
var dotenv = require('dotenv');
|
|
17
|
-
var fs = require('fs-extra');
|
|
18
18
|
var ejs = require('ejs');
|
|
19
19
|
var child_process = require('child_process');
|
|
20
20
|
var commander = require('commander');
|
|
@@ -49,15 +49,15 @@ 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
|
|
54
|
-
var fs8__default = /*#__PURE__*/_interopDefault(fs8);
|
|
52
|
+
var path11__default = /*#__PURE__*/_interopDefault(path11);
|
|
53
|
+
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
55
54
|
var crypto__default = /*#__PURE__*/_interopDefault(crypto);
|
|
55
|
+
var esbuild__namespace = /*#__PURE__*/_interopNamespace(esbuild);
|
|
56
|
+
var fs9__default = /*#__PURE__*/_interopDefault(fs9);
|
|
56
57
|
var http__default = /*#__PURE__*/_interopDefault(http);
|
|
57
58
|
var fs3__default = /*#__PURE__*/_interopDefault(fs3);
|
|
58
59
|
var os__default = /*#__PURE__*/_interopDefault(os);
|
|
59
60
|
var dotenv__default = /*#__PURE__*/_interopDefault(dotenv);
|
|
60
|
-
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
61
61
|
var ejs__default = /*#__PURE__*/_interopDefault(ejs);
|
|
62
62
|
var inquirer__default = /*#__PURE__*/_interopDefault(inquirer);
|
|
63
63
|
var archiver__default = /*#__PURE__*/_interopDefault(archiver);
|
|
@@ -132,6 +132,206 @@ var init_logger = __esm({
|
|
|
132
132
|
logger = new Logger();
|
|
133
133
|
}
|
|
134
134
|
});
|
|
135
|
+
function sortedCopy(value) {
|
|
136
|
+
if (Array.isArray(value)) {
|
|
137
|
+
return value.map((v) => sortedCopy(v));
|
|
138
|
+
}
|
|
139
|
+
if (value && typeof value === "object") {
|
|
140
|
+
const sorted = {};
|
|
141
|
+
for (const key of Object.keys(value).sort()) {
|
|
142
|
+
sorted[key] = sortedCopy(value[key]);
|
|
143
|
+
}
|
|
144
|
+
return sorted;
|
|
145
|
+
}
|
|
146
|
+
return value;
|
|
147
|
+
}
|
|
148
|
+
function normalizeField(raw) {
|
|
149
|
+
const out = {
|
|
150
|
+
id: String(raw.id),
|
|
151
|
+
type: String(raw.type)
|
|
152
|
+
};
|
|
153
|
+
if (raw.required === true) out.required = true;
|
|
154
|
+
if (raw.default !== void 0) out.default = raw.default;
|
|
155
|
+
if (Array.isArray(raw.aliases) && raw.aliases.length > 0) {
|
|
156
|
+
out.aliases = [...raw.aliases].map(String).sort();
|
|
157
|
+
}
|
|
158
|
+
if (typeof raw.maxLength === "number") out.maxLength = raw.maxLength;
|
|
159
|
+
if (typeof raw.min === "number") out.min = raw.min;
|
|
160
|
+
if (typeof raw.max === "number") out.max = raw.max;
|
|
161
|
+
if (typeof raw.step === "number") out.step = raw.step;
|
|
162
|
+
if (Array.isArray(raw.accept)) {
|
|
163
|
+
out.accept = [...raw.accept].map(String).sort();
|
|
164
|
+
}
|
|
165
|
+
if (Array.isArray(raw.options)) {
|
|
166
|
+
out.options = raw.options.map((o) => String(o?.value ?? o)).sort();
|
|
167
|
+
}
|
|
168
|
+
return out;
|
|
169
|
+
}
|
|
170
|
+
function normalizeBlock(raw) {
|
|
171
|
+
return {
|
|
172
|
+
type: String(raw.type),
|
|
173
|
+
settings: Array.isArray(raw.settings) ? raw.settings.map(normalizeField).sort(sortFieldsById) : [],
|
|
174
|
+
defaults: raw.defaults && typeof raw.defaults === "object" ? sortedCopy(raw.defaults) : {},
|
|
175
|
+
...typeof raw.limit === "number" ? { limit: raw.limit } : {},
|
|
176
|
+
...typeof raw.min === "number" ? { min: raw.min } : {},
|
|
177
|
+
...raw.sortable === true ? { sortable: true } : {},
|
|
178
|
+
...raw.baseType ? { baseType: String(raw.baseType) } : {}
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
function normalizeTemplate(raw) {
|
|
182
|
+
const out = { id: String(raw.id) };
|
|
183
|
+
if (raw.isDefault === true) out.isDefault = true;
|
|
184
|
+
if (Array.isArray(raw.settings)) {
|
|
185
|
+
out.settings = raw.settings.map(normalizeField).sort(sortFieldsById);
|
|
186
|
+
}
|
|
187
|
+
if (raw.defaults && typeof raw.defaults === "object") {
|
|
188
|
+
out.defaults = sortedCopy(raw.defaults);
|
|
189
|
+
}
|
|
190
|
+
return out;
|
|
191
|
+
}
|
|
192
|
+
function sortFieldsById(a, b) {
|
|
193
|
+
return a.id.localeCompare(b.id);
|
|
194
|
+
}
|
|
195
|
+
function sortByType(a, b) {
|
|
196
|
+
return a.type.localeCompare(b.type);
|
|
197
|
+
}
|
|
198
|
+
function normalizeSection(raw) {
|
|
199
|
+
return {
|
|
200
|
+
type: String(raw.type),
|
|
201
|
+
settings: Array.isArray(raw.settings) ? raw.settings.map(normalizeField).sort(sortFieldsById) : [],
|
|
202
|
+
defaults: raw.defaults && typeof raw.defaults === "object" ? sortedCopy(raw.defaults) : {},
|
|
203
|
+
blocks: Array.isArray(raw.blocks) ? raw.blocks.map(normalizeBlock).sort(sortByType) : [],
|
|
204
|
+
templates: Array.isArray(raw.templates) ? raw.templates.map(normalizeTemplate).sort(sortFieldsById) : [],
|
|
205
|
+
dataRequirements: raw.dataRequirements && typeof raw.dataRequirements === "object" ? sortedCopy(raw.dataRequirements) : null,
|
|
206
|
+
...raw.global === true ? { global: true } : {},
|
|
207
|
+
...typeof raw.maxBlocks === "number" ? { maxBlocks: raw.maxBlocks } : {}
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
async function extractSchemas(themePath) {
|
|
211
|
+
const { createJiti } = await import('jiti');
|
|
212
|
+
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)));
|
|
213
|
+
const schemaFiles = await glob.glob("sections/**/*.schema.ts", { cwd: themePath });
|
|
214
|
+
const sections = {};
|
|
215
|
+
for (const file of schemaFiles) {
|
|
216
|
+
try {
|
|
217
|
+
const mod = await jiti.import(path11__default.default.join(themePath, file));
|
|
218
|
+
const exports$1 = mod;
|
|
219
|
+
for (const value of Object.values(exports$1)) {
|
|
220
|
+
if (value && typeof value === "object" && typeof value.type === "string" && Array.isArray(value.settings)) {
|
|
221
|
+
const section = normalizeSection(value);
|
|
222
|
+
sections[section.type] = section;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
} catch {
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
const manifest = {
|
|
229
|
+
manifestVersion: 1,
|
|
230
|
+
sections: {}
|
|
231
|
+
};
|
|
232
|
+
for (const type of Object.keys(sections).sort()) {
|
|
233
|
+
manifest.sections[type] = sections[type];
|
|
234
|
+
}
|
|
235
|
+
return manifest;
|
|
236
|
+
}
|
|
237
|
+
function serializeManifest(manifest) {
|
|
238
|
+
return JSON.stringify(sortedCopy(manifest), null, 2);
|
|
239
|
+
}
|
|
240
|
+
var init_extract_schemas = __esm({
|
|
241
|
+
"src/utils/extract-schemas.ts"() {
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
function isVideoAsset(filePath) {
|
|
245
|
+
const lower = filePath.toLowerCase();
|
|
246
|
+
return VIDEO_EXTENSIONS.some((ext) => lower.endsWith(ext));
|
|
247
|
+
}
|
|
248
|
+
function mimeFor(filename) {
|
|
249
|
+
const ext = path11__default.default.extname(filename).toLowerCase();
|
|
250
|
+
return MIME_MAP[ext] || "application/octet-stream";
|
|
251
|
+
}
|
|
252
|
+
async function sha256Prefix(absPath, len) {
|
|
253
|
+
const buf = await fs__default.default.readFile(absPath);
|
|
254
|
+
return crypto__default.default.createHash("sha256").update(buf).digest("hex").slice(0, len);
|
|
255
|
+
}
|
|
256
|
+
function insertHashIntoName(relPath, hash) {
|
|
257
|
+
const dir = path11__default.default.posix.dirname(relPath);
|
|
258
|
+
const base = path11__default.default.posix.basename(relPath);
|
|
259
|
+
const ext = path11__default.default.posix.extname(base);
|
|
260
|
+
const stem = ext ? base.slice(0, -ext.length) : base;
|
|
261
|
+
const hashed = `${stem}-${hash}${ext}`;
|
|
262
|
+
return dir === "." ? hashed : `${dir}/${hashed}`;
|
|
263
|
+
}
|
|
264
|
+
async function scanThemeAssets(distDir) {
|
|
265
|
+
const assetsDir = path11__default.default.join(distDir, "theme-assets");
|
|
266
|
+
if (!await fs__default.default.pathExists(assetsDir)) return [];
|
|
267
|
+
const files = await glob.glob("**/*", {
|
|
268
|
+
cwd: assetsDir,
|
|
269
|
+
nodir: true,
|
|
270
|
+
dot: false
|
|
271
|
+
});
|
|
272
|
+
const results = [];
|
|
273
|
+
for (const rel of files) {
|
|
274
|
+
const absPath = path11__default.default.join(assetsDir, rel);
|
|
275
|
+
const stat = await fs__default.default.stat(absPath);
|
|
276
|
+
if (!stat.isFile()) continue;
|
|
277
|
+
const originalPath = rel.split(path11__default.default.sep).join("/");
|
|
278
|
+
const hash = await sha256Prefix(absPath, HASH_LEN);
|
|
279
|
+
const hashedPath = insertHashIntoName(originalPath, hash);
|
|
280
|
+
const contentType = mimeFor(rel);
|
|
281
|
+
results.push({
|
|
282
|
+
originalPath,
|
|
283
|
+
hashedPath,
|
|
284
|
+
hash,
|
|
285
|
+
size: stat.size,
|
|
286
|
+
contentType,
|
|
287
|
+
absPath
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
results.sort((a, b) => a.originalPath.localeCompare(b.originalPath));
|
|
291
|
+
return results;
|
|
292
|
+
}
|
|
293
|
+
function buildAssetMap(entries) {
|
|
294
|
+
const map = {};
|
|
295
|
+
for (const e of entries) {
|
|
296
|
+
map[e.originalPath] = e.hashedPath;
|
|
297
|
+
}
|
|
298
|
+
return map;
|
|
299
|
+
}
|
|
300
|
+
var MIME_MAP, HASH_LEN, VIDEO_EXTENSIONS;
|
|
301
|
+
var init_scan_theme_assets = __esm({
|
|
302
|
+
"src/utils/scan-theme-assets.ts"() {
|
|
303
|
+
MIME_MAP = {
|
|
304
|
+
".png": "image/png",
|
|
305
|
+
".jpg": "image/jpeg",
|
|
306
|
+
".jpeg": "image/jpeg",
|
|
307
|
+
".gif": "image/gif",
|
|
308
|
+
".webp": "image/webp",
|
|
309
|
+
".avif": "image/avif",
|
|
310
|
+
".svg": "image/svg+xml",
|
|
311
|
+
".ico": "image/x-icon",
|
|
312
|
+
".bmp": "image/bmp",
|
|
313
|
+
".woff": "font/woff",
|
|
314
|
+
".woff2": "font/woff2",
|
|
315
|
+
".ttf": "font/ttf",
|
|
316
|
+
".otf": "font/otf",
|
|
317
|
+
".eot": "application/vnd.ms-fontobject",
|
|
318
|
+
".mp4": "video/mp4",
|
|
319
|
+
".webm": "video/webm",
|
|
320
|
+
".mov": "video/quicktime",
|
|
321
|
+
".ogg": "video/ogg",
|
|
322
|
+
".json": "application/json"
|
|
323
|
+
};
|
|
324
|
+
HASH_LEN = 8;
|
|
325
|
+
VIDEO_EXTENSIONS = [
|
|
326
|
+
".mp4",
|
|
327
|
+
".webm",
|
|
328
|
+
".ogg",
|
|
329
|
+
".mov",
|
|
330
|
+
".avi",
|
|
331
|
+
".mkv"
|
|
332
|
+
];
|
|
333
|
+
}
|
|
334
|
+
});
|
|
135
335
|
|
|
136
336
|
// src/utils/compile-theme.ts
|
|
137
337
|
var compile_theme_exports = {};
|
|
@@ -147,8 +347,8 @@ async function generateThemeCSS(themePath, outDir) {
|
|
|
147
347
|
const tailwindcss = (await import('tailwindcss')).default;
|
|
148
348
|
const tailwindConfig = {
|
|
149
349
|
content: [
|
|
150
|
-
|
|
151
|
-
|
|
350
|
+
path11__default.default.join(themePath, "sections/**/*.{ts,tsx}"),
|
|
351
|
+
path11__default.default.join(themePath, "components/**/*.{ts,tsx}")
|
|
152
352
|
],
|
|
153
353
|
theme: { extend: {} },
|
|
154
354
|
plugins: []
|
|
@@ -158,7 +358,7 @@ async function generateThemeCSS(themePath, outDir) {
|
|
|
158
358
|
inputCSS,
|
|
159
359
|
{ from: void 0 }
|
|
160
360
|
);
|
|
161
|
-
await
|
|
361
|
+
await fs9__default.default.writeFile(path11__default.default.join(outDir, "bundle.css"), result.css);
|
|
162
362
|
logger.info("Generated bundle.css");
|
|
163
363
|
} catch (err) {
|
|
164
364
|
logger.warning(
|
|
@@ -169,12 +369,12 @@ async function generateThemeCSS(themePath, outDir) {
|
|
|
169
369
|
async function resolveNodeModulesFile(startDir, relativePath) {
|
|
170
370
|
let dir = startDir;
|
|
171
371
|
while (true) {
|
|
172
|
-
const candidate =
|
|
372
|
+
const candidate = path11__default.default.join(dir, "node_modules", relativePath);
|
|
173
373
|
try {
|
|
174
|
-
await
|
|
374
|
+
await fs9__default.default.access(candidate);
|
|
175
375
|
return candidate;
|
|
176
376
|
} catch {
|
|
177
|
-
const parent =
|
|
377
|
+
const parent = path11__default.default.dirname(dir);
|
|
178
378
|
if (parent === dir) break;
|
|
179
379
|
dir = parent;
|
|
180
380
|
}
|
|
@@ -198,7 +398,7 @@ async function scanImportsFromPackage(sourceDir, packageName) {
|
|
|
198
398
|
});
|
|
199
399
|
for (const file of sourceFiles) {
|
|
200
400
|
try {
|
|
201
|
-
const content = await
|
|
401
|
+
const content = await fs9__default.default.readFile(path11__default.default.join(sourceDir, file), "utf-8");
|
|
202
402
|
for (const match of content.matchAll(namespaceImportRegex)) {
|
|
203
403
|
const subpath = match[1] ? match[1].slice(1) : "";
|
|
204
404
|
if (!result[subpath]) result[subpath] = /* @__PURE__ */ new Set();
|
|
@@ -252,17 +452,17 @@ function createCoreGlobalPlugin(themePath) {
|
|
|
252
452
|
const distFileName = subpath ? `${subpath}.mjs` : "index.mjs";
|
|
253
453
|
let distPath = await resolveNodeModulesFile(
|
|
254
454
|
themePath,
|
|
255
|
-
|
|
455
|
+
path11__default.default.join("@onexapis", "core", "dist", distFileName)
|
|
256
456
|
);
|
|
257
457
|
if (!distPath) {
|
|
258
458
|
distPath = await resolveNodeModulesFile(
|
|
259
459
|
__dirname,
|
|
260
|
-
|
|
460
|
+
path11__default.default.join("@onexapis", "core", "dist", distFileName)
|
|
261
461
|
);
|
|
262
462
|
}
|
|
263
463
|
try {
|
|
264
464
|
if (!distPath) throw new Error("not found");
|
|
265
|
-
const distContent = await
|
|
465
|
+
const distContent = await fs9__default.default.readFile(distPath, "utf-8");
|
|
266
466
|
const exportMatches = distContent.matchAll(/export\s*\{([^}]+)\}/g);
|
|
267
467
|
for (const m of exportMatches) {
|
|
268
468
|
const names = m[1].split(",").map((n) => {
|
|
@@ -491,7 +691,7 @@ async function generateThemeData(themePath, outputDir, themeId) {
|
|
|
491
691
|
const pages = {};
|
|
492
692
|
for (const ext of [".ts", ".js"]) {
|
|
493
693
|
try {
|
|
494
|
-
const mod = await jiti.import(
|
|
694
|
+
const mod = await jiti.import(path11__default.default.join(themePath, `theme.config${ext}`));
|
|
495
695
|
themeConfig = mod.default || mod;
|
|
496
696
|
break;
|
|
497
697
|
} catch {
|
|
@@ -499,20 +699,20 @@ async function generateThemeData(themePath, outputDir, themeId) {
|
|
|
499
699
|
}
|
|
500
700
|
for (const ext of [".ts", ".js"]) {
|
|
501
701
|
try {
|
|
502
|
-
const mod = await jiti.import(
|
|
702
|
+
const mod = await jiti.import(path11__default.default.join(themePath, `theme.layout${ext}`));
|
|
503
703
|
layoutConfig = mod.default || mod;
|
|
504
704
|
break;
|
|
505
705
|
} catch {
|
|
506
706
|
}
|
|
507
707
|
}
|
|
508
708
|
const schemas = {};
|
|
509
|
-
const sectionsDir =
|
|
709
|
+
const sectionsDir = path11__default.default.join(themePath, "sections");
|
|
510
710
|
try {
|
|
511
|
-
const sectionDirs = await
|
|
711
|
+
const sectionDirs = await fs9__default.default.readdir(sectionsDir);
|
|
512
712
|
for (const dir of sectionDirs) {
|
|
513
|
-
const schemaFile =
|
|
713
|
+
const schemaFile = path11__default.default.join(sectionsDir, dir, `${dir}.schema.ts`);
|
|
514
714
|
try {
|
|
515
|
-
await
|
|
715
|
+
await fs9__default.default.access(schemaFile);
|
|
516
716
|
const mod = await jiti.import(schemaFile);
|
|
517
717
|
for (const [key, value] of Object.entries(mod)) {
|
|
518
718
|
if (key.endsWith("Schema") && value && typeof value === "object" && value.type) {
|
|
@@ -524,14 +724,14 @@ async function generateThemeData(themePath, outputDir, themeId) {
|
|
|
524
724
|
}
|
|
525
725
|
} catch {
|
|
526
726
|
}
|
|
527
|
-
const pagesDir =
|
|
727
|
+
const pagesDir = path11__default.default.join(themePath, "pages");
|
|
528
728
|
try {
|
|
529
|
-
const files = await
|
|
729
|
+
const files = await fs9__default.default.readdir(pagesDir);
|
|
530
730
|
for (const file of files) {
|
|
531
731
|
if (!file.match(/\.(ts|js)$/)) continue;
|
|
532
732
|
const name = file.replace(/\.(ts|js)$/, "");
|
|
533
733
|
try {
|
|
534
|
-
const mod = await jiti.import(
|
|
734
|
+
const mod = await jiti.import(path11__default.default.join(pagesDir, file));
|
|
535
735
|
const config = mod.default || mod;
|
|
536
736
|
const sections = (config.sections || []).map((section) => {
|
|
537
737
|
const schema = schemas[section.type];
|
|
@@ -559,8 +759,8 @@ async function generateThemeData(themePath, outputDir, themeId) {
|
|
|
559
759
|
}
|
|
560
760
|
} catch {
|
|
561
761
|
}
|
|
562
|
-
await
|
|
563
|
-
|
|
762
|
+
await fs9__default.default.writeFile(
|
|
763
|
+
path11__default.default.join(outputDir, "theme-data.json"),
|
|
564
764
|
JSON.stringify(
|
|
565
765
|
{
|
|
566
766
|
themeId,
|
|
@@ -583,22 +783,22 @@ async function generateThemeData(themePath, outputDir, themeId) {
|
|
|
583
783
|
logger.info(`Generated theme-data.json (${Object.keys(pages).length} pages)`);
|
|
584
784
|
}
|
|
585
785
|
async function contentHashEntry(outputDir) {
|
|
586
|
-
const entryPath =
|
|
587
|
-
const mapPath =
|
|
786
|
+
const entryPath = path11__default.default.join(outputDir, "bundle-entry.js");
|
|
787
|
+
const mapPath = path11__default.default.join(outputDir, "bundle-entry.js.map");
|
|
588
788
|
let entryContent;
|
|
589
789
|
try {
|
|
590
|
-
entryContent = await
|
|
790
|
+
entryContent = await fs9__default.default.readFile(entryPath, "utf-8");
|
|
591
791
|
} catch {
|
|
592
|
-
const indexPath =
|
|
792
|
+
const indexPath = path11__default.default.join(outputDir, "index.js");
|
|
593
793
|
try {
|
|
594
|
-
entryContent = await
|
|
794
|
+
entryContent = await fs9__default.default.readFile(indexPath, "utf-8");
|
|
595
795
|
} catch {
|
|
596
796
|
logger.warning("No entry file found in output, skipping content hash");
|
|
597
797
|
return;
|
|
598
798
|
}
|
|
599
799
|
const hash2 = crypto__default.default.createHash("sha256").update(entryContent).digest("hex").slice(0, 8);
|
|
600
800
|
const hashedName2 = `bundle-entry-${hash2}.js`;
|
|
601
|
-
const indexMapPath =
|
|
801
|
+
const indexMapPath = path11__default.default.join(outputDir, "index.js.map");
|
|
602
802
|
const hashedMapName2 = `bundle-entry-${hash2}.js.map`;
|
|
603
803
|
entryContent = entryContent.replace(
|
|
604
804
|
/\/\/# sourceMappingURL=index\.js\.map/,
|
|
@@ -606,18 +806,18 @@ async function contentHashEntry(outputDir) {
|
|
|
606
806
|
);
|
|
607
807
|
const oldFiles2 = await glob.glob("bundle-entry-*.js*", { cwd: outputDir });
|
|
608
808
|
for (const f of oldFiles2) {
|
|
609
|
-
await
|
|
809
|
+
await fs9__default.default.unlink(path11__default.default.join(outputDir, f));
|
|
610
810
|
}
|
|
611
|
-
await
|
|
612
|
-
await
|
|
811
|
+
await fs9__default.default.writeFile(path11__default.default.join(outputDir, hashedName2), entryContent);
|
|
812
|
+
await fs9__default.default.unlink(indexPath);
|
|
613
813
|
try {
|
|
614
|
-
await
|
|
814
|
+
await fs9__default.default.unlink(entryPath);
|
|
615
815
|
} catch {
|
|
616
816
|
}
|
|
617
|
-
await
|
|
817
|
+
await fs9__default.default.writeFile(entryPath, entryContent);
|
|
618
818
|
try {
|
|
619
|
-
await
|
|
620
|
-
await
|
|
819
|
+
await fs9__default.default.access(indexMapPath);
|
|
820
|
+
await fs9__default.default.rename(indexMapPath, path11__default.default.join(outputDir, hashedMapName2));
|
|
621
821
|
} catch {
|
|
622
822
|
}
|
|
623
823
|
logger.info(`Entry hashed: ${hashedName2}`);
|
|
@@ -632,17 +832,17 @@ async function contentHashEntry(outputDir) {
|
|
|
632
832
|
);
|
|
633
833
|
const oldFiles = await glob.glob("bundle-entry-*.js*", { cwd: outputDir });
|
|
634
834
|
for (const f of oldFiles) {
|
|
635
|
-
await
|
|
835
|
+
await fs9__default.default.unlink(path11__default.default.join(outputDir, f));
|
|
636
836
|
}
|
|
637
|
-
await
|
|
837
|
+
await fs9__default.default.writeFile(path11__default.default.join(outputDir, hashedName), entryContent);
|
|
638
838
|
try {
|
|
639
|
-
await
|
|
839
|
+
await fs9__default.default.unlink(entryPath);
|
|
640
840
|
} catch {
|
|
641
841
|
}
|
|
642
|
-
await
|
|
842
|
+
await fs9__default.default.writeFile(entryPath, entryContent);
|
|
643
843
|
try {
|
|
644
|
-
await
|
|
645
|
-
await
|
|
844
|
+
await fs9__default.default.access(mapPath);
|
|
845
|
+
await fs9__default.default.rename(mapPath, path11__default.default.join(outputDir, hashedMapName));
|
|
646
846
|
} catch {
|
|
647
847
|
}
|
|
648
848
|
logger.info(`Entry hashed: ${hashedName}`);
|
|
@@ -654,7 +854,7 @@ async function extractDataRequirements(themePath) {
|
|
|
654
854
|
const requirements = {};
|
|
655
855
|
for (const file of schemaFiles) {
|
|
656
856
|
try {
|
|
657
|
-
const mod = await jiti.import(
|
|
857
|
+
const mod = await jiti.import(path11__default.default.join(themePath, file));
|
|
658
858
|
const exports$1 = mod;
|
|
659
859
|
for (const value of Object.values(exports$1)) {
|
|
660
860
|
if (value && typeof value === "object" && typeof value.type === "string" && value.dataRequirements && typeof value.dataRequirements === "object") {
|
|
@@ -669,12 +869,46 @@ async function extractDataRequirements(themePath) {
|
|
|
669
869
|
}
|
|
670
870
|
return requirements;
|
|
671
871
|
}
|
|
872
|
+
async function writeGateManifests(themePath, outputDir) {
|
|
873
|
+
try {
|
|
874
|
+
const schemas = await extractSchemas(themePath);
|
|
875
|
+
await fs9__default.default.writeFile(
|
|
876
|
+
path11__default.default.join(outputDir, "schemas.json"),
|
|
877
|
+
serializeManifest(schemas)
|
|
878
|
+
);
|
|
879
|
+
logger.info(
|
|
880
|
+
`Generated schemas.json (${Object.keys(schemas.sections).length} sections)`
|
|
881
|
+
);
|
|
882
|
+
} catch (err) {
|
|
883
|
+
logger.warning(
|
|
884
|
+
`schemas.json not written: ${err instanceof Error ? err.message : String(err)}`
|
|
885
|
+
);
|
|
886
|
+
}
|
|
887
|
+
try {
|
|
888
|
+
const entries = await scanThemeAssets(outputDir);
|
|
889
|
+
const assets = entries.map((e) => ({
|
|
890
|
+
path: e.originalPath,
|
|
891
|
+
hash: e.hash,
|
|
892
|
+
size: e.size,
|
|
893
|
+
contentType: e.contentType
|
|
894
|
+
}));
|
|
895
|
+
await fs9__default.default.writeFile(
|
|
896
|
+
path11__default.default.join(outputDir, "asset-manifest.json"),
|
|
897
|
+
JSON.stringify({ manifestVersion: 1, assets }, null, 2)
|
|
898
|
+
);
|
|
899
|
+
logger.info(`Generated asset-manifest.json (${assets.length} assets)`);
|
|
900
|
+
} catch (err) {
|
|
901
|
+
logger.warning(
|
|
902
|
+
`asset-manifest.json not written: ${err instanceof Error ? err.message : String(err)}`
|
|
903
|
+
);
|
|
904
|
+
}
|
|
905
|
+
}
|
|
672
906
|
async function generateManifest(themeName, themePath, outputDir) {
|
|
673
907
|
let version2 = "1.0.0";
|
|
674
908
|
let themeId = themeName;
|
|
675
909
|
try {
|
|
676
|
-
const pkgContent = await
|
|
677
|
-
|
|
910
|
+
const pkgContent = await fs9__default.default.readFile(
|
|
911
|
+
path11__default.default.join(themePath, "package.json"),
|
|
678
912
|
"utf-8"
|
|
679
913
|
);
|
|
680
914
|
const pkg = JSON.parse(pkgContent);
|
|
@@ -692,7 +926,7 @@ async function generateManifest(themeName, themePath, outputDir) {
|
|
|
692
926
|
const dataRequirements = await extractDataRequirements(themePath);
|
|
693
927
|
let hasThemeConfig = false;
|
|
694
928
|
try {
|
|
695
|
-
await
|
|
929
|
+
await fs9__default.default.access(path11__default.default.join(themePath, "theme.config.ts"));
|
|
696
930
|
hasThemeConfig = true;
|
|
697
931
|
} catch {
|
|
698
932
|
}
|
|
@@ -733,24 +967,24 @@ async function generateManifest(themeName, themePath, outputDir) {
|
|
|
733
967
|
// Section data requirements for server-side prefetching (keyed by section type)
|
|
734
968
|
dataRequirements
|
|
735
969
|
};
|
|
736
|
-
await
|
|
737
|
-
|
|
970
|
+
await fs9__default.default.writeFile(
|
|
971
|
+
path11__default.default.join(outputDir, "manifest.json"),
|
|
738
972
|
JSON.stringify(manifest, null, 2)
|
|
739
973
|
);
|
|
740
974
|
}
|
|
741
975
|
async function compileStandaloneTheme(themePath, themeName) {
|
|
742
|
-
const outputDir =
|
|
743
|
-
const bundleEntry =
|
|
744
|
-
const indexEntry =
|
|
976
|
+
const outputDir = path11__default.default.join(themePath, "dist");
|
|
977
|
+
const bundleEntry = path11__default.default.join(themePath, "bundle-entry.ts");
|
|
978
|
+
const indexEntry = path11__default.default.join(themePath, "index.ts");
|
|
745
979
|
let entryPoint = indexEntry;
|
|
746
980
|
try {
|
|
747
|
-
await
|
|
981
|
+
await fs9__default.default.access(bundleEntry);
|
|
748
982
|
entryPoint = bundleEntry;
|
|
749
983
|
} catch {
|
|
750
984
|
}
|
|
751
|
-
const shimPath =
|
|
752
|
-
await
|
|
753
|
-
await
|
|
985
|
+
const shimPath = path11__default.default.join(outputDir, ".process-shim.js");
|
|
986
|
+
await fs9__default.default.mkdir(outputDir, { recursive: true });
|
|
987
|
+
await fs9__default.default.writeFile(shimPath, PROCESS_SHIM);
|
|
754
988
|
const buildOptions = {
|
|
755
989
|
entryPoints: [entryPoint],
|
|
756
990
|
bundle: true,
|
|
@@ -801,19 +1035,20 @@ async function compileStandaloneTheme(themePath, themeName) {
|
|
|
801
1035
|
try {
|
|
802
1036
|
const result = await esbuild__namespace.build(buildOptions);
|
|
803
1037
|
try {
|
|
804
|
-
await
|
|
1038
|
+
await fs9__default.default.unlink(shimPath);
|
|
805
1039
|
} catch {
|
|
806
1040
|
}
|
|
807
1041
|
await contentHashEntry(outputDir);
|
|
808
|
-
const themeAssetsDir =
|
|
809
|
-
const distThemeAssets =
|
|
1042
|
+
const themeAssetsDir = path11__default.default.join(themePath, "assets");
|
|
1043
|
+
const distThemeAssets = path11__default.default.join(outputDir, "theme-assets");
|
|
810
1044
|
try {
|
|
811
|
-
await
|
|
812
|
-
await
|
|
1045
|
+
await fs9__default.default.access(themeAssetsDir);
|
|
1046
|
+
await fs9__default.default.cp(themeAssetsDir, distThemeAssets, { recursive: true });
|
|
813
1047
|
logger.info("Copied static assets to dist/theme-assets/");
|
|
814
1048
|
} catch {
|
|
815
1049
|
}
|
|
816
1050
|
await generateManifest(themeName, themePath, outputDir);
|
|
1051
|
+
await writeGateManifests(themePath, outputDir);
|
|
817
1052
|
await generateThemeData(themePath, outputDir, themeName);
|
|
818
1053
|
await generateThemeCSS(themePath, outputDir);
|
|
819
1054
|
if (result.metafile) {
|
|
@@ -828,7 +1063,7 @@ async function compileStandaloneTheme(themePath, themeName) {
|
|
|
828
1063
|
return true;
|
|
829
1064
|
} catch (error) {
|
|
830
1065
|
try {
|
|
831
|
-
await
|
|
1066
|
+
await fs9__default.default.unlink(shimPath);
|
|
832
1067
|
} catch {
|
|
833
1068
|
}
|
|
834
1069
|
logger.error(`esbuild compilation failed: ${error}`);
|
|
@@ -836,18 +1071,18 @@ async function compileStandaloneTheme(themePath, themeName) {
|
|
|
836
1071
|
}
|
|
837
1072
|
}
|
|
838
1073
|
async function compileStandaloneThemeDev(themePath, themeName) {
|
|
839
|
-
const outputDir =
|
|
840
|
-
const bundleEntry =
|
|
841
|
-
const indexEntry =
|
|
1074
|
+
const outputDir = path11__default.default.join(themePath, "dist");
|
|
1075
|
+
const bundleEntry = path11__default.default.join(themePath, "bundle-entry.ts");
|
|
1076
|
+
const indexEntry = path11__default.default.join(themePath, "index.ts");
|
|
842
1077
|
let entryPoint = indexEntry;
|
|
843
1078
|
try {
|
|
844
|
-
await
|
|
1079
|
+
await fs9__default.default.access(bundleEntry);
|
|
845
1080
|
entryPoint = bundleEntry;
|
|
846
1081
|
} catch {
|
|
847
1082
|
}
|
|
848
|
-
const shimPath =
|
|
849
|
-
await
|
|
850
|
-
await
|
|
1083
|
+
const shimPath = path11__default.default.join(outputDir, ".process-shim.js");
|
|
1084
|
+
await fs9__default.default.mkdir(outputDir, { recursive: true });
|
|
1085
|
+
await fs9__default.default.writeFile(shimPath, PROCESS_SHIM);
|
|
851
1086
|
const buildOptions = {
|
|
852
1087
|
entryPoints: [entryPoint],
|
|
853
1088
|
bundle: true,
|
|
@@ -901,18 +1136,18 @@ async function compileStandaloneThemeDev(themePath, themeName) {
|
|
|
901
1136
|
return { context: context2, outputDir };
|
|
902
1137
|
}
|
|
903
1138
|
async function compilePreviewRuntime(themePath) {
|
|
904
|
-
const outputDir =
|
|
905
|
-
await
|
|
906
|
-
const outputPath =
|
|
1139
|
+
const outputDir = path11__default.default.join(themePath, "dist");
|
|
1140
|
+
await fs9__default.default.mkdir(outputDir, { recursive: true });
|
|
1141
|
+
const outputPath = path11__default.default.join(outputDir, "preview-runtime.js");
|
|
907
1142
|
const locations = [
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
1143
|
+
path11__default.default.join(__dirname, "..", "preview", "preview-app.tsx"),
|
|
1144
|
+
path11__default.default.join(__dirname, "preview", "preview-app.tsx"),
|
|
1145
|
+
path11__default.default.join(__dirname, "..", "..", "src", "preview", "preview-app.tsx")
|
|
911
1146
|
];
|
|
912
1147
|
let previewEntryPath = null;
|
|
913
1148
|
for (const loc of locations) {
|
|
914
1149
|
try {
|
|
915
|
-
await
|
|
1150
|
+
await fs9__default.default.access(loc);
|
|
916
1151
|
previewEntryPath = loc;
|
|
917
1152
|
break;
|
|
918
1153
|
} catch {
|
|
@@ -995,10 +1230,10 @@ ${locations.join("\n")}`
|
|
|
995
1230
|
if (!lucideScanned) {
|
|
996
1231
|
lucideScanned = true;
|
|
997
1232
|
const coreSrcCandidates = [
|
|
998
|
-
|
|
999
|
-
|
|
1233
|
+
path11__default.default.join(themePath, "node_modules", "@onexapis", "core", "src"),
|
|
1234
|
+
path11__default.default.join(themePath, "..", "..", "packages", "core", "src"),
|
|
1000
1235
|
// monorepo sibling
|
|
1001
|
-
|
|
1236
|
+
path11__default.default.join(
|
|
1002
1237
|
__dirname,
|
|
1003
1238
|
"..",
|
|
1004
1239
|
"..",
|
|
@@ -1013,7 +1248,7 @@ ${locations.join("\n")}`
|
|
|
1013
1248
|
let coreSourceDir = null;
|
|
1014
1249
|
for (const candidate of coreSrcCandidates) {
|
|
1015
1250
|
try {
|
|
1016
|
-
await
|
|
1251
|
+
await fs9__default.default.access(candidate);
|
|
1017
1252
|
coreSourceDir = candidate;
|
|
1018
1253
|
break;
|
|
1019
1254
|
} catch {
|
|
@@ -1032,21 +1267,21 @@ ${locations.join("\n")}`
|
|
|
1032
1267
|
}
|
|
1033
1268
|
} else {
|
|
1034
1269
|
const coreDistCandidates = [
|
|
1035
|
-
|
|
1270
|
+
path11__default.default.join(themePath, "node_modules", "@onexapis", "core", "dist")
|
|
1036
1271
|
];
|
|
1037
1272
|
const resolvedDist = await resolveNodeModulesFile(
|
|
1038
1273
|
__dirname,
|
|
1039
|
-
|
|
1274
|
+
path11__default.default.join("@onexapis", "core", "dist")
|
|
1040
1275
|
);
|
|
1041
1276
|
if (resolvedDist) coreDistCandidates.push(resolvedDist);
|
|
1042
1277
|
for (const candidate of coreDistCandidates) {
|
|
1043
1278
|
try {
|
|
1044
|
-
await
|
|
1279
|
+
await fs9__default.default.access(candidate);
|
|
1045
1280
|
const mjsFiles = await glob.glob("*.mjs", { cwd: candidate });
|
|
1046
1281
|
const importRegex = /import\s*\{([^}]+)\}\s*from\s*["']lucide-react["']/g;
|
|
1047
1282
|
for (const file of mjsFiles) {
|
|
1048
|
-
const content = await
|
|
1049
|
-
|
|
1283
|
+
const content = await fs9__default.default.readFile(
|
|
1284
|
+
path11__default.default.join(candidate, file),
|
|
1050
1285
|
"utf-8"
|
|
1051
1286
|
);
|
|
1052
1287
|
for (const match of content.matchAll(importRegex)) {
|
|
@@ -1101,7 +1336,7 @@ export default new Proxy({}, { get: (_, name) => name === '__esModule' ? true :
|
|
|
1101
1336
|
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);
|
|
1102
1337
|
const cjsPath = req.resolve("framer-motion");
|
|
1103
1338
|
const pkgDir = cjsPath.replace(/[/\\]dist[/\\].*$/, "");
|
|
1104
|
-
const esmEntry =
|
|
1339
|
+
const esmEntry = path11__default.default.join(pkgDir, "dist", "es", "index.mjs");
|
|
1105
1340
|
const { existsSync } = await import('fs');
|
|
1106
1341
|
if (existsSync(esmEntry)) {
|
|
1107
1342
|
return { path: esmEntry, namespace: "file" };
|
|
@@ -1200,8 +1435,8 @@ export function headers() { return new Headers(); }
|
|
|
1200
1435
|
});
|
|
1201
1436
|
}
|
|
1202
1437
|
};
|
|
1203
|
-
const shimPath =
|
|
1204
|
-
await
|
|
1438
|
+
const shimPath = path11__default.default.join(outputDir, ".process-shim-preview.js");
|
|
1439
|
+
await fs9__default.default.writeFile(shimPath, PROCESS_SHIM);
|
|
1205
1440
|
await esbuild__namespace.build({
|
|
1206
1441
|
entryPoints: [previewEntryPath],
|
|
1207
1442
|
bundle: true,
|
|
@@ -1236,7 +1471,7 @@ export function headers() { return new Headers(); }
|
|
|
1236
1471
|
}
|
|
1237
1472
|
});
|
|
1238
1473
|
try {
|
|
1239
|
-
await
|
|
1474
|
+
await fs9__default.default.unlink(shimPath);
|
|
1240
1475
|
} catch {
|
|
1241
1476
|
}
|
|
1242
1477
|
return outputPath;
|
|
@@ -1245,6 +1480,8 @@ var PROCESS_SHIM, reactGlobalPlugin, reactQueryGlobalPlugin;
|
|
|
1245
1480
|
var init_compile_theme = __esm({
|
|
1246
1481
|
"src/utils/compile-theme.ts"() {
|
|
1247
1482
|
init_logger();
|
|
1483
|
+
init_extract_schemas();
|
|
1484
|
+
init_scan_theme_assets();
|
|
1248
1485
|
PROCESS_SHIM = `
|
|
1249
1486
|
if (typeof process === "undefined") {
|
|
1250
1487
|
globalThis.process = {
|
|
@@ -1400,7 +1637,7 @@ __export(dev_server_exports, {
|
|
|
1400
1637
|
});
|
|
1401
1638
|
function createDevServer(options) {
|
|
1402
1639
|
const clients = /* @__PURE__ */ new Set();
|
|
1403
|
-
const themeDataPath =
|
|
1640
|
+
const themeDataPath = path11__default.default.join(options.distDir, "theme-data.json");
|
|
1404
1641
|
const server = http__default.default.createServer((req, res) => {
|
|
1405
1642
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
1406
1643
|
res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
|
|
@@ -1426,8 +1663,8 @@ function createDevServer(options) {
|
|
|
1426
1663
|
if (pathname.startsWith("/_assets/")) {
|
|
1427
1664
|
const parts = pathname.replace(/^\/_assets\//, "").split("/");
|
|
1428
1665
|
const assetSubpath = parts.slice(1).join("/");
|
|
1429
|
-
const assetPath =
|
|
1430
|
-
if (!assetPath.startsWith(
|
|
1666
|
+
const assetPath = path11__default.default.join(options.themePath, "assets", assetSubpath);
|
|
1667
|
+
if (!assetPath.startsWith(path11__default.default.join(options.themePath, "assets"))) {
|
|
1431
1668
|
res.writeHead(403);
|
|
1432
1669
|
res.end("Forbidden");
|
|
1433
1670
|
return;
|
|
@@ -1438,8 +1675,8 @@ function createDevServer(options) {
|
|
|
1438
1675
|
if (pathname.startsWith("/themes/")) {
|
|
1439
1676
|
const match = pathname.match(/^\/themes\/[^/]+\/assets\/(.+)/);
|
|
1440
1677
|
if (match) {
|
|
1441
|
-
const assetPath =
|
|
1442
|
-
if (!assetPath.startsWith(
|
|
1678
|
+
const assetPath = path11__default.default.join(options.themePath, "assets", match[1]);
|
|
1679
|
+
if (!assetPath.startsWith(path11__default.default.join(options.themePath, "assets"))) {
|
|
1443
1680
|
res.writeHead(403);
|
|
1444
1681
|
res.end("Forbidden");
|
|
1445
1682
|
return;
|
|
@@ -1451,26 +1688,26 @@ function createDevServer(options) {
|
|
|
1451
1688
|
if (pathname.startsWith("/assets/")) {
|
|
1452
1689
|
const subpath = pathname.replace(/^\/assets\//, "");
|
|
1453
1690
|
const segments = subpath.split("/");
|
|
1454
|
-
const assetsBase =
|
|
1691
|
+
const assetsBase = path11__default.default.join(options.themePath, "assets");
|
|
1455
1692
|
let assetPath;
|
|
1456
1693
|
if (segments[0] === options.themeName || segments[0] === options.themeName.replace(/^my-/, "")) {
|
|
1457
|
-
assetPath =
|
|
1694
|
+
assetPath = path11__default.default.join(assetsBase, segments.slice(1).join("/"));
|
|
1458
1695
|
} else {
|
|
1459
|
-
assetPath =
|
|
1696
|
+
assetPath = path11__default.default.join(assetsBase, subpath);
|
|
1460
1697
|
}
|
|
1461
1698
|
if (assetPath.startsWith(assetsBase) && fs3__default.default.existsSync(assetPath)) {
|
|
1462
1699
|
serveFile(res, assetPath);
|
|
1463
1700
|
return;
|
|
1464
1701
|
}
|
|
1465
1702
|
if (segments.length > 1) {
|
|
1466
|
-
const fallbackPath =
|
|
1703
|
+
const fallbackPath = path11__default.default.join(assetsBase, segments.slice(1).join("/"));
|
|
1467
1704
|
if (fallbackPath.startsWith(assetsBase) && fs3__default.default.existsSync(fallbackPath)) {
|
|
1468
1705
|
serveFile(res, fallbackPath);
|
|
1469
1706
|
return;
|
|
1470
1707
|
}
|
|
1471
1708
|
}
|
|
1472
1709
|
}
|
|
1473
|
-
const filePath =
|
|
1710
|
+
const filePath = path11__default.default.join(options.distDir, pathname);
|
|
1474
1711
|
if (!filePath.startsWith(options.distDir)) {
|
|
1475
1712
|
res.writeHead(403);
|
|
1476
1713
|
res.end("Forbidden");
|
|
@@ -1513,7 +1750,7 @@ function serveFile(res, filePath) {
|
|
|
1513
1750
|
res.end("Not Found");
|
|
1514
1751
|
return;
|
|
1515
1752
|
}
|
|
1516
|
-
const ext =
|
|
1753
|
+
const ext = path11__default.default.extname(filePath);
|
|
1517
1754
|
const contentType = MIME_TYPES[ext] || "application/octet-stream";
|
|
1518
1755
|
const content = fs3__default.default.readFileSync(filePath);
|
|
1519
1756
|
res.writeHead(200, { "Content-Type": contentType });
|
|
@@ -1634,18 +1871,18 @@ async function renderTemplate(templatePath, data) {
|
|
|
1634
1871
|
return ejs__default.default.render(template, data);
|
|
1635
1872
|
}
|
|
1636
1873
|
async function writeFile(filePath, content) {
|
|
1637
|
-
await fs__default.default.ensureDir(
|
|
1874
|
+
await fs__default.default.ensureDir(path11__default.default.dirname(filePath));
|
|
1638
1875
|
await fs__default.default.writeFile(filePath, content, "utf-8");
|
|
1639
1876
|
}
|
|
1640
1877
|
function getTemplatesDir() {
|
|
1641
1878
|
const locations = [
|
|
1642
|
-
|
|
1879
|
+
path11__default.default.join(__dirname, "../../templates"),
|
|
1643
1880
|
// Development
|
|
1644
|
-
|
|
1881
|
+
path11__default.default.join(__dirname, "../templates"),
|
|
1645
1882
|
// Production (dist/)
|
|
1646
|
-
|
|
1883
|
+
path11__default.default.join(process.cwd(), "templates"),
|
|
1647
1884
|
// Fallback
|
|
1648
|
-
|
|
1885
|
+
path11__default.default.join(process.cwd(), "packages/cli/templates")
|
|
1649
1886
|
// Monorepo
|
|
1650
1887
|
];
|
|
1651
1888
|
for (const location of locations) {
|
|
@@ -1657,7 +1894,7 @@ function getTemplatesDir() {
|
|
|
1657
1894
|
}
|
|
1658
1895
|
async function copyTemplate(templateName, targetDir, data) {
|
|
1659
1896
|
const templatesDir = getTemplatesDir();
|
|
1660
|
-
const templateDir =
|
|
1897
|
+
const templateDir = path11__default.default.join(templatesDir, templateName);
|
|
1661
1898
|
if (!fs__default.default.existsSync(templateDir)) {
|
|
1662
1899
|
throw new Error(
|
|
1663
1900
|
`Template "${templateName}" not found at ${templateDir}. Available templates: ${fs__default.default.readdirSync(templatesDir).join(", ")}`
|
|
@@ -1666,8 +1903,8 @@ async function copyTemplate(templateName, targetDir, data) {
|
|
|
1666
1903
|
await fs__default.default.ensureDir(targetDir);
|
|
1667
1904
|
const files = await fs__default.default.readdir(templateDir);
|
|
1668
1905
|
for (const file of files) {
|
|
1669
|
-
const templatePath =
|
|
1670
|
-
const targetPath =
|
|
1906
|
+
const templatePath = path11__default.default.join(templateDir, file);
|
|
1907
|
+
const targetPath = path11__default.default.join(targetDir, file);
|
|
1671
1908
|
const stat = await fs__default.default.stat(templatePath);
|
|
1672
1909
|
if (stat.isDirectory()) {
|
|
1673
1910
|
await copyTemplateDir(templatePath, targetPath, data);
|
|
@@ -1684,8 +1921,8 @@ async function copyTemplateDir(templateDir, targetDir, data) {
|
|
|
1684
1921
|
await fs__default.default.ensureDir(targetDir);
|
|
1685
1922
|
const files = await fs__default.default.readdir(templateDir);
|
|
1686
1923
|
for (const file of files) {
|
|
1687
|
-
const templatePath =
|
|
1688
|
-
const targetPath =
|
|
1924
|
+
const templatePath = path11__default.default.join(templateDir, file);
|
|
1925
|
+
const targetPath = path11__default.default.join(targetDir, file);
|
|
1689
1926
|
const stat = await fs__default.default.stat(templatePath);
|
|
1690
1927
|
if (stat.isDirectory()) {
|
|
1691
1928
|
await copyTemplateDir(templatePath, targetPath, data);
|
|
@@ -1700,32 +1937,32 @@ async function copyTemplateDir(templateDir, targetDir, data) {
|
|
|
1700
1937
|
}
|
|
1701
1938
|
function getProjectRoot() {
|
|
1702
1939
|
let currentDir = process.cwd();
|
|
1703
|
-
while (currentDir !==
|
|
1704
|
-
const packageJsonPath =
|
|
1940
|
+
while (currentDir !== path11__default.default.parse(currentDir).root) {
|
|
1941
|
+
const packageJsonPath = path11__default.default.join(currentDir, "package.json");
|
|
1705
1942
|
if (fs__default.default.existsSync(packageJsonPath)) {
|
|
1706
1943
|
const packageJson = fs__default.default.readJsonSync(packageJsonPath);
|
|
1707
|
-
if (packageJson.workspaces || fs__default.default.existsSync(
|
|
1944
|
+
if (packageJson.workspaces || fs__default.default.existsSync(path11__default.default.join(currentDir, "src/themes")) || fs__default.default.existsSync(path11__default.default.join(currentDir, "themes"))) {
|
|
1708
1945
|
return currentDir;
|
|
1709
1946
|
}
|
|
1710
1947
|
}
|
|
1711
|
-
currentDir =
|
|
1948
|
+
currentDir = path11__default.default.dirname(currentDir);
|
|
1712
1949
|
}
|
|
1713
1950
|
return process.cwd();
|
|
1714
1951
|
}
|
|
1715
1952
|
function getThemesDir() {
|
|
1716
1953
|
const root = getProjectRoot();
|
|
1717
|
-
if (fs__default.default.existsSync(
|
|
1718
|
-
return
|
|
1719
|
-
if (fs__default.default.existsSync(
|
|
1720
|
-
return
|
|
1721
|
-
return
|
|
1954
|
+
if (fs__default.default.existsSync(path11__default.default.join(root, "themes")))
|
|
1955
|
+
return path11__default.default.join(root, "themes");
|
|
1956
|
+
if (fs__default.default.existsSync(path11__default.default.join(root, "src/themes")))
|
|
1957
|
+
return path11__default.default.join(root, "src/themes");
|
|
1958
|
+
return path11__default.default.dirname(root);
|
|
1722
1959
|
}
|
|
1723
1960
|
function getFeaturesDir() {
|
|
1724
|
-
return
|
|
1961
|
+
return path11__default.default.join(getProjectRoot(), "src/features");
|
|
1725
1962
|
}
|
|
1726
1963
|
function isOneXProject() {
|
|
1727
1964
|
const root = getProjectRoot();
|
|
1728
|
-
return fs__default.default.existsSync(
|
|
1965
|
+
return fs__default.default.existsSync(path11__default.default.join(root, "themes")) || fs__default.default.existsSync(path11__default.default.join(root, "src/themes")) || fs__default.default.existsSync(path11__default.default.join(root, "theme.config.ts")) || fs__default.default.existsSync(path11__default.default.join(root, "bundle-entry.ts"));
|
|
1729
1966
|
}
|
|
1730
1967
|
function ensureOneXProject() {
|
|
1731
1968
|
if (!isOneXProject()) {
|
|
@@ -1741,13 +1978,13 @@ function listThemes() {
|
|
|
1741
1978
|
return [];
|
|
1742
1979
|
}
|
|
1743
1980
|
return fs__default.default.readdirSync(themesDir).filter((name) => {
|
|
1744
|
-
const themePath =
|
|
1745
|
-
return fs__default.default.statSync(themePath).isDirectory() && (fs__default.default.existsSync(
|
|
1981
|
+
const themePath = path11__default.default.join(themesDir, name);
|
|
1982
|
+
return fs__default.default.statSync(themePath).isDirectory() && (fs__default.default.existsSync(path11__default.default.join(themePath, "theme.config.ts")) || fs__default.default.existsSync(path11__default.default.join(themePath, "bundle-entry.ts")) || fs__default.default.existsSync(path11__default.default.join(themePath, "manifest.ts")));
|
|
1746
1983
|
});
|
|
1747
1984
|
}
|
|
1748
1985
|
function themeExists(themeName) {
|
|
1749
|
-
const themePath =
|
|
1750
|
-
return fs__default.default.existsSync(themePath) && (fs__default.default.existsSync(
|
|
1986
|
+
const themePath = path11__default.default.join(getThemesDir(), themeName);
|
|
1987
|
+
return fs__default.default.existsSync(themePath) && (fs__default.default.existsSync(path11__default.default.join(themePath, "theme.config.ts")) || fs__default.default.existsSync(path11__default.default.join(themePath, "bundle-entry.ts")) || fs__default.default.existsSync(path11__default.default.join(themePath, "manifest.ts")));
|
|
1751
1988
|
}
|
|
1752
1989
|
function detectPackageManager() {
|
|
1753
1990
|
const userAgent = process.env.npm_config_user_agent || "";
|
|
@@ -1755,9 +1992,9 @@ function detectPackageManager() {
|
|
|
1755
1992
|
if (userAgent.includes("yarn")) return "yarn";
|
|
1756
1993
|
if (userAgent.includes("bun")) return "bun";
|
|
1757
1994
|
const cwd = process.cwd();
|
|
1758
|
-
if (fs__default.default.existsSync(
|
|
1759
|
-
if (fs__default.default.existsSync(
|
|
1760
|
-
if (fs__default.default.existsSync(
|
|
1995
|
+
if (fs__default.default.existsSync(path11__default.default.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
1996
|
+
if (fs__default.default.existsSync(path11__default.default.join(cwd, "yarn.lock"))) return "yarn";
|
|
1997
|
+
if (fs__default.default.existsSync(path11__default.default.join(cwd, "bun.lockb"))) return "bun";
|
|
1761
1998
|
return "npm";
|
|
1762
1999
|
}
|
|
1763
2000
|
async function installDependencies(projectPath, packageManager = "npm") {
|
|
@@ -1806,15 +2043,16 @@ function getValidCategories() {
|
|
|
1806
2043
|
"contact"
|
|
1807
2044
|
];
|
|
1808
2045
|
}
|
|
1809
|
-
var AUTH_DIR =
|
|
2046
|
+
var AUTH_DIR = path11__default.default.join(os__default.default.homedir(), ".onexthm");
|
|
1810
2047
|
var ENV_URLS = {
|
|
1811
2048
|
dev: "https://platform-dev.onexeos.com",
|
|
1812
|
-
|
|
2049
|
+
staging: "https://platform-staging.onexeos.com",
|
|
2050
|
+
prod: "https://platform-apis.onexeos.com"
|
|
1813
2051
|
};
|
|
1814
2052
|
function getAuthFile(env = "dev") {
|
|
1815
|
-
const newFile =
|
|
2053
|
+
const newFile = path11__default.default.join(AUTH_DIR, `auth-${env}.json`);
|
|
1816
2054
|
if (env === "dev") {
|
|
1817
|
-
const legacyFile =
|
|
2055
|
+
const legacyFile = path11__default.default.join(AUTH_DIR, "auth.json");
|
|
1818
2056
|
if (fs__default.default.existsSync(legacyFile) && !fs__default.default.existsSync(newFile)) {
|
|
1819
2057
|
try {
|
|
1820
2058
|
fs__default.default.moveSync(legacyFile, newFile);
|
|
@@ -1965,7 +2203,7 @@ async function initCommand(projectName, options = {}) {
|
|
|
1965
2203
|
if (!validateThemeName(kebabName)) {
|
|
1966
2204
|
return "Invalid project name. Use lowercase letters, numbers, and hyphens only.";
|
|
1967
2205
|
}
|
|
1968
|
-
if (fs3__default.default.existsSync(
|
|
2206
|
+
if (fs3__default.default.existsSync(path11__default.default.join(process.cwd(), kebabName))) {
|
|
1969
2207
|
return `Directory "${kebabName}" already exists`;
|
|
1970
2208
|
}
|
|
1971
2209
|
return true;
|
|
@@ -1976,7 +2214,7 @@ async function initCommand(projectName, options = {}) {
|
|
|
1976
2214
|
} else {
|
|
1977
2215
|
name = toKebabCase(projectName);
|
|
1978
2216
|
}
|
|
1979
|
-
const projectPath =
|
|
2217
|
+
const projectPath = path11__default.default.join(process.cwd(), name);
|
|
1980
2218
|
if (fs3__default.default.existsSync(projectPath)) {
|
|
1981
2219
|
logger.error(`Directory "${name}" already exists.`);
|
|
1982
2220
|
process.exit(1);
|
|
@@ -2092,7 +2330,7 @@ async function initCommand(projectName, options = {}) {
|
|
|
2092
2330
|
description,
|
|
2093
2331
|
author
|
|
2094
2332
|
);
|
|
2095
|
-
const mcpJsonPath =
|
|
2333
|
+
const mcpJsonPath = path11__default.default.join(projectPath, ".mcp.json");
|
|
2096
2334
|
if (fs3__default.default.existsSync(mcpJsonPath)) {
|
|
2097
2335
|
let mcpContent = fs3__default.default.readFileSync(mcpJsonPath, "utf-8");
|
|
2098
2336
|
if (figmaApiKey) {
|
|
@@ -2172,7 +2410,7 @@ async function initCommand(projectName, options = {}) {
|
|
|
2172
2410
|
}
|
|
2173
2411
|
}
|
|
2174
2412
|
async function renameThemeInFiles(projectPath, themeName, displayName, description, author) {
|
|
2175
|
-
const configPath =
|
|
2413
|
+
const configPath = path11__default.default.join(projectPath, "theme.config.ts");
|
|
2176
2414
|
if (fs3__default.default.existsSync(configPath)) {
|
|
2177
2415
|
let content = fs3__default.default.readFileSync(configPath, "utf-8");
|
|
2178
2416
|
content = content.replace(
|
|
@@ -2185,7 +2423,7 @@ async function renameThemeInFiles(projectPath, themeName, displayName, descripti
|
|
|
2185
2423
|
);
|
|
2186
2424
|
fs3__default.default.writeFileSync(configPath, content, "utf-8");
|
|
2187
2425
|
}
|
|
2188
|
-
const pkgPath =
|
|
2426
|
+
const pkgPath = path11__default.default.join(projectPath, "package.json");
|
|
2189
2427
|
if (fs3__default.default.existsSync(pkgPath)) {
|
|
2190
2428
|
let content = fs3__default.default.readFileSync(pkgPath, "utf-8");
|
|
2191
2429
|
content = content.replace(
|
|
@@ -2207,10 +2445,10 @@ async function createSectionCommand(name, options) {
|
|
|
2207
2445
|
ensureOneXProject();
|
|
2208
2446
|
if (!options.theme) {
|
|
2209
2447
|
const isStandaloneTheme = ["theme.config.ts", "bundle-entry.ts"].some(
|
|
2210
|
-
(f) => fs__default.default.existsSync(
|
|
2448
|
+
(f) => fs__default.default.existsSync(path11__default.default.join(process.cwd(), f))
|
|
2211
2449
|
);
|
|
2212
2450
|
if (isStandaloneTheme) {
|
|
2213
|
-
options.theme =
|
|
2451
|
+
options.theme = path11__default.default.basename(process.cwd());
|
|
2214
2452
|
}
|
|
2215
2453
|
}
|
|
2216
2454
|
const sectionName = toKebabCase(name);
|
|
@@ -2273,35 +2511,35 @@ async function createSectionCommand(name, options) {
|
|
|
2273
2511
|
};
|
|
2274
2512
|
logger.startSpinner("Creating section files...");
|
|
2275
2513
|
try {
|
|
2276
|
-
const themePath =
|
|
2277
|
-
const sectionPath =
|
|
2514
|
+
const themePath = path11__default.default.join(getThemesDir(), themeName);
|
|
2515
|
+
const sectionPath = path11__default.default.join(themePath, "sections", sectionName);
|
|
2278
2516
|
const schemaContent = generateSectionSchema(data);
|
|
2279
2517
|
await writeFile(
|
|
2280
|
-
|
|
2518
|
+
path11__default.default.join(sectionPath, `${sectionName}.schema.ts`),
|
|
2281
2519
|
schemaContent
|
|
2282
2520
|
);
|
|
2283
2521
|
if (createTemplate) {
|
|
2284
2522
|
const templateContent = generateSectionTemplate(data);
|
|
2285
2523
|
await writeFile(
|
|
2286
|
-
|
|
2524
|
+
path11__default.default.join(sectionPath, `${sectionName}-default.tsx`),
|
|
2287
2525
|
templateContent
|
|
2288
2526
|
);
|
|
2289
2527
|
}
|
|
2290
2528
|
const indexContent = generateSectionIndex(data, createTemplate);
|
|
2291
|
-
await writeFile(
|
|
2529
|
+
await writeFile(path11__default.default.join(sectionPath, "index.ts"), indexContent);
|
|
2292
2530
|
logger.stopSpinner(true, "Section files created successfully!");
|
|
2293
2531
|
logger.newLine();
|
|
2294
2532
|
logger.section("Next steps:");
|
|
2295
2533
|
logger.log(
|
|
2296
|
-
` 1. Edit schema: ${
|
|
2534
|
+
` 1. Edit schema: ${path11__default.default.relative(process.cwd(), path11__default.default.join(sectionPath, `${sectionName}.schema.ts`))}`
|
|
2297
2535
|
);
|
|
2298
2536
|
if (createTemplate) {
|
|
2299
2537
|
logger.log(
|
|
2300
|
-
` 2. Edit template: ${
|
|
2538
|
+
` 2. Edit template: ${path11__default.default.relative(process.cwd(), path11__default.default.join(sectionPath, `${sectionName}-default.tsx`))}`
|
|
2301
2539
|
);
|
|
2302
2540
|
}
|
|
2303
2541
|
logger.log(
|
|
2304
|
-
` 3. Add to theme manifest: ${
|
|
2542
|
+
` 3. Add to theme manifest: ${path11__default.default.relative(process.cwd(), path11__default.default.join(themePath, "manifest.ts"))}`
|
|
2305
2543
|
);
|
|
2306
2544
|
logger.newLine();
|
|
2307
2545
|
logger.success("Section created successfully!");
|
|
@@ -2449,10 +2687,10 @@ async function createBlockCommand(name, options) {
|
|
|
2449
2687
|
ensureOneXProject();
|
|
2450
2688
|
if (!options.theme) {
|
|
2451
2689
|
const isStandaloneTheme = ["theme.config.ts", "bundle-entry.ts"].some(
|
|
2452
|
-
(f) => fs__default.default.existsSync(
|
|
2690
|
+
(f) => fs__default.default.existsSync(path11__default.default.join(process.cwd(), f))
|
|
2453
2691
|
);
|
|
2454
2692
|
if (isStandaloneTheme) {
|
|
2455
|
-
options.theme =
|
|
2693
|
+
options.theme = path11__default.default.basename(process.cwd());
|
|
2456
2694
|
}
|
|
2457
2695
|
}
|
|
2458
2696
|
const blockName = toKebabCase(name);
|
|
@@ -2527,24 +2765,24 @@ async function createBlockCommand(name, options) {
|
|
|
2527
2765
|
};
|
|
2528
2766
|
logger.startSpinner("Creating block files...");
|
|
2529
2767
|
try {
|
|
2530
|
-
const blockPath = scope === "shared" ?
|
|
2768
|
+
const blockPath = scope === "shared" ? path11__default.default.join(getFeaturesDir(), "blocks", blockName) : path11__default.default.join(getThemesDir(), themeName, "blocks", blockName);
|
|
2531
2769
|
const schemaContent = generateBlockSchema(data);
|
|
2532
2770
|
await writeFile(
|
|
2533
|
-
|
|
2771
|
+
path11__default.default.join(blockPath, `${blockName}.schema.ts`),
|
|
2534
2772
|
schemaContent
|
|
2535
2773
|
);
|
|
2536
2774
|
const componentContent = generateBlockComponent(data);
|
|
2537
|
-
await writeFile(
|
|
2775
|
+
await writeFile(path11__default.default.join(blockPath, `${blockName}.tsx`), componentContent);
|
|
2538
2776
|
const indexContent = generateBlockIndex(data);
|
|
2539
|
-
await writeFile(
|
|
2777
|
+
await writeFile(path11__default.default.join(blockPath, "index.ts"), indexContent);
|
|
2540
2778
|
logger.stopSpinner(true, "Block files created successfully!");
|
|
2541
2779
|
logger.newLine();
|
|
2542
2780
|
logger.section("Next steps:");
|
|
2543
2781
|
logger.log(
|
|
2544
|
-
` 1. Edit schema: ${
|
|
2782
|
+
` 1. Edit schema: ${path11__default.default.relative(process.cwd(), path11__default.default.join(blockPath, `${blockName}.schema.ts`))}`
|
|
2545
2783
|
);
|
|
2546
2784
|
logger.log(
|
|
2547
|
-
` 2. Edit component: ${
|
|
2785
|
+
` 2. Edit component: ${path11__default.default.relative(process.cwd(), path11__default.default.join(blockPath, `${blockName}.tsx`))}`
|
|
2548
2786
|
);
|
|
2549
2787
|
logger.log(
|
|
2550
2788
|
` 3. Register in block registry: src/lib/registry/block-registry.ts`
|
|
@@ -2722,31 +2960,31 @@ async function createComponentCommand(name, options) {
|
|
|
2722
2960
|
};
|
|
2723
2961
|
logger.startSpinner("Creating component files...");
|
|
2724
2962
|
try {
|
|
2725
|
-
const componentPath =
|
|
2963
|
+
const componentPath = path11__default.default.join(
|
|
2726
2964
|
getFeaturesDir(),
|
|
2727
2965
|
"components",
|
|
2728
2966
|
componentName
|
|
2729
2967
|
);
|
|
2730
2968
|
const schemaContent = generateComponentSchema(data);
|
|
2731
2969
|
await writeFile(
|
|
2732
|
-
|
|
2970
|
+
path11__default.default.join(componentPath, `${componentName}.schema.ts`),
|
|
2733
2971
|
schemaContent
|
|
2734
2972
|
);
|
|
2735
2973
|
const componentContent = generateComponent(data);
|
|
2736
2974
|
await writeFile(
|
|
2737
|
-
|
|
2975
|
+
path11__default.default.join(componentPath, `${componentName}.tsx`),
|
|
2738
2976
|
componentContent
|
|
2739
2977
|
);
|
|
2740
2978
|
const indexContent = generateComponentIndex(data);
|
|
2741
|
-
await writeFile(
|
|
2979
|
+
await writeFile(path11__default.default.join(componentPath, "index.ts"), indexContent);
|
|
2742
2980
|
logger.stopSpinner(true, "Component files created successfully!");
|
|
2743
2981
|
logger.newLine();
|
|
2744
2982
|
logger.section("Next steps:");
|
|
2745
2983
|
logger.log(
|
|
2746
|
-
` 1. Edit schema: ${
|
|
2984
|
+
` 1. Edit schema: ${path11__default.default.relative(process.cwd(), path11__default.default.join(componentPath, `${componentName}.schema.ts`))}`
|
|
2747
2985
|
);
|
|
2748
2986
|
logger.log(
|
|
2749
|
-
` 2. Edit component: ${
|
|
2987
|
+
` 2. Edit component: ${path11__default.default.relative(process.cwd(), path11__default.default.join(componentPath, `${componentName}.tsx`))}`
|
|
2750
2988
|
);
|
|
2751
2989
|
logger.log(
|
|
2752
2990
|
` 3. Register in component registry: src/lib/registry/component-registry.ts`
|
|
@@ -2903,13 +3141,13 @@ async function listSections(themeFilter) {
|
|
|
2903
3141
|
return;
|
|
2904
3142
|
}
|
|
2905
3143
|
for (const theme of themes) {
|
|
2906
|
-
const sectionsDir =
|
|
3144
|
+
const sectionsDir = path11__default.default.join(getThemesDir(), theme, "sections");
|
|
2907
3145
|
if (!fs__default.default.existsSync(sectionsDir)) {
|
|
2908
3146
|
continue;
|
|
2909
3147
|
}
|
|
2910
3148
|
const sections = fs__default.default.readdirSync(sectionsDir).filter((name) => {
|
|
2911
|
-
const sectionPath =
|
|
2912
|
-
return fs__default.default.statSync(sectionPath).isDirectory() && fs__default.default.existsSync(
|
|
3149
|
+
const sectionPath = path11__default.default.join(sectionsDir, name);
|
|
3150
|
+
return fs__default.default.statSync(sectionPath).isDirectory() && fs__default.default.existsSync(path11__default.default.join(sectionPath, "index.ts"));
|
|
2913
3151
|
});
|
|
2914
3152
|
if (sections.length > 0) {
|
|
2915
3153
|
logger.log(chalk4__default.default.cyan(`
|
|
@@ -2923,11 +3161,11 @@ async function listSections(themeFilter) {
|
|
|
2923
3161
|
}
|
|
2924
3162
|
async function listBlocks(themeFilter) {
|
|
2925
3163
|
logger.section("\u{1F9F1} Blocks");
|
|
2926
|
-
const sharedBlocksDir =
|
|
3164
|
+
const sharedBlocksDir = path11__default.default.join(getFeaturesDir(), "blocks");
|
|
2927
3165
|
if (fs__default.default.existsSync(sharedBlocksDir)) {
|
|
2928
3166
|
const sharedBlocks = fs__default.default.readdirSync(sharedBlocksDir).filter((name) => {
|
|
2929
|
-
const blockPath =
|
|
2930
|
-
return fs__default.default.statSync(blockPath).isDirectory() && fs__default.default.existsSync(
|
|
3167
|
+
const blockPath = path11__default.default.join(sharedBlocksDir, name);
|
|
3168
|
+
return fs__default.default.statSync(blockPath).isDirectory() && fs__default.default.existsSync(path11__default.default.join(blockPath, "index.ts"));
|
|
2931
3169
|
});
|
|
2932
3170
|
if (sharedBlocks.length > 0) {
|
|
2933
3171
|
logger.log(chalk4__default.default.cyan("\n Shared:"));
|
|
@@ -2938,13 +3176,13 @@ async function listBlocks(themeFilter) {
|
|
|
2938
3176
|
}
|
|
2939
3177
|
const themes = themeFilter ? [themeFilter] : listThemes();
|
|
2940
3178
|
for (const theme of themes) {
|
|
2941
|
-
const blocksDir =
|
|
3179
|
+
const blocksDir = path11__default.default.join(getThemesDir(), theme, "blocks");
|
|
2942
3180
|
if (!fs__default.default.existsSync(blocksDir)) {
|
|
2943
3181
|
continue;
|
|
2944
3182
|
}
|
|
2945
3183
|
const blocks = fs__default.default.readdirSync(blocksDir).filter((name) => {
|
|
2946
|
-
const blockPath =
|
|
2947
|
-
return fs__default.default.statSync(blockPath).isDirectory() && fs__default.default.existsSync(
|
|
3184
|
+
const blockPath = path11__default.default.join(blocksDir, name);
|
|
3185
|
+
return fs__default.default.statSync(blockPath).isDirectory() && fs__default.default.existsSync(path11__default.default.join(blockPath, "index.ts"));
|
|
2948
3186
|
});
|
|
2949
3187
|
if (blocks.length > 0) {
|
|
2950
3188
|
logger.log(chalk4__default.default.cyan(`
|
|
@@ -2958,14 +3196,14 @@ async function listBlocks(themeFilter) {
|
|
|
2958
3196
|
}
|
|
2959
3197
|
async function listComponents() {
|
|
2960
3198
|
logger.section("\u2699\uFE0F Components");
|
|
2961
|
-
const componentsDir =
|
|
3199
|
+
const componentsDir = path11__default.default.join(getFeaturesDir(), "components");
|
|
2962
3200
|
if (!fs__default.default.existsSync(componentsDir)) {
|
|
2963
3201
|
logger.warning("No components directory found");
|
|
2964
3202
|
return;
|
|
2965
3203
|
}
|
|
2966
3204
|
const components = fs__default.default.readdirSync(componentsDir).filter((name) => {
|
|
2967
|
-
const componentPath =
|
|
2968
|
-
return fs__default.default.statSync(componentPath).isDirectory() && fs__default.default.existsSync(
|
|
3205
|
+
const componentPath = path11__default.default.join(componentsDir, name);
|
|
3206
|
+
return fs__default.default.statSync(componentPath).isDirectory() && fs__default.default.existsSync(path11__default.default.join(componentPath, "index.ts"));
|
|
2969
3207
|
});
|
|
2970
3208
|
if (components.length === 0) {
|
|
2971
3209
|
logger.warning("No components found");
|
|
@@ -2986,11 +3224,11 @@ async function listThemesInfo() {
|
|
|
2986
3224
|
}
|
|
2987
3225
|
logger.log("");
|
|
2988
3226
|
for (const theme of themes) {
|
|
2989
|
-
const themeDir =
|
|
3227
|
+
const themeDir = path11__default.default.join(getThemesDir(), theme);
|
|
2990
3228
|
const candidates = ["theme.config.ts", "bundle-entry.ts", "manifest.ts"];
|
|
2991
3229
|
let manifestContent = "";
|
|
2992
3230
|
for (const candidate of candidates) {
|
|
2993
|
-
const candidatePath =
|
|
3231
|
+
const candidatePath = path11__default.default.join(themeDir, candidate);
|
|
2994
3232
|
if (fs__default.default.existsSync(candidatePath)) {
|
|
2995
3233
|
manifestContent = fs__default.default.readFileSync(candidatePath, "utf-8");
|
|
2996
3234
|
break;
|
|
@@ -3028,9 +3266,9 @@ async function validateCommand(options) {
|
|
|
3028
3266
|
"theme.config.ts",
|
|
3029
3267
|
"bundle-entry.ts",
|
|
3030
3268
|
"manifest.ts"
|
|
3031
|
-
].some((f) => fs__default.default.existsSync(
|
|
3269
|
+
].some((f) => fs__default.default.existsSync(path11__default.default.join(process.cwd(), f)));
|
|
3032
3270
|
if (isThemeDir2) {
|
|
3033
|
-
themeToValidate =
|
|
3271
|
+
themeToValidate = path11__default.default.basename(process.cwd());
|
|
3034
3272
|
logger.info(`Validating current theme: ${themeToValidate}`);
|
|
3035
3273
|
} else {
|
|
3036
3274
|
logger.error(
|
|
@@ -3039,11 +3277,11 @@ async function validateCommand(options) {
|
|
|
3039
3277
|
process.exit(1);
|
|
3040
3278
|
}
|
|
3041
3279
|
}
|
|
3042
|
-
const themePath =
|
|
3280
|
+
const themePath = path11__default.default.join(getThemesDir(), themeToValidate);
|
|
3043
3281
|
logger.startSpinner("Running validation checks...");
|
|
3044
3282
|
const entryFiles = ["manifest.ts", "theme.config.ts", "bundle-entry.ts"];
|
|
3045
3283
|
const foundEntry = entryFiles.find(
|
|
3046
|
-
(f) => fs__default.default.existsSync(
|
|
3284
|
+
(f) => fs__default.default.existsSync(path11__default.default.join(themePath, f))
|
|
3047
3285
|
);
|
|
3048
3286
|
if (!foundEntry) {
|
|
3049
3287
|
issues.push({
|
|
@@ -3053,7 +3291,7 @@ async function validateCommand(options) {
|
|
|
3053
3291
|
});
|
|
3054
3292
|
} else if (foundEntry === "manifest.ts") {
|
|
3055
3293
|
const manifestContent = fs__default.default.readFileSync(
|
|
3056
|
-
|
|
3294
|
+
path11__default.default.join(themePath, foundEntry),
|
|
3057
3295
|
"utf-8"
|
|
3058
3296
|
);
|
|
3059
3297
|
if (!manifestContent.includes("export const") && !manifestContent.includes("export default") && !manifestContent.includes("export interface")) {
|
|
@@ -3064,7 +3302,7 @@ async function validateCommand(options) {
|
|
|
3064
3302
|
});
|
|
3065
3303
|
}
|
|
3066
3304
|
}
|
|
3067
|
-
const configPath =
|
|
3305
|
+
const configPath = path11__default.default.join(themePath, "theme.config.ts");
|
|
3068
3306
|
if (!fs__default.default.existsSync(configPath)) {
|
|
3069
3307
|
issues.push({
|
|
3070
3308
|
type: "warning",
|
|
@@ -3072,7 +3310,7 @@ async function validateCommand(options) {
|
|
|
3072
3310
|
message: "Theme config file not found (recommended)"
|
|
3073
3311
|
});
|
|
3074
3312
|
}
|
|
3075
|
-
const indexPath =
|
|
3313
|
+
const indexPath = path11__default.default.join(themePath, "index.ts");
|
|
3076
3314
|
if (!fs__default.default.existsSync(indexPath)) {
|
|
3077
3315
|
issues.push({
|
|
3078
3316
|
type: "warning",
|
|
@@ -3080,7 +3318,7 @@ async function validateCommand(options) {
|
|
|
3080
3318
|
message: "Index file not found (recommended)"
|
|
3081
3319
|
});
|
|
3082
3320
|
}
|
|
3083
|
-
const sectionsDir =
|
|
3321
|
+
const sectionsDir = path11__default.default.join(themePath, "sections");
|
|
3084
3322
|
if (!fs__default.default.existsSync(sectionsDir)) {
|
|
3085
3323
|
issues.push({
|
|
3086
3324
|
type: "warning",
|
|
@@ -3089,16 +3327,16 @@ async function validateCommand(options) {
|
|
|
3089
3327
|
});
|
|
3090
3328
|
} else {
|
|
3091
3329
|
const sections = fs__default.default.readdirSync(sectionsDir).filter(
|
|
3092
|
-
(name) => fs__default.default.statSync(
|
|
3330
|
+
(name) => fs__default.default.statSync(path11__default.default.join(sectionsDir, name)).isDirectory()
|
|
3093
3331
|
);
|
|
3094
3332
|
for (const sectionName of sections) {
|
|
3095
|
-
const sectionPath =
|
|
3096
|
-
const schemaFile =
|
|
3097
|
-
const defaultTemplate =
|
|
3333
|
+
const sectionPath = path11__default.default.join(sectionsDir, sectionName);
|
|
3334
|
+
const schemaFile = path11__default.default.join(sectionPath, `${sectionName}.schema.ts`);
|
|
3335
|
+
const defaultTemplate = path11__default.default.join(
|
|
3098
3336
|
sectionPath,
|
|
3099
3337
|
`${sectionName}-default.tsx`
|
|
3100
3338
|
);
|
|
3101
|
-
const indexFile =
|
|
3339
|
+
const indexFile = path11__default.default.join(sectionPath, "index.ts");
|
|
3102
3340
|
if (!fs__default.default.existsSync(schemaFile)) {
|
|
3103
3341
|
issues.push({
|
|
3104
3342
|
type: "error",
|
|
@@ -3122,14 +3360,14 @@ async function validateCommand(options) {
|
|
|
3122
3360
|
}
|
|
3123
3361
|
}
|
|
3124
3362
|
}
|
|
3125
|
-
const blocksDir =
|
|
3363
|
+
const blocksDir = path11__default.default.join(themePath, "blocks");
|
|
3126
3364
|
if (fs__default.default.existsSync(blocksDir)) {
|
|
3127
|
-
const blocks = fs__default.default.readdirSync(blocksDir).filter((name) => fs__default.default.statSync(
|
|
3365
|
+
const blocks = fs__default.default.readdirSync(blocksDir).filter((name) => fs__default.default.statSync(path11__default.default.join(blocksDir, name)).isDirectory());
|
|
3128
3366
|
for (const blockName of blocks) {
|
|
3129
|
-
const blockPath =
|
|
3130
|
-
const schemaFile =
|
|
3131
|
-
const componentFile =
|
|
3132
|
-
const indexFile =
|
|
3367
|
+
const blockPath = path11__default.default.join(blocksDir, blockName);
|
|
3368
|
+
const schemaFile = path11__default.default.join(blockPath, `${blockName}.schema.ts`);
|
|
3369
|
+
const componentFile = path11__default.default.join(blockPath, `${blockName}.tsx`);
|
|
3370
|
+
const indexFile = path11__default.default.join(blockPath, "index.ts");
|
|
3133
3371
|
if (!fs__default.default.existsSync(schemaFile)) {
|
|
3134
3372
|
issues.push({
|
|
3135
3373
|
type: "error",
|
|
@@ -3155,13 +3393,13 @@ async function validateCommand(options) {
|
|
|
3155
3393
|
}
|
|
3156
3394
|
if (fs__default.default.existsSync(sectionsDir)) {
|
|
3157
3395
|
const sections = fs__default.default.readdirSync(sectionsDir).filter(
|
|
3158
|
-
(name) => fs__default.default.statSync(
|
|
3396
|
+
(name) => fs__default.default.statSync(path11__default.default.join(sectionsDir, name)).isDirectory()
|
|
3159
3397
|
);
|
|
3160
3398
|
for (const sectionName of sections) {
|
|
3161
|
-
const sectionPath =
|
|
3399
|
+
const sectionPath = path11__default.default.join(sectionsDir, sectionName);
|
|
3162
3400
|
const tsxFiles = fs__default.default.readdirSync(sectionPath).filter((f) => f.endsWith(".tsx") && !f.endsWith(".schema.ts"));
|
|
3163
3401
|
for (const tsxFile of tsxFiles) {
|
|
3164
|
-
const filePath =
|
|
3402
|
+
const filePath = path11__default.default.join(sectionPath, tsxFile);
|
|
3165
3403
|
const content = fs__default.default.readFileSync(filePath, "utf-8");
|
|
3166
3404
|
const relPath = `sections/${sectionName}/${tsxFile}`;
|
|
3167
3405
|
if (!content.includes('"use client"') && !content.includes("'use client'")) {
|
|
@@ -3209,12 +3447,12 @@ async function validateCommand(options) {
|
|
|
3209
3447
|
}
|
|
3210
3448
|
}
|
|
3211
3449
|
}
|
|
3212
|
-
const registryPath =
|
|
3213
|
-
const bundleEntryPath =
|
|
3450
|
+
const registryPath = path11__default.default.join(themePath, "sections-registry.ts");
|
|
3451
|
+
const bundleEntryPath = path11__default.default.join(themePath, "bundle-entry.ts");
|
|
3214
3452
|
const registryContent = fs__default.default.existsSync(registryPath) ? fs__default.default.readFileSync(registryPath, "utf-8") : fs__default.default.existsSync(bundleEntryPath) ? fs__default.default.readFileSync(bundleEntryPath, "utf-8") : "";
|
|
3215
3453
|
if (fs__default.default.existsSync(sectionsDir) && registryContent) {
|
|
3216
3454
|
const sections = fs__default.default.readdirSync(sectionsDir).filter(
|
|
3217
|
-
(name) => fs__default.default.statSync(
|
|
3455
|
+
(name) => fs__default.default.statSync(path11__default.default.join(sectionsDir, name)).isDirectory()
|
|
3218
3456
|
);
|
|
3219
3457
|
for (const sectionName of sections) {
|
|
3220
3458
|
if (!registryContent.includes(`sections/${sectionName}`) && !registryContent.includes(`"${sectionName}"`)) {
|
|
@@ -3237,7 +3475,7 @@ async function validateCommand(options) {
|
|
|
3237
3475
|
});
|
|
3238
3476
|
}
|
|
3239
3477
|
}
|
|
3240
|
-
const pagesDir =
|
|
3478
|
+
const pagesDir = path11__default.default.join(themePath, "pages");
|
|
3241
3479
|
if (fs__default.default.existsSync(pagesDir)) {
|
|
3242
3480
|
const allSchemaTypeSet = new Set(
|
|
3243
3481
|
schemaTypes.map((s) => s.schemaType || s.folderName)
|
|
@@ -3289,9 +3527,9 @@ async function validateCommand(options) {
|
|
|
3289
3527
|
}
|
|
3290
3528
|
async function loadSchemaTypes(themePath, sectionsDir) {
|
|
3291
3529
|
const results = [];
|
|
3292
|
-
const sections = fs__default.default.readdirSync(sectionsDir).filter((name) => fs__default.default.statSync(
|
|
3530
|
+
const sections = fs__default.default.readdirSync(sectionsDir).filter((name) => fs__default.default.statSync(path11__default.default.join(sectionsDir, name)).isDirectory());
|
|
3293
3531
|
for (const sectionName of sections) {
|
|
3294
|
-
const schemaFile =
|
|
3532
|
+
const schemaFile = path11__default.default.join(
|
|
3295
3533
|
sectionsDir,
|
|
3296
3534
|
sectionName,
|
|
3297
3535
|
`${sectionName}.schema.ts`
|
|
@@ -3329,7 +3567,7 @@ async function validatePageSectionTypes(pagesDir, validTypes) {
|
|
|
3329
3567
|
const issues = [];
|
|
3330
3568
|
const files = fs__default.default.readdirSync(pagesDir).filter((f) => f.match(/\.(ts|js)$/));
|
|
3331
3569
|
for (const file of files) {
|
|
3332
|
-
const content = fs__default.default.readFileSync(
|
|
3570
|
+
const content = fs__default.default.readFileSync(path11__default.default.join(pagesDir, file), "utf-8");
|
|
3333
3571
|
const pageName = file.replace(/\.(ts|js)$/, "");
|
|
3334
3572
|
const sectionsMatch = content.match(/\bsections:\s*\[/);
|
|
3335
3573
|
if (!sectionsMatch || sectionsMatch.index === void 0) continue;
|
|
@@ -3342,9 +3580,13 @@ async function validatePageSectionTypes(pagesDir, validTypes) {
|
|
|
3342
3580
|
endIdx = i;
|
|
3343
3581
|
}
|
|
3344
3582
|
const sectionsBlock = content.slice(startIdx, endIdx);
|
|
3345
|
-
const
|
|
3346
|
-
|
|
3583
|
+
const sectionTypeMatches = sectionsBlock.matchAll(
|
|
3584
|
+
/\bid:\s*["'][^"']*["'],\s*\n?\s*type:\s*["']([^"']+)["']/g
|
|
3585
|
+
);
|
|
3586
|
+
for (const match of sectionTypeMatches) {
|
|
3347
3587
|
const sectionType = match[1];
|
|
3588
|
+
if (COMPONENT_TYPES.has(sectionType)) continue;
|
|
3589
|
+
if (BLOCK_TYPES.has(sectionType)) continue;
|
|
3348
3590
|
if (!validTypes.has(sectionType)) {
|
|
3349
3591
|
issues.push({
|
|
3350
3592
|
type: "error",
|
|
@@ -3397,6 +3639,64 @@ var FIELD_TYPES = /* @__PURE__ */ new Set([
|
|
|
3397
3639
|
"inline_richtext",
|
|
3398
3640
|
"repeater"
|
|
3399
3641
|
]);
|
|
3642
|
+
var COMPONENT_TYPES = /* @__PURE__ */ new Set([
|
|
3643
|
+
"heading",
|
|
3644
|
+
"paragraph",
|
|
3645
|
+
"button",
|
|
3646
|
+
"image",
|
|
3647
|
+
"link",
|
|
3648
|
+
"icon",
|
|
3649
|
+
"badge",
|
|
3650
|
+
"divider",
|
|
3651
|
+
"spacer",
|
|
3652
|
+
"container",
|
|
3653
|
+
"grid",
|
|
3654
|
+
"columns",
|
|
3655
|
+
"card",
|
|
3656
|
+
"quote",
|
|
3657
|
+
"input",
|
|
3658
|
+
"textarea",
|
|
3659
|
+
"checkbox",
|
|
3660
|
+
"select",
|
|
3661
|
+
"video",
|
|
3662
|
+
"gallery",
|
|
3663
|
+
"alert",
|
|
3664
|
+
"progress",
|
|
3665
|
+
"rating",
|
|
3666
|
+
"timer",
|
|
3667
|
+
"list",
|
|
3668
|
+
"table",
|
|
3669
|
+
"accordion",
|
|
3670
|
+
"tabs",
|
|
3671
|
+
"code",
|
|
3672
|
+
"map",
|
|
3673
|
+
"product-card",
|
|
3674
|
+
"blog-card",
|
|
3675
|
+
"social-links",
|
|
3676
|
+
"hotline-contacts",
|
|
3677
|
+
"company-info",
|
|
3678
|
+
"torn-separator"
|
|
3679
|
+
]);
|
|
3680
|
+
var BLOCK_TYPES = /* @__PURE__ */ new Set([
|
|
3681
|
+
"brand-feature",
|
|
3682
|
+
"collection-item",
|
|
3683
|
+
"crafting-step",
|
|
3684
|
+
"testimonial-item",
|
|
3685
|
+
"stat-item",
|
|
3686
|
+
"footer-link",
|
|
3687
|
+
"navigation-links-block",
|
|
3688
|
+
"policy-section",
|
|
3689
|
+
"core-value-card",
|
|
3690
|
+
"faq-item",
|
|
3691
|
+
"feature-item",
|
|
3692
|
+
"gallery-item",
|
|
3693
|
+
"logo-item",
|
|
3694
|
+
"pricing-tier",
|
|
3695
|
+
"service-item",
|
|
3696
|
+
"stat-card",
|
|
3697
|
+
"team-member",
|
|
3698
|
+
"hero-content"
|
|
3699
|
+
]);
|
|
3400
3700
|
|
|
3401
3701
|
// src/commands/build.ts
|
|
3402
3702
|
init_logger();
|
|
@@ -3407,14 +3707,14 @@ async function buildCommand(options) {
|
|
|
3407
3707
|
if (options.theme) {
|
|
3408
3708
|
themeName = options.theme;
|
|
3409
3709
|
try {
|
|
3410
|
-
const workspaceThemePath =
|
|
3710
|
+
const workspaceThemePath = path11__default.default.join(getThemesDir(), themeName);
|
|
3411
3711
|
if (fs__default.default.existsSync(workspaceThemePath)) {
|
|
3412
3712
|
themePath = workspaceThemePath;
|
|
3413
3713
|
} else {
|
|
3414
|
-
themePath =
|
|
3714
|
+
themePath = path11__default.default.join(process.cwd(), themeName);
|
|
3415
3715
|
}
|
|
3416
3716
|
} catch {
|
|
3417
|
-
themePath =
|
|
3717
|
+
themePath = path11__default.default.join(process.cwd(), themeName);
|
|
3418
3718
|
}
|
|
3419
3719
|
if (!fs__default.default.existsSync(themePath)) {
|
|
3420
3720
|
logger.error(`Theme "${themeName}" not found.`);
|
|
@@ -3425,10 +3725,10 @@ async function buildCommand(options) {
|
|
|
3425
3725
|
"theme.config.ts",
|
|
3426
3726
|
"bundle-entry.ts",
|
|
3427
3727
|
"manifest.ts"
|
|
3428
|
-
].some((f) => fs__default.default.existsSync(
|
|
3728
|
+
].some((f) => fs__default.default.existsSync(path11__default.default.join(process.cwd(), f)));
|
|
3429
3729
|
if (isThemeDir2) {
|
|
3430
3730
|
themePath = process.cwd();
|
|
3431
|
-
themeName =
|
|
3731
|
+
themeName = path11__default.default.basename(themePath);
|
|
3432
3732
|
logger.info(`Building current theme: ${themeName}`);
|
|
3433
3733
|
} else {
|
|
3434
3734
|
logger.error(
|
|
@@ -3437,7 +3737,7 @@ async function buildCommand(options) {
|
|
|
3437
3737
|
process.exit(1);
|
|
3438
3738
|
}
|
|
3439
3739
|
}
|
|
3440
|
-
const packageJsonPath =
|
|
3740
|
+
const packageJsonPath = path11__default.default.join(themePath, "package.json");
|
|
3441
3741
|
const hasPkgJson = fs__default.default.existsSync(packageJsonPath);
|
|
3442
3742
|
if (!hasPkgJson) {
|
|
3443
3743
|
logger.warning(
|
|
@@ -3493,9 +3793,9 @@ async function buildCommand(options) {
|
|
|
3493
3793
|
logger.success("\u2713 Theme built successfully!");
|
|
3494
3794
|
logger.newLine();
|
|
3495
3795
|
logger.info(`Theme: ${themeName}`);
|
|
3496
|
-
const distPath =
|
|
3796
|
+
const distPath = path11__default.default.join(themePath, "dist");
|
|
3497
3797
|
if (fs__default.default.existsSync(distPath)) {
|
|
3498
|
-
logger.log(`Output: ${
|
|
3798
|
+
logger.log(`Output: ${path11__default.default.relative(process.cwd(), distPath)}`);
|
|
3499
3799
|
const files = fs__default.default.readdirSync(distPath);
|
|
3500
3800
|
logger.log(`Files: ${files.length}`);
|
|
3501
3801
|
}
|
|
@@ -3551,7 +3851,7 @@ async function packageCommand(options) {
|
|
|
3551
3851
|
let themeName;
|
|
3552
3852
|
if (options.theme) {
|
|
3553
3853
|
themeName = options.theme;
|
|
3554
|
-
themePath =
|
|
3854
|
+
themePath = path11__default.default.join(getThemesDir(), themeName);
|
|
3555
3855
|
if (!fs__default.default.existsSync(themePath)) {
|
|
3556
3856
|
logger.error(`Theme "${themeName}" not found.`);
|
|
3557
3857
|
process.exit(1);
|
|
@@ -3561,10 +3861,10 @@ async function packageCommand(options) {
|
|
|
3561
3861
|
"theme.config.ts",
|
|
3562
3862
|
"bundle-entry.ts",
|
|
3563
3863
|
"manifest.ts"
|
|
3564
|
-
].some((f) => fs__default.default.existsSync(
|
|
3864
|
+
].some((f) => fs__default.default.existsSync(path11__default.default.join(process.cwd(), f)));
|
|
3565
3865
|
if (isThemeDir2) {
|
|
3566
3866
|
themePath = process.cwd();
|
|
3567
|
-
themeName =
|
|
3867
|
+
themeName = path11__default.default.basename(themePath);
|
|
3568
3868
|
logger.info(`Packaging current theme: ${themeName}`);
|
|
3569
3869
|
} else {
|
|
3570
3870
|
logger.error(
|
|
@@ -3573,7 +3873,7 @@ async function packageCommand(options) {
|
|
|
3573
3873
|
process.exit(1);
|
|
3574
3874
|
}
|
|
3575
3875
|
}
|
|
3576
|
-
const packageJsonPath =
|
|
3876
|
+
const packageJsonPath = path11__default.default.join(themePath, "package.json");
|
|
3577
3877
|
let version2 = "1.0.0";
|
|
3578
3878
|
if (fs__default.default.existsSync(packageJsonPath)) {
|
|
3579
3879
|
const packageJson = await fs__default.default.readJson(packageJsonPath);
|
|
@@ -3583,7 +3883,7 @@ async function packageCommand(options) {
|
|
|
3583
3883
|
logger.info(`Theme: ${themeName}`);
|
|
3584
3884
|
logger.info(`Version: ${version2}`);
|
|
3585
3885
|
logger.newLine();
|
|
3586
|
-
const compiledThemePath =
|
|
3886
|
+
const compiledThemePath = path11__default.default.join(
|
|
3587
3887
|
process.cwd(),
|
|
3588
3888
|
"themes",
|
|
3589
3889
|
themeName,
|
|
@@ -3617,8 +3917,8 @@ async function packageCommand(options) {
|
|
|
3617
3917
|
logger.newLine();
|
|
3618
3918
|
logger.section("Step 2: Create Package");
|
|
3619
3919
|
const packageName = options.name || `${themeName}-${version2}`;
|
|
3620
|
-
const outputDir = options.output ||
|
|
3621
|
-
const outputPath =
|
|
3920
|
+
const outputDir = options.output || path11__default.default.join(process.cwd(), "dist");
|
|
3921
|
+
const outputPath = path11__default.default.join(outputDir, `${packageName}.zip`);
|
|
3622
3922
|
await fs__default.default.ensureDir(outputDir);
|
|
3623
3923
|
logger.startSpinner("Creating zip archive...");
|
|
3624
3924
|
try {
|
|
@@ -3631,11 +3931,11 @@ async function packageCommand(options) {
|
|
|
3631
3931
|
logger.newLine();
|
|
3632
3932
|
logger.info(`Package: ${packageName}.zip`);
|
|
3633
3933
|
logger.log(`Size: ${sizeMB} MB`);
|
|
3634
|
-
logger.log(`Location: ${
|
|
3934
|
+
logger.log(`Location: ${path11__default.default.relative(process.cwd(), outputPath)}`);
|
|
3635
3935
|
logger.newLine();
|
|
3636
3936
|
logger.section("Next steps:");
|
|
3637
3937
|
logger.log(
|
|
3638
|
-
` onexthm deploy --package ${
|
|
3938
|
+
` onexthm deploy --package ${path11__default.default.relative(process.cwd(), outputPath)}`
|
|
3639
3939
|
);
|
|
3640
3940
|
} catch (error) {
|
|
3641
3941
|
logger.stopSpinner(false, "Failed to create package");
|
|
@@ -3693,9 +3993,9 @@ async function deployCommand(options) {
|
|
|
3693
3993
|
ensureOneXProject();
|
|
3694
3994
|
let packagePath;
|
|
3695
3995
|
if (options.package) {
|
|
3696
|
-
packagePath =
|
|
3996
|
+
packagePath = path11__default.default.resolve(options.package);
|
|
3697
3997
|
} else if (options.theme) {
|
|
3698
|
-
const distDir =
|
|
3998
|
+
const distDir = path11__default.default.join(process.cwd(), "dist");
|
|
3699
3999
|
if (!fs__default.default.existsSync(distDir)) {
|
|
3700
4000
|
logger.error("No dist/ directory found. Run 'onexthm package' first.");
|
|
3701
4001
|
process.exit(1);
|
|
@@ -3710,7 +4010,7 @@ async function deployCommand(options) {
|
|
|
3710
4010
|
process.exit(1);
|
|
3711
4011
|
}
|
|
3712
4012
|
packageFiles.sort().reverse();
|
|
3713
|
-
packagePath =
|
|
4013
|
+
packagePath = path11__default.default.join(distDir, packageFiles[0]);
|
|
3714
4014
|
} else {
|
|
3715
4015
|
logger.error("Either --package or --theme must be specified.");
|
|
3716
4016
|
logger.info("Examples:");
|
|
@@ -3724,11 +4024,11 @@ async function deployCommand(options) {
|
|
|
3724
4024
|
}
|
|
3725
4025
|
const stats = await fs__default.default.stat(packagePath);
|
|
3726
4026
|
const sizeMB = (stats.size / 1024 / 1024).toFixed(2);
|
|
3727
|
-
const fileName =
|
|
4027
|
+
const fileName = path11__default.default.basename(packagePath);
|
|
3728
4028
|
logger.newLine();
|
|
3729
4029
|
logger.info(`Package: ${fileName}`);
|
|
3730
4030
|
logger.log(`Size: ${sizeMB} MB`);
|
|
3731
|
-
logger.log(`Path: ${
|
|
4031
|
+
logger.log(`Path: ${path11__default.default.relative(process.cwd(), packagePath)}`);
|
|
3732
4032
|
logger.newLine();
|
|
3733
4033
|
const apiUrl = options.apiUrl || process.env.ONEX_API_URL || "http://localhost:3001";
|
|
3734
4034
|
const uploadEndpoint = `${apiUrl}/website-api/themes/upload`;
|
|
@@ -3885,8 +4185,8 @@ async function downloadBundleZip(apiUrl, themeId, version2) {
|
|
|
3885
4185
|
async function createCompatibilityFiles(outputDir, manifest) {
|
|
3886
4186
|
const entryFile = manifest.output?.entry || "bundle-entry.js";
|
|
3887
4187
|
if (entryFile !== "bundle-entry.js" && entryFile.startsWith("bundle-entry-")) {
|
|
3888
|
-
const hashedPath =
|
|
3889
|
-
const stablePath =
|
|
4188
|
+
const hashedPath = path11__default.default.join(outputDir, entryFile);
|
|
4189
|
+
const stablePath = path11__default.default.join(outputDir, "bundle-entry.js");
|
|
3890
4190
|
if (await fs__default.default.pathExists(hashedPath)) {
|
|
3891
4191
|
await fs__default.default.copy(hashedPath, stablePath);
|
|
3892
4192
|
const mapPath = hashedPath + ".map";
|
|
@@ -3895,13 +4195,13 @@ async function createCompatibilityFiles(outputDir, manifest) {
|
|
|
3895
4195
|
}
|
|
3896
4196
|
}
|
|
3897
4197
|
}
|
|
3898
|
-
const sectionsRegistryPath =
|
|
4198
|
+
const sectionsRegistryPath = path11__default.default.join(outputDir, "sections-registry.js");
|
|
3899
4199
|
const content = `// Re-export all sections from bundle-entry
|
|
3900
4200
|
// This file exists to maintain compatibility with the import path
|
|
3901
4201
|
export * from './bundle-entry.js';
|
|
3902
4202
|
`;
|
|
3903
4203
|
await fs__default.default.writeFile(sectionsRegistryPath, content, "utf-8");
|
|
3904
|
-
const pkgJsonPath =
|
|
4204
|
+
const pkgJsonPath = path11__default.default.join(outputDir, "package.json");
|
|
3905
4205
|
await fs__default.default.writeFile(pkgJsonPath, '{\n "type": "module"\n}\n', "utf-8");
|
|
3906
4206
|
}
|
|
3907
4207
|
function showDownloadFailureHelp(themeId, apiUrl) {
|
|
@@ -4000,7 +4300,7 @@ async function downloadCommand(options) {
|
|
|
4000
4300
|
zip.extractAllTo(outputDir, true);
|
|
4001
4301
|
const entries = zip.getEntries().filter((e) => !e.isDirectory);
|
|
4002
4302
|
spinner.succeed(`Extracted ${entries.length} files to ${outputDir}`);
|
|
4003
|
-
const manifestPath =
|
|
4303
|
+
const manifestPath = path11__default.default.join(outputDir, "manifest.json");
|
|
4004
4304
|
const manifest = await fs__default.default.readJson(manifestPath);
|
|
4005
4305
|
await createCompatibilityFiles(outputDir, manifest);
|
|
4006
4306
|
console.log();
|
|
@@ -4121,7 +4421,7 @@ async function renameTheme(themeDir, oldName, newName) {
|
|
|
4121
4421
|
const oldPrefix = `${oldName}-`;
|
|
4122
4422
|
const newPrefix = `${newName}-`;
|
|
4123
4423
|
const newDisplayName = newName.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
4124
|
-
const pkgPath =
|
|
4424
|
+
const pkgPath = path11__default.default.join(themeDir, "package.json");
|
|
4125
4425
|
if (await fs__default.default.pathExists(pkgPath)) {
|
|
4126
4426
|
const pkg = await fs__default.default.readJson(pkgPath);
|
|
4127
4427
|
pkg.name = `@onex-themes/${newName}`;
|
|
@@ -4137,7 +4437,7 @@ async function renameTheme(themeDir, oldName, newName) {
|
|
|
4137
4437
|
}
|
|
4138
4438
|
await fs__default.default.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
4139
4439
|
}
|
|
4140
|
-
const configPath =
|
|
4440
|
+
const configPath = path11__default.default.join(themeDir, "theme.config.ts");
|
|
4141
4441
|
if (await fs__default.default.pathExists(configPath)) {
|
|
4142
4442
|
let content = await fs__default.default.readFile(configPath, "utf-8");
|
|
4143
4443
|
content = content.replace(/id:\s*"[^"]*"/, `id: "${newName}"`);
|
|
@@ -4147,7 +4447,7 @@ async function renameTheme(themeDir, oldName, newName) {
|
|
|
4147
4447
|
);
|
|
4148
4448
|
await fs__default.default.writeFile(configPath, content);
|
|
4149
4449
|
}
|
|
4150
|
-
const layoutPath =
|
|
4450
|
+
const layoutPath = path11__default.default.join(themeDir, "theme.layout.ts");
|
|
4151
4451
|
if (await fs__default.default.pathExists(layoutPath)) {
|
|
4152
4452
|
let content = await fs__default.default.readFile(layoutPath, "utf-8");
|
|
4153
4453
|
content = content.replace(/id:\s*"[^"]*"/, `id: "${newName}"`);
|
|
@@ -4160,7 +4460,7 @@ async function renameTheme(themeDir, oldName, newName) {
|
|
|
4160
4460
|
const oldDisplayName = oldName.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
4161
4461
|
const tsFiles = await glob.glob("**/*.ts", { cwd: themeDir, nodir: true });
|
|
4162
4462
|
for (const file of tsFiles) {
|
|
4163
|
-
const filePath =
|
|
4463
|
+
const filePath = path11__default.default.join(themeDir, file);
|
|
4164
4464
|
let content = await fs__default.default.readFile(filePath, "utf-8");
|
|
4165
4465
|
const original = content;
|
|
4166
4466
|
content = content.replace(
|
|
@@ -4203,7 +4503,7 @@ async function cloneCommand(themeName, options) {
|
|
|
4203
4503
|
}
|
|
4204
4504
|
const spinner = ora__default.default("Initializing clone...").start();
|
|
4205
4505
|
try {
|
|
4206
|
-
const outputDir = options.output ||
|
|
4506
|
+
const outputDir = options.output || path11__default.default.resolve(process.cwd(), newName);
|
|
4207
4507
|
if (await fs__default.default.pathExists(outputDir)) {
|
|
4208
4508
|
spinner.fail(chalk4__default.default.red(`Directory already exists: ${outputDir}`));
|
|
4209
4509
|
logger.info(
|
|
@@ -4249,7 +4549,7 @@ async function cloneCommand(themeName, options) {
|
|
|
4249
4549
|
spinner.succeed(
|
|
4250
4550
|
`Renamed theme: ${chalk4__default.default.gray(themeName)} \u2192 ${chalk4__default.default.cyan(newName)}`
|
|
4251
4551
|
);
|
|
4252
|
-
const envExamplePath =
|
|
4552
|
+
const envExamplePath = path11__default.default.join(outputDir, ".env.example");
|
|
4253
4553
|
if (!await fs__default.default.pathExists(envExamplePath)) {
|
|
4254
4554
|
await fs__default.default.writeFile(
|
|
4255
4555
|
envExamplePath,
|
|
@@ -4262,7 +4562,7 @@ async function cloneCommand(themeName, options) {
|
|
|
4262
4562
|
].join("\n")
|
|
4263
4563
|
);
|
|
4264
4564
|
}
|
|
4265
|
-
const mcpJsonPath =
|
|
4565
|
+
const mcpJsonPath = path11__default.default.join(outputDir, ".mcp.json");
|
|
4266
4566
|
if (await fs__default.default.pathExists(mcpJsonPath)) {
|
|
4267
4567
|
const { default: inquirerMod } = await import('inquirer');
|
|
4268
4568
|
const { figmaApiKey } = await inquirerMod.prompt([
|
|
@@ -4287,7 +4587,7 @@ async function cloneCommand(themeName, options) {
|
|
|
4287
4587
|
}
|
|
4288
4588
|
if (options.install !== false) {
|
|
4289
4589
|
const hasPkgJson = await fs__default.default.pathExists(
|
|
4290
|
-
|
|
4590
|
+
path11__default.default.join(outputDir, "package.json")
|
|
4291
4591
|
);
|
|
4292
4592
|
if (hasPkgJson) {
|
|
4293
4593
|
spinner.start("Installing dependencies...");
|
|
@@ -4315,7 +4615,7 @@ async function cloneCommand(themeName, options) {
|
|
|
4315
4615
|
console.log(chalk4__default.default.cyan(" Files: ") + chalk4__default.default.white(entries.length));
|
|
4316
4616
|
console.log();
|
|
4317
4617
|
console.log(chalk4__default.default.cyan("Next steps:"));
|
|
4318
|
-
console.log(chalk4__default.default.gray(` cd ${
|
|
4618
|
+
console.log(chalk4__default.default.gray(` cd ${path11__default.default.relative(process.cwd(), outputDir)}`));
|
|
4319
4619
|
console.log(
|
|
4320
4620
|
chalk4__default.default.gray(" cp .env.example .env # then add your Company ID")
|
|
4321
4621
|
);
|
|
@@ -4342,14 +4642,14 @@ async function devCommand(options) {
|
|
|
4342
4642
|
if (options.theme) {
|
|
4343
4643
|
themeName = options.theme;
|
|
4344
4644
|
try {
|
|
4345
|
-
const workspaceThemePath =
|
|
4645
|
+
const workspaceThemePath = path11__default.default.join(getThemesDir(), themeName);
|
|
4346
4646
|
if (fs__default.default.existsSync(workspaceThemePath)) {
|
|
4347
4647
|
themePath = workspaceThemePath;
|
|
4348
4648
|
} else {
|
|
4349
|
-
themePath =
|
|
4649
|
+
themePath = path11__default.default.join(process.cwd(), themeName);
|
|
4350
4650
|
}
|
|
4351
4651
|
} catch {
|
|
4352
|
-
themePath =
|
|
4652
|
+
themePath = path11__default.default.join(process.cwd(), themeName);
|
|
4353
4653
|
}
|
|
4354
4654
|
if (!fs__default.default.existsSync(themePath)) {
|
|
4355
4655
|
logger.error(`Theme "${themeName}" not found.`);
|
|
@@ -4360,10 +4660,10 @@ async function devCommand(options) {
|
|
|
4360
4660
|
"theme.config.ts",
|
|
4361
4661
|
"bundle-entry.ts",
|
|
4362
4662
|
"manifest.ts"
|
|
4363
|
-
].some((f) => fs__default.default.existsSync(
|
|
4663
|
+
].some((f) => fs__default.default.existsSync(path11__default.default.join(process.cwd(), f)));
|
|
4364
4664
|
if (isThemeDir2) {
|
|
4365
4665
|
themePath = process.cwd();
|
|
4366
|
-
themeName =
|
|
4666
|
+
themeName = path11__default.default.basename(themePath);
|
|
4367
4667
|
} else {
|
|
4368
4668
|
logger.error(
|
|
4369
4669
|
"Not in a theme directory and no --theme specified. Run from theme root or use --theme flag."
|
|
@@ -4432,9 +4732,9 @@ async function devCommand(options) {
|
|
|
4432
4732
|
watcher.close();
|
|
4433
4733
|
await context2.dispose();
|
|
4434
4734
|
server.close();
|
|
4435
|
-
const shimPath =
|
|
4735
|
+
const shimPath = path11__default.default.join(outputDir, ".process-shim.js");
|
|
4436
4736
|
try {
|
|
4437
|
-
await
|
|
4737
|
+
await fs9__default.default.unlink(shimPath);
|
|
4438
4738
|
} catch {
|
|
4439
4739
|
}
|
|
4440
4740
|
process.exit(0);
|
|
@@ -4443,8 +4743,8 @@ async function devCommand(options) {
|
|
|
4443
4743
|
|
|
4444
4744
|
// src/commands/config.ts
|
|
4445
4745
|
init_logger();
|
|
4446
|
-
var CONFIG_DIR =
|
|
4447
|
-
var CONFIG_FILE =
|
|
4746
|
+
var CONFIG_DIR = path11__default.default.join(os__default.default.homedir(), ".onexthm");
|
|
4747
|
+
var CONFIG_FILE = path11__default.default.join(CONFIG_DIR, ".env");
|
|
4448
4748
|
var CONFIG_ENTRIES = [
|
|
4449
4749
|
{
|
|
4450
4750
|
key: "AWS_ACCESS_KEY_ID",
|
|
@@ -4712,91 +5012,357 @@ async function whoamiCommand(options = {}) {
|
|
|
4712
5012
|
|
|
4713
5013
|
// src/commands/publish.ts
|
|
4714
5014
|
init_logger();
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
|
|
4738
|
-
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4746
|
-
|
|
4747
|
-
|
|
5015
|
+
init_scan_theme_assets();
|
|
5016
|
+
|
|
5017
|
+
// src/utils/fetch-prior-schemas.ts
|
|
5018
|
+
async function fetchPriorGateManifests(themeId, env) {
|
|
5019
|
+
const apiUrl = getApiUrl(env);
|
|
5020
|
+
const url = `${apiUrl}/website-api/themes/${encodeURIComponent(themeId)}/gate-manifests/latest`;
|
|
5021
|
+
let res;
|
|
5022
|
+
try {
|
|
5023
|
+
res = await authenticatedFetch(url, { method: "GET" }, env);
|
|
5024
|
+
} catch (err) {
|
|
5025
|
+
return {
|
|
5026
|
+
result: null,
|
|
5027
|
+
reason: `network error: ${err instanceof Error ? err.message : "unknown"}`
|
|
5028
|
+
};
|
|
5029
|
+
}
|
|
5030
|
+
if (res.status === 404) {
|
|
5031
|
+
return { result: null, reason: "no-prior" };
|
|
5032
|
+
}
|
|
5033
|
+
if (!res.ok) {
|
|
5034
|
+
return {
|
|
5035
|
+
result: null,
|
|
5036
|
+
reason: `server returned ${res.status} ${res.statusText}`
|
|
5037
|
+
};
|
|
5038
|
+
}
|
|
5039
|
+
let data;
|
|
5040
|
+
try {
|
|
5041
|
+
data = await res.json();
|
|
5042
|
+
} catch {
|
|
5043
|
+
return { result: null, reason: "non-JSON response from server" };
|
|
5044
|
+
}
|
|
5045
|
+
const body = data.statusCode ? data.body : data;
|
|
5046
|
+
if (!body || typeof body.version !== "string" || !body.schemas || !body.assets) {
|
|
5047
|
+
return { result: null, reason: "malformed response (missing fields)" };
|
|
5048
|
+
}
|
|
5049
|
+
return {
|
|
5050
|
+
result: {
|
|
5051
|
+
version: body.version,
|
|
5052
|
+
schemas: body.schemas,
|
|
5053
|
+
assets: body.assets
|
|
5054
|
+
},
|
|
5055
|
+
reason: null
|
|
5056
|
+
};
|
|
4748
5057
|
}
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
|
|
5058
|
+
|
|
5059
|
+
// src/utils/schema-diff.ts
|
|
5060
|
+
var SEVERITY = {
|
|
5061
|
+
safe: 0,
|
|
5062
|
+
"safe-rename": 1,
|
|
5063
|
+
"defaults-only": 2,
|
|
5064
|
+
additive: 3,
|
|
5065
|
+
breaking: 4,
|
|
5066
|
+
"breaking-asset": 5,
|
|
5067
|
+
"breaking-severe": 6
|
|
5068
|
+
};
|
|
5069
|
+
var BUMP_FOR = {
|
|
5070
|
+
safe: "patch",
|
|
5071
|
+
"safe-rename": "patch",
|
|
5072
|
+
"defaults-only": "patch",
|
|
5073
|
+
additive: "minor",
|
|
5074
|
+
breaking: "major",
|
|
5075
|
+
"breaking-asset": "major",
|
|
5076
|
+
"breaking-severe": "major"
|
|
5077
|
+
};
|
|
5078
|
+
function bumpFor(kind) {
|
|
5079
|
+
return BUMP_FOR[kind];
|
|
5080
|
+
}
|
|
5081
|
+
function maxSeverity(a, b) {
|
|
5082
|
+
return SEVERITY[a] >= SEVERITY[b] ? a : b;
|
|
5083
|
+
}
|
|
5084
|
+
function classify(changes) {
|
|
5085
|
+
let highest = "safe";
|
|
5086
|
+
for (const c of changes) {
|
|
5087
|
+
highest = maxSeverity(highest, c.kind);
|
|
5088
|
+
}
|
|
5089
|
+
return { bump: bumpFor(highest), highest, changes };
|
|
5090
|
+
}
|
|
5091
|
+
function diffManifests(prior, current) {
|
|
5092
|
+
const changes = [];
|
|
5093
|
+
const priorSections = prior.schemas.sections;
|
|
5094
|
+
const currentSections = current.schemas.sections;
|
|
5095
|
+
const sectionTypes = /* @__PURE__ */ new Set([
|
|
5096
|
+
...Object.keys(priorSections),
|
|
5097
|
+
...Object.keys(currentSections)
|
|
5098
|
+
]);
|
|
5099
|
+
for (const type of [...sectionTypes].sort()) {
|
|
5100
|
+
const p = priorSections[type];
|
|
5101
|
+
const c = currentSections[type];
|
|
5102
|
+
if (p && !c) {
|
|
5103
|
+
changes.push({
|
|
5104
|
+
kind: "breaking-severe",
|
|
5105
|
+
path: `sections.${type}`,
|
|
5106
|
+
detail: `Section type "${type}" removed. Pages using this section will render empty.`
|
|
5107
|
+
});
|
|
5108
|
+
continue;
|
|
5109
|
+
}
|
|
5110
|
+
if (!p && c) {
|
|
5111
|
+
changes.push({
|
|
5112
|
+
kind: "additive",
|
|
5113
|
+
path: `sections.${type}`,
|
|
5114
|
+
detail: `Section type "${type}" added.`
|
|
5115
|
+
});
|
|
5116
|
+
continue;
|
|
5117
|
+
}
|
|
5118
|
+
if (p && c) diffSection(p, c, changes);
|
|
5119
|
+
}
|
|
5120
|
+
diffAssets(prior.assets, current.assets, changes);
|
|
5121
|
+
return changes;
|
|
4752
5122
|
}
|
|
4753
|
-
|
|
4754
|
-
const
|
|
4755
|
-
|
|
5123
|
+
function diffSection(prior, current, out) {
|
|
5124
|
+
const type = current.type;
|
|
5125
|
+
if (JSON.stringify(prior.dataRequirements) !== JSON.stringify(current.dataRequirements)) {
|
|
5126
|
+
out.push({
|
|
5127
|
+
kind: "breaking",
|
|
5128
|
+
path: `sections.${type}.dataRequirements`,
|
|
5129
|
+
detail: "dataRequirements changed."
|
|
5130
|
+
});
|
|
5131
|
+
}
|
|
5132
|
+
diffFieldList(
|
|
5133
|
+
prior.settings,
|
|
5134
|
+
current.settings,
|
|
5135
|
+
`sections.${type}.settings`,
|
|
5136
|
+
out
|
|
5137
|
+
);
|
|
5138
|
+
diffDefaults(
|
|
5139
|
+
prior.defaults,
|
|
5140
|
+
current.defaults,
|
|
5141
|
+
`sections.${type}.defaults`,
|
|
5142
|
+
out
|
|
5143
|
+
);
|
|
5144
|
+
diffBlocks(prior.blocks, current.blocks, `sections.${type}.blocks`, out);
|
|
5145
|
+
}
|
|
5146
|
+
function diffBlocks(prior, current, pathPrefix, out) {
|
|
5147
|
+
const priorByType = new Map(prior.map((b) => [b.type, b]));
|
|
5148
|
+
const currentByType = new Map(current.map((b) => [b.type, b]));
|
|
5149
|
+
for (const type of /* @__PURE__ */ new Set([
|
|
5150
|
+
...priorByType.keys(),
|
|
5151
|
+
...currentByType.keys()
|
|
5152
|
+
])) {
|
|
5153
|
+
const p = priorByType.get(type);
|
|
5154
|
+
const c = currentByType.get(type);
|
|
5155
|
+
if (p && !c) {
|
|
5156
|
+
out.push({
|
|
5157
|
+
kind: "breaking",
|
|
5158
|
+
path: `${pathPrefix}.${type}`,
|
|
5159
|
+
detail: `Block type "${type}" removed.`
|
|
5160
|
+
});
|
|
5161
|
+
continue;
|
|
5162
|
+
}
|
|
5163
|
+
if (!p && c) {
|
|
5164
|
+
out.push({
|
|
5165
|
+
kind: "additive",
|
|
5166
|
+
path: `${pathPrefix}.${type}`,
|
|
5167
|
+
detail: `Block type "${type}" added.`
|
|
5168
|
+
});
|
|
5169
|
+
continue;
|
|
5170
|
+
}
|
|
5171
|
+
if (p && c) {
|
|
5172
|
+
diffFieldList(
|
|
5173
|
+
p.settings,
|
|
5174
|
+
c.settings,
|
|
5175
|
+
`${pathPrefix}.${type}.settings`,
|
|
5176
|
+
out
|
|
5177
|
+
);
|
|
5178
|
+
diffDefaults(
|
|
5179
|
+
p.defaults,
|
|
5180
|
+
c.defaults,
|
|
5181
|
+
`${pathPrefix}.${type}.defaults`,
|
|
5182
|
+
out
|
|
5183
|
+
);
|
|
5184
|
+
}
|
|
5185
|
+
}
|
|
4756
5186
|
}
|
|
4757
|
-
function
|
|
4758
|
-
const
|
|
4759
|
-
const
|
|
4760
|
-
const
|
|
4761
|
-
const
|
|
4762
|
-
|
|
4763
|
-
|
|
5187
|
+
function diffFieldList(prior, current, pathPrefix, out) {
|
|
5188
|
+
const priorById = new Map(prior.map((f) => [f.id, f]));
|
|
5189
|
+
const currentById = new Map(current.map((f) => [f.id, f]));
|
|
5190
|
+
const aliasToCurrent = /* @__PURE__ */ new Map();
|
|
5191
|
+
for (const f of current) {
|
|
5192
|
+
if (f.aliases) {
|
|
5193
|
+
for (const alias of f.aliases) {
|
|
5194
|
+
aliasToCurrent.set(alias, f);
|
|
5195
|
+
}
|
|
5196
|
+
}
|
|
5197
|
+
}
|
|
5198
|
+
for (const [id, p] of priorById) {
|
|
5199
|
+
const c = currentById.get(id);
|
|
5200
|
+
if (c) {
|
|
5201
|
+
diffFieldPair(p, c, `${pathPrefix}.${id}`, out);
|
|
5202
|
+
continue;
|
|
5203
|
+
}
|
|
5204
|
+
const renamed = aliasToCurrent.get(id);
|
|
5205
|
+
if (renamed) {
|
|
5206
|
+
if (renamed.type === p.type) {
|
|
5207
|
+
out.push({
|
|
5208
|
+
kind: "safe-rename",
|
|
5209
|
+
path: `${pathPrefix}.${id}`,
|
|
5210
|
+
detail: `Field "${id}" renamed to "${renamed.id}" (alias preserved).`
|
|
5211
|
+
});
|
|
5212
|
+
} else {
|
|
5213
|
+
out.push({
|
|
5214
|
+
kind: "breaking",
|
|
5215
|
+
path: `${pathPrefix}.${id}`,
|
|
5216
|
+
detail: `Field "${id}" renamed to "${renamed.id}" but type changed (${p.type} \u2192 ${renamed.type}).`
|
|
5217
|
+
});
|
|
5218
|
+
}
|
|
5219
|
+
} else {
|
|
5220
|
+
out.push({
|
|
5221
|
+
kind: "breaking",
|
|
5222
|
+
path: `${pathPrefix}.${id}`,
|
|
5223
|
+
detail: `Field "${id}" removed. Consider adding aliases: ["${id}"] to the replacement field if this was a rename.`
|
|
5224
|
+
});
|
|
5225
|
+
}
|
|
5226
|
+
}
|
|
5227
|
+
for (const [id, c] of currentById) {
|
|
5228
|
+
if (priorById.has(id)) continue;
|
|
5229
|
+
const coveredByAlias = c.aliases?.some((a) => priorById.has(a)) ?? false;
|
|
5230
|
+
if (coveredByAlias) continue;
|
|
5231
|
+
if (c.required && c.default === void 0) {
|
|
5232
|
+
out.push({
|
|
5233
|
+
kind: "breaking",
|
|
5234
|
+
path: `${pathPrefix}.${id}`,
|
|
5235
|
+
detail: `Required field "${id}" added with no default. Existing instances cannot satisfy it.`
|
|
5236
|
+
});
|
|
5237
|
+
} else {
|
|
5238
|
+
out.push({
|
|
5239
|
+
kind: "additive",
|
|
5240
|
+
path: `${pathPrefix}.${id}`,
|
|
5241
|
+
detail: `Field "${id}" added.`
|
|
5242
|
+
});
|
|
5243
|
+
}
|
|
5244
|
+
}
|
|
4764
5245
|
}
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
|
|
4778
|
-
|
|
4779
|
-
|
|
4780
|
-
|
|
4781
|
-
|
|
4782
|
-
|
|
4783
|
-
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
|
|
5246
|
+
function diffFieldPair(p, c, path23, out) {
|
|
5247
|
+
if (p.type !== c.type) {
|
|
5248
|
+
out.push({
|
|
5249
|
+
kind: "breaking",
|
|
5250
|
+
path: path23,
|
|
5251
|
+
detail: `Type changed (${p.type} \u2192 ${c.type}). Saved values may misrender.`
|
|
5252
|
+
});
|
|
5253
|
+
return;
|
|
5254
|
+
}
|
|
5255
|
+
if (p.required !== true && c.required === true) {
|
|
5256
|
+
out.push({
|
|
5257
|
+
kind: "breaking",
|
|
5258
|
+
path: path23,
|
|
5259
|
+
detail: "Field became required. Existing empty instances now invalid."
|
|
5260
|
+
});
|
|
5261
|
+
}
|
|
5262
|
+
if (typeof p.maxLength === "number" || typeof c.maxLength === "number") {
|
|
5263
|
+
if ((c.maxLength ?? Infinity) < (p.maxLength ?? Infinity)) {
|
|
5264
|
+
out.push({
|
|
5265
|
+
kind: "breaking",
|
|
5266
|
+
path: path23,
|
|
5267
|
+
detail: `maxLength tightened (${p.maxLength ?? "\u221E"} \u2192 ${c.maxLength}).`
|
|
5268
|
+
});
|
|
5269
|
+
}
|
|
5270
|
+
}
|
|
5271
|
+
if (typeof p.min === "number" || typeof c.min === "number") {
|
|
5272
|
+
if ((c.min ?? -Infinity) > (p.min ?? -Infinity)) {
|
|
5273
|
+
out.push({
|
|
5274
|
+
kind: "breaking",
|
|
5275
|
+
path: path23,
|
|
5276
|
+
detail: `min raised (${p.min ?? "-\u221E"} \u2192 ${c.min}).`
|
|
5277
|
+
});
|
|
5278
|
+
}
|
|
5279
|
+
}
|
|
5280
|
+
if (typeof p.max === "number" || typeof c.max === "number") {
|
|
5281
|
+
if ((c.max ?? Infinity) < (p.max ?? Infinity)) {
|
|
5282
|
+
out.push({
|
|
5283
|
+
kind: "breaking",
|
|
5284
|
+
path: path23,
|
|
5285
|
+
detail: `max lowered (${p.max ?? "\u221E"} \u2192 ${c.max}).`
|
|
5286
|
+
});
|
|
5287
|
+
}
|
|
5288
|
+
}
|
|
5289
|
+
if (p.options || c.options) {
|
|
5290
|
+
const priorOpts = new Set(p.options ?? []);
|
|
5291
|
+
const currentOpts = new Set(c.options ?? []);
|
|
5292
|
+
const removed = [...priorOpts].filter((o) => !currentOpts.has(o));
|
|
5293
|
+
const added = [...currentOpts].filter((o) => !priorOpts.has(o));
|
|
5294
|
+
if (removed.length > 0) {
|
|
5295
|
+
out.push({
|
|
5296
|
+
kind: "breaking",
|
|
5297
|
+
path: path23,
|
|
5298
|
+
detail: `Option(s) removed: ${removed.join(", ")}. Existing saved values may be orphaned.`
|
|
5299
|
+
});
|
|
5300
|
+
}
|
|
5301
|
+
if (added.length > 0) {
|
|
5302
|
+
out.push({
|
|
5303
|
+
kind: "additive",
|
|
5304
|
+
path: path23,
|
|
5305
|
+
detail: `Option(s) added: ${added.join(", ")}.`
|
|
5306
|
+
});
|
|
5307
|
+
}
|
|
5308
|
+
}
|
|
5309
|
+
if (!deepEqual(p.default, c.default)) {
|
|
5310
|
+
out.push({
|
|
5311
|
+
kind: "defaults-only",
|
|
5312
|
+
path: path23,
|
|
5313
|
+
detail: `Default changed: ${JSON.stringify(p.default)} \u2192 ${JSON.stringify(c.default)}.`
|
|
4789
5314
|
});
|
|
4790
5315
|
}
|
|
4791
|
-
results.sort((a, b) => a.originalPath.localeCompare(b.originalPath));
|
|
4792
|
-
return results;
|
|
4793
5316
|
}
|
|
4794
|
-
function
|
|
4795
|
-
const
|
|
4796
|
-
for (const
|
|
4797
|
-
|
|
5317
|
+
function diffDefaults(prior, current, pathPrefix, out) {
|
|
5318
|
+
const keys = /* @__PURE__ */ new Set([...Object.keys(prior), ...Object.keys(current)]);
|
|
5319
|
+
for (const key of [...keys].sort()) {
|
|
5320
|
+
if (!(key in prior) || !(key in current)) continue;
|
|
5321
|
+
if (!deepEqual(prior[key], current[key])) {
|
|
5322
|
+
out.push({
|
|
5323
|
+
kind: "defaults-only",
|
|
5324
|
+
path: `${pathPrefix}.${key}`,
|
|
5325
|
+
detail: `Default value changed.`
|
|
5326
|
+
});
|
|
5327
|
+
}
|
|
5328
|
+
}
|
|
5329
|
+
}
|
|
5330
|
+
function diffAssets(prior, current, out) {
|
|
5331
|
+
const currentPaths = new Set(current.assets.map((a) => a.path));
|
|
5332
|
+
for (const a of prior.assets) {
|
|
5333
|
+
if (!currentPaths.has(a.path)) {
|
|
5334
|
+
out.push({
|
|
5335
|
+
kind: "breaking-asset",
|
|
5336
|
+
path: `theme-assets/${a.path}`,
|
|
5337
|
+
detail: `Asset "${a.path}" was present in the prior version and is now missing. Code that references it hardcoded will break.`
|
|
5338
|
+
});
|
|
5339
|
+
}
|
|
4798
5340
|
}
|
|
4799
|
-
|
|
5341
|
+
}
|
|
5342
|
+
function deepEqual(a, b) {
|
|
5343
|
+
if (a === b) return true;
|
|
5344
|
+
if (a === null || b === null) return false;
|
|
5345
|
+
if (typeof a !== typeof b) return false;
|
|
5346
|
+
if (typeof a !== "object") return false;
|
|
5347
|
+
if (Array.isArray(a) !== Array.isArray(b)) return false;
|
|
5348
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
5349
|
+
if (a.length !== b.length) return false;
|
|
5350
|
+
for (let i = 0; i < a.length; i++) {
|
|
5351
|
+
if (!deepEqual(a[i], b[i])) return false;
|
|
5352
|
+
}
|
|
5353
|
+
return true;
|
|
5354
|
+
}
|
|
5355
|
+
const ak = Object.keys(a);
|
|
5356
|
+
const bk = Object.keys(b);
|
|
5357
|
+
if (ak.length !== bk.length) return false;
|
|
5358
|
+
for (const k of ak) {
|
|
5359
|
+
if (!deepEqual(
|
|
5360
|
+
a[k],
|
|
5361
|
+
b[k]
|
|
5362
|
+
))
|
|
5363
|
+
return false;
|
|
5364
|
+
}
|
|
5365
|
+
return true;
|
|
4800
5366
|
}
|
|
4801
5367
|
|
|
4802
5368
|
// src/commands/publish.ts
|
|
@@ -4815,13 +5381,13 @@ async function publishCommand(options) {
|
|
|
4815
5381
|
logger.info(`Logged in as: ${tokens.user.email}`);
|
|
4816
5382
|
let themePath;
|
|
4817
5383
|
if (options.theme) {
|
|
4818
|
-
themePath =
|
|
5384
|
+
themePath = path11__default.default.resolve(options.theme);
|
|
4819
5385
|
} else {
|
|
4820
5386
|
const isThemeDir2 = [
|
|
4821
5387
|
"theme.config.ts",
|
|
4822
5388
|
"bundle-entry.ts",
|
|
4823
5389
|
"manifest.ts"
|
|
4824
|
-
].some((f) => fs__default.default.existsSync(
|
|
5390
|
+
].some((f) => fs__default.default.existsSync(path11__default.default.join(process.cwd(), f)));
|
|
4825
5391
|
if (isThemeDir2) {
|
|
4826
5392
|
themePath = process.cwd();
|
|
4827
5393
|
} else {
|
|
@@ -4831,13 +5397,13 @@ async function publishCommand(options) {
|
|
|
4831
5397
|
process.exit(1);
|
|
4832
5398
|
}
|
|
4833
5399
|
}
|
|
4834
|
-
const pkgPath =
|
|
5400
|
+
const pkgPath = path11__default.default.join(themePath, "package.json");
|
|
4835
5401
|
if (!fs__default.default.existsSync(pkgPath)) {
|
|
4836
5402
|
logger.error("No package.json found in theme directory");
|
|
4837
5403
|
process.exit(1);
|
|
4838
5404
|
}
|
|
4839
5405
|
const pkg = fs__default.default.readJsonSync(pkgPath);
|
|
4840
|
-
const themeId = pkg.name?.replace("@onex-themes/", "") ||
|
|
5406
|
+
const themeId = pkg.name?.replace("@onex-themes/", "") || path11__default.default.basename(themePath);
|
|
4841
5407
|
if (options.bump) {
|
|
4842
5408
|
const currentVersion = pkg.version || "1.0.0";
|
|
4843
5409
|
const newVersion = semver__default.default.inc(currentVersion, options.bump);
|
|
@@ -4861,57 +5427,62 @@ async function publishCommand(options) {
|
|
|
4861
5427
|
logger.info(`Version: ${version2}`);
|
|
4862
5428
|
logger.newLine();
|
|
4863
5429
|
const apiUrl = getApiUrl(env);
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
|
|
5430
|
+
if (!options.dryRun) {
|
|
5431
|
+
logger.startSpinner("Registering theme...");
|
|
5432
|
+
try {
|
|
5433
|
+
const regResponse = await authenticatedFetch(
|
|
5434
|
+
`${apiUrl}/website-api/themes/register`,
|
|
5435
|
+
{
|
|
5436
|
+
method: "POST",
|
|
5437
|
+
body: JSON.stringify({
|
|
5438
|
+
themeId,
|
|
5439
|
+
name: pkg.displayName || themeId,
|
|
5440
|
+
description: pkg.description || "",
|
|
5441
|
+
email: tokens.user.email,
|
|
5442
|
+
author: typeof pkg.author === "string" ? pkg.author : pkg.author?.name || tokens.user.name || "",
|
|
5443
|
+
category: pkg.onex?.category || "MINIMAL",
|
|
5444
|
+
tags: pkg.keywords || [],
|
|
5445
|
+
thumbnail_url: pkg.onex?.thumbnail || ""
|
|
5446
|
+
})
|
|
5447
|
+
},
|
|
5448
|
+
env
|
|
5449
|
+
);
|
|
5450
|
+
const regData = await regResponse.json();
|
|
5451
|
+
const regBody = regData.statusCode ? regData.body : regData;
|
|
5452
|
+
if (!regResponse.ok) {
|
|
5453
|
+
const errMsg = regBody.error || regBody.message || "Registration failed";
|
|
5454
|
+
if (!errMsg.includes("already registered")) {
|
|
5455
|
+
logger.stopSpinner(false, "Registration failed");
|
|
5456
|
+
logger.error(errMsg);
|
|
5457
|
+
process.exit(1);
|
|
5458
|
+
}
|
|
4891
5459
|
}
|
|
5460
|
+
logger.stopSpinner(true, regBody.message || "Theme registered");
|
|
5461
|
+
} catch (error) {
|
|
5462
|
+
logger.stopSpinner(false, "Registration failed");
|
|
5463
|
+
logger.error(
|
|
5464
|
+
error instanceof Error ? error.message : "Connection failed"
|
|
5465
|
+
);
|
|
5466
|
+
process.exit(1);
|
|
4892
5467
|
}
|
|
4893
|
-
logger.stopSpinner(true, regBody.message || "Theme registered");
|
|
4894
|
-
} catch (error) {
|
|
4895
|
-
logger.stopSpinner(false, "Registration failed");
|
|
4896
|
-
logger.error(error instanceof Error ? error.message : "Connection failed");
|
|
4897
|
-
process.exit(1);
|
|
4898
5468
|
}
|
|
4899
|
-
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
|
|
4904
|
-
|
|
4905
|
-
|
|
4906
|
-
|
|
4907
|
-
|
|
4908
|
-
|
|
4909
|
-
|
|
4910
|
-
|
|
4911
|
-
|
|
4912
|
-
|
|
4913
|
-
|
|
4914
|
-
|
|
5469
|
+
if (!options.dryRun) {
|
|
5470
|
+
logger.startSpinner("Checking version availability...");
|
|
5471
|
+
try {
|
|
5472
|
+
const checkResponse = await authenticatedFetch(
|
|
5473
|
+
`${apiUrl}/website-api/themes/${encodeURIComponent(themeId)}/versions/${encodeURIComponent(version2)}/exists`,
|
|
5474
|
+
{ method: "GET" },
|
|
5475
|
+
env
|
|
5476
|
+
);
|
|
5477
|
+
const checkData = await checkResponse.json();
|
|
5478
|
+
const checkBody = checkData.statusCode ? checkData.body : checkData;
|
|
5479
|
+
if (checkBody.exists) {
|
|
5480
|
+
logger.stopSpinner(false, "Version already published");
|
|
5481
|
+
const patchVer = semver__default.default.inc(version2, "patch") || "?";
|
|
5482
|
+
const minorVer = semver__default.default.inc(version2, "minor") || "?";
|
|
5483
|
+
const majorVer = semver__default.default.inc(version2, "major") || "?";
|
|
5484
|
+
logger.error(
|
|
5485
|
+
`
|
|
4915
5486
|
Version ${version2} of "${themeId}" is already published and cannot be overwritten.
|
|
4916
5487
|
|
|
4917
5488
|
To publish a new version:
|
|
@@ -4922,12 +5493,16 @@ Or use the --bump flag:
|
|
|
4922
5493
|
onexthm publish --bump patch (${version2} -> ${patchVer})
|
|
4923
5494
|
onexthm publish --bump minor (${version2} -> ${minorVer})
|
|
4924
5495
|
onexthm publish --bump major (${version2} -> ${majorVer})`
|
|
5496
|
+
);
|
|
5497
|
+
process.exit(1);
|
|
5498
|
+
}
|
|
5499
|
+
logger.stopSpinner(true, `Version ${version2} is available`);
|
|
5500
|
+
} catch (error) {
|
|
5501
|
+
logger.stopSpinner(
|
|
5502
|
+
true,
|
|
5503
|
+
"Version check skipped (endpoint not available)"
|
|
4925
5504
|
);
|
|
4926
|
-
process.exit(1);
|
|
4927
5505
|
}
|
|
4928
|
-
logger.stopSpinner(true, `Version ${version2} is available`);
|
|
4929
|
-
} catch (error) {
|
|
4930
|
-
logger.stopSpinner(true, "Version check skipped (endpoint not available)");
|
|
4931
5506
|
}
|
|
4932
5507
|
logger.startSpinner("Building theme...");
|
|
4933
5508
|
try {
|
|
@@ -4944,7 +5519,19 @@ Or use the --bump flag:
|
|
|
4944
5519
|
logger.error(error instanceof Error ? error.message : "Build error");
|
|
4945
5520
|
process.exit(1);
|
|
4946
5521
|
}
|
|
4947
|
-
const distDir =
|
|
5522
|
+
const distDir = path11__default.default.join(themePath, "dist");
|
|
5523
|
+
const classification = await runSchemaDiffGate(
|
|
5524
|
+
themeId,
|
|
5525
|
+
distDir,
|
|
5526
|
+
env,
|
|
5527
|
+
options
|
|
5528
|
+
);
|
|
5529
|
+
if (options.dryRun) {
|
|
5530
|
+
const exitCode = classification?.highest === "breaking" || classification?.highest === "breaking-severe" || classification?.highest === "breaking-asset" ? 2 : 0;
|
|
5531
|
+
logger.newLine();
|
|
5532
|
+
logger.info(`Dry run complete (exit ${exitCode}). No files uploaded.`);
|
|
5533
|
+
process.exit(exitCode);
|
|
5534
|
+
}
|
|
4948
5535
|
let assetEntries = [];
|
|
4949
5536
|
try {
|
|
4950
5537
|
assetEntries = await scanThemeAssets(distDir);
|
|
@@ -4981,7 +5568,7 @@ Or use the --bump flag:
|
|
|
4981
5568
|
for (const [originalPath, url] of Object.entries(videoUrls)) {
|
|
4982
5569
|
assetMap[originalPath] = url;
|
|
4983
5570
|
}
|
|
4984
|
-
const assetMapPath =
|
|
5571
|
+
const assetMapPath = path11__default.default.join(distDir, "asset-map.json");
|
|
4985
5572
|
await fs__default.default.writeFile(assetMapPath, JSON.stringify(assetMap, null, 2));
|
|
4986
5573
|
} catch (error) {
|
|
4987
5574
|
logger.error(
|
|
@@ -5104,7 +5691,7 @@ Or use the --bump flag:
|
|
|
5104
5691
|
logger.error("Build the theme first: onexthm build");
|
|
5105
5692
|
process.exit(1);
|
|
5106
5693
|
}
|
|
5107
|
-
const bundleZipPath =
|
|
5694
|
+
const bundleZipPath = path11__default.default.join(themePath, "dist", "bundle.zip");
|
|
5108
5695
|
await createZip(distDir, bundleZipPath, [
|
|
5109
5696
|
"bundle.zip",
|
|
5110
5697
|
"source.zip",
|
|
@@ -5131,7 +5718,7 @@ Or use the --bump flag:
|
|
|
5131
5718
|
}
|
|
5132
5719
|
logger.startSpinner("Uploading source...");
|
|
5133
5720
|
try {
|
|
5134
|
-
const sourceZipPath =
|
|
5721
|
+
const sourceZipPath = path11__default.default.join(themePath, "dist", "source.zip");
|
|
5135
5722
|
await createZip(themePath, sourceZipPath, [
|
|
5136
5723
|
"node_modules",
|
|
5137
5724
|
"dist",
|
|
@@ -5217,7 +5804,7 @@ async function uploadThumbnail(apiUrl, themeId, themePath, distDir, env = "dev")
|
|
|
5217
5804
|
let imageBase64 = null;
|
|
5218
5805
|
let mimeType = "image/png";
|
|
5219
5806
|
for (const { file, mime } of THUMBNAIL_CANDIDATES) {
|
|
5220
|
-
const candidate =
|
|
5807
|
+
const candidate = path11__default.default.join(themePath, file);
|
|
5221
5808
|
if (fs__default.default.existsSync(candidate)) {
|
|
5222
5809
|
const buf = fs__default.default.readFileSync(candidate);
|
|
5223
5810
|
imageBase64 = `data:${mime};base64,${buf.toString("base64")}`;
|
|
@@ -5319,7 +5906,7 @@ async function screenshotHomePage(themePath, distDir) {
|
|
|
5319
5906
|
const { compilePreviewRuntime: compilePreviewRuntime2 } = await Promise.resolve().then(() => (init_compile_theme(), compile_theme_exports));
|
|
5320
5907
|
const { createDevServer: createDevServer2 } = await Promise.resolve().then(() => (init_dev_server(), dev_server_exports));
|
|
5321
5908
|
const previewRuntimePath = await compilePreviewRuntime2(themePath);
|
|
5322
|
-
const themeName =
|
|
5909
|
+
const themeName = path11__default.default.basename(themePath);
|
|
5323
5910
|
const port = await findFreePort(4500);
|
|
5324
5911
|
const server = createDevServer2({
|
|
5325
5912
|
port,
|
|
@@ -5376,7 +5963,7 @@ async function findFreePort(start) {
|
|
|
5376
5963
|
});
|
|
5377
5964
|
}
|
|
5378
5965
|
async function uploadVideoMultipart(apiUrl, themeId, video, env = "dev") {
|
|
5379
|
-
const fileName =
|
|
5966
|
+
const fileName = path11__default.default.basename(video.originalPath);
|
|
5380
5967
|
const videoInitUrl = `${apiUrl}/media/videos/multipart/init`;
|
|
5381
5968
|
const videoInitBody = {
|
|
5382
5969
|
file_name: fileName,
|
|
@@ -5505,6 +6092,91 @@ async function createZip(sourceDir, outputPath, exclude) {
|
|
|
5505
6092
|
archive.finalize();
|
|
5506
6093
|
});
|
|
5507
6094
|
}
|
|
6095
|
+
async function runSchemaDiffGate(themeId, distDir, env, options) {
|
|
6096
|
+
logger.startSpinner("Fetching prior version for diff...");
|
|
6097
|
+
const { result: prior, reason } = await fetchPriorGateManifests(themeId, env);
|
|
6098
|
+
if (!prior) {
|
|
6099
|
+
if (reason === "no-prior") {
|
|
6100
|
+
logger.stopSpinner(true, "First publish \u2014 no prior version to diff");
|
|
6101
|
+
} else {
|
|
6102
|
+
logger.stopSpinner(true, `Gate skipped (${reason})`);
|
|
6103
|
+
}
|
|
6104
|
+
return null;
|
|
6105
|
+
}
|
|
6106
|
+
logger.stopSpinner(true, `Fetched prior version ${prior.version}`);
|
|
6107
|
+
let currentSchemas;
|
|
6108
|
+
let currentAssets;
|
|
6109
|
+
try {
|
|
6110
|
+
currentSchemas = JSON.parse(
|
|
6111
|
+
await fs__default.default.readFile(path11__default.default.join(distDir, "schemas.json"), "utf-8")
|
|
6112
|
+
);
|
|
6113
|
+
} catch (err) {
|
|
6114
|
+
logger.warning(
|
|
6115
|
+
`Gate skipped: dist/schemas.json missing or unreadable (${err instanceof Error ? err.message : "unknown"})`
|
|
6116
|
+
);
|
|
6117
|
+
return null;
|
|
6118
|
+
}
|
|
6119
|
+
try {
|
|
6120
|
+
currentAssets = JSON.parse(
|
|
6121
|
+
await fs__default.default.readFile(path11__default.default.join(distDir, "asset-manifest.json"), "utf-8")
|
|
6122
|
+
);
|
|
6123
|
+
} catch {
|
|
6124
|
+
currentAssets = { manifestVersion: 1, assets: [] };
|
|
6125
|
+
}
|
|
6126
|
+
const changes = diffManifests(
|
|
6127
|
+
{ schemas: prior.schemas, assets: prior.assets },
|
|
6128
|
+
{ schemas: currentSchemas, assets: currentAssets }
|
|
6129
|
+
);
|
|
6130
|
+
const classification = classify(changes);
|
|
6131
|
+
printGateReport(prior.version, classification);
|
|
6132
|
+
if (options.dryRun) return classification;
|
|
6133
|
+
const isBreaking = classification.highest === "breaking" || classification.highest === "breaking-severe" || classification.highest === "breaking-asset";
|
|
6134
|
+
if (isBreaking && !options.force) {
|
|
6135
|
+
logger.error(
|
|
6136
|
+
"\nPublish blocked: breaking changes detected.\n \u2022 Bump major version and ship migration notes, OR\n \u2022 Re-run with --force to override (logged in the audit trail)."
|
|
6137
|
+
);
|
|
6138
|
+
process.exit(1);
|
|
6139
|
+
}
|
|
6140
|
+
if (classification.highest === "defaults-only" && !options.confirmDefaults) {
|
|
6141
|
+
logger.error(
|
|
6142
|
+
"\nPublish blocked: default values changed.\nThese defaults will propagate to every customer site that hasn't overridden\nthe field. Re-run with --confirm-defaults to acknowledge the change, or\nrevert the default if it wasn't intentional."
|
|
6143
|
+
);
|
|
6144
|
+
process.exit(1);
|
|
6145
|
+
}
|
|
6146
|
+
return classification;
|
|
6147
|
+
}
|
|
6148
|
+
function printGateReport(priorVersion, classification) {
|
|
6149
|
+
logger.newLine();
|
|
6150
|
+
logger.info(`Schema diff vs. v${priorVersion}:`);
|
|
6151
|
+
if (classification.changes.length === 0) {
|
|
6152
|
+
logger.log(" \u2713 Safe \u2014 no schema changes detected");
|
|
6153
|
+
return;
|
|
6154
|
+
}
|
|
6155
|
+
for (const change of classification.changes) {
|
|
6156
|
+
const icon = iconFor(change.kind);
|
|
6157
|
+
logger.log(` ${icon} [${change.kind}] ${change.path} \u2014 ${change.detail}`);
|
|
6158
|
+
}
|
|
6159
|
+
logger.log(
|
|
6160
|
+
`
|
|
6161
|
+
\u2192 Classification: ${classification.highest}. Suggested bump: ${classification.bump}.`
|
|
6162
|
+
);
|
|
6163
|
+
}
|
|
6164
|
+
function iconFor(kind) {
|
|
6165
|
+
switch (kind) {
|
|
6166
|
+
case "safe":
|
|
6167
|
+
case "safe-rename":
|
|
6168
|
+
return "\u2713";
|
|
6169
|
+
case "additive":
|
|
6170
|
+
return "+";
|
|
6171
|
+
case "defaults-only":
|
|
6172
|
+
return "\u26A0";
|
|
6173
|
+
case "breaking":
|
|
6174
|
+
case "breaking-asset":
|
|
6175
|
+
return "\u2717";
|
|
6176
|
+
case "breaking-severe":
|
|
6177
|
+
return "\u2717\u2717";
|
|
6178
|
+
}
|
|
6179
|
+
}
|
|
5508
6180
|
|
|
5509
6181
|
// src/commands/mcp.ts
|
|
5510
6182
|
init_logger();
|
|
@@ -5516,18 +6188,18 @@ var AI_CONTEXT_FILES = [
|
|
|
5516
6188
|
".mcp.json"
|
|
5517
6189
|
];
|
|
5518
6190
|
function resolveTargetDir(opts) {
|
|
5519
|
-
return
|
|
6191
|
+
return path11__default.default.resolve(opts.cwd ?? process.cwd());
|
|
5520
6192
|
}
|
|
5521
6193
|
function resolveDefaultTemplateDir() {
|
|
5522
|
-
return
|
|
6194
|
+
return path11__default.default.join(getTemplatesDir(), "default");
|
|
5523
6195
|
}
|
|
5524
6196
|
function isThemeDir(dir) {
|
|
5525
|
-
return fs__default.default.existsSync(
|
|
6197
|
+
return fs__default.default.existsSync(path11__default.default.join(dir, "theme.config.ts")) || fs__default.default.existsSync(path11__default.default.join(dir, "theme.config.js"));
|
|
5526
6198
|
}
|
|
5527
6199
|
function inspectFiles(templateDir, targetDir) {
|
|
5528
6200
|
return AI_CONTEXT_FILES.map((name) => {
|
|
5529
|
-
const templatePath =
|
|
5530
|
-
const targetPath =
|
|
6201
|
+
const templatePath = path11__default.default.join(templateDir, name);
|
|
6202
|
+
const targetPath = path11__default.default.join(targetDir, name);
|
|
5531
6203
|
const exists = fs__default.default.existsSync(targetPath);
|
|
5532
6204
|
let identical = false;
|
|
5533
6205
|
if (exists && fs__default.default.existsSync(templatePath)) {
|
|
@@ -5670,7 +6342,7 @@ async function mcpDoctorCommand(options = {}) {
|
|
|
5670
6342
|
return;
|
|
5671
6343
|
}
|
|
5672
6344
|
logger.success("theme.config.ts present");
|
|
5673
|
-
const mcpJsonPath =
|
|
6345
|
+
const mcpJsonPath = path11__default.default.join(targetDir, ".mcp.json");
|
|
5674
6346
|
if (!fs__default.default.existsSync(mcpJsonPath)) {
|
|
5675
6347
|
logger.error(".mcp.json missing \u2014 run `onexthm mcp setup`");
|
|
5676
6348
|
} else {
|
|
@@ -5708,7 +6380,7 @@ async function mcpDoctorCommand(options = {}) {
|
|
|
5708
6380
|
logger.success(`${s.name} up to date`);
|
|
5709
6381
|
}
|
|
5710
6382
|
}
|
|
5711
|
-
const registryPath =
|
|
6383
|
+
const registryPath = path11__default.default.join(targetDir, "sections-registry.ts");
|
|
5712
6384
|
if (fs__default.default.existsSync(registryPath)) {
|
|
5713
6385
|
logger.success("sections-registry.ts present");
|
|
5714
6386
|
} else {
|
|
@@ -5720,22 +6392,22 @@ async function mcpDoctorCommand(options = {}) {
|
|
|
5720
6392
|
|
|
5721
6393
|
// src/cli.ts
|
|
5722
6394
|
dotenv__default.default.config({
|
|
5723
|
-
path:
|
|
6395
|
+
path: path11__default.default.join(process.cwd(), ".env.local"),
|
|
5724
6396
|
override: true
|
|
5725
6397
|
});
|
|
5726
|
-
dotenv__default.default.config({ path:
|
|
6398
|
+
dotenv__default.default.config({ path: path11__default.default.join(process.cwd(), ".env") });
|
|
5727
6399
|
try {
|
|
5728
6400
|
const projectRoot = getProjectRoot();
|
|
5729
|
-
if (
|
|
6401
|
+
if (path11__default.default.resolve(projectRoot) !== path11__default.default.resolve(process.cwd())) {
|
|
5730
6402
|
dotenv__default.default.config({
|
|
5731
|
-
path:
|
|
6403
|
+
path: path11__default.default.join(projectRoot, ".env.local")
|
|
5732
6404
|
});
|
|
5733
|
-
dotenv__default.default.config({ path:
|
|
6405
|
+
dotenv__default.default.config({ path: path11__default.default.join(projectRoot, ".env") });
|
|
5734
6406
|
}
|
|
5735
6407
|
} catch {
|
|
5736
6408
|
}
|
|
5737
6409
|
dotenv__default.default.config({
|
|
5738
|
-
path:
|
|
6410
|
+
path: path11__default.default.join(os__default.default.homedir(), ".onexthm", ".env"),
|
|
5739
6411
|
quiet: true
|
|
5740
6412
|
});
|
|
5741
6413
|
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)));
|
|
@@ -5748,7 +6420,7 @@ program.command("init").description("Create a new OneX theme project").argument(
|
|
|
5748
6420
|
"default"
|
|
5749
6421
|
).option("--no-install", "Skip installing dependencies").option("--git", "Initialize git repository").option("-y, --yes", "Skip prompts and use defaults").option(
|
|
5750
6422
|
"--env <env>",
|
|
5751
|
-
"Target environment: dev or prod (default: dev)",
|
|
6423
|
+
"Target environment: dev, staging, or prod (default: dev)",
|
|
5752
6424
|
"dev"
|
|
5753
6425
|
).action(initCommand);
|
|
5754
6426
|
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(
|
|
@@ -5779,7 +6451,7 @@ program.command("download").description("Download a published theme via the webs
|
|
|
5779
6451
|
"latest"
|
|
5780
6452
|
).option(
|
|
5781
6453
|
"--env <env>",
|
|
5782
|
-
"Target environment: dev or prod (default: dev)",
|
|
6454
|
+
"Target environment: dev, staging, or prod (default: dev)",
|
|
5783
6455
|
"dev"
|
|
5784
6456
|
).option("-b, --bucket <name>", "[deprecated] ignored").option("-o, --output <dir>", "Output directory", "./active-theme").action(downloadCommand);
|
|
5785
6457
|
program.command("clone").description("Clone theme source code via the website-api").argument("<theme-name>", "Theme to clone").option(
|
|
@@ -5788,23 +6460,23 @@ program.command("clone").description("Clone theme source code via the website-ap
|
|
|
5788
6460
|
"latest"
|
|
5789
6461
|
).option("-n, --name <name>", "New theme name (skips interactive prompt)").option("-o, --output <dir>", "Output directory").option(
|
|
5790
6462
|
"--env <env>",
|
|
5791
|
-
"Target environment: dev or prod (default: dev)",
|
|
6463
|
+
"Target environment: dev, staging, or prod (default: dev)",
|
|
5792
6464
|
"dev"
|
|
5793
6465
|
).option("-b, --bucket <name>", "[deprecated] ignored").option("--no-install", "Skip running pnpm install after clone").action(cloneCommand);
|
|
5794
6466
|
program.command("config").description("Configure OneX CLI credentials (AWS, API keys)").action(configCommand);
|
|
5795
6467
|
program.command("login").description("Login to OneX platform").option(
|
|
5796
6468
|
"--env <env>",
|
|
5797
|
-
"Target environment: dev or prod (default: dev)",
|
|
6469
|
+
"Target environment: dev, staging, or prod (default: dev)",
|
|
5798
6470
|
"dev"
|
|
5799
6471
|
).action(loginCommand);
|
|
5800
6472
|
program.command("logout").description("Logout from OneX platform").option(
|
|
5801
6473
|
"--env <env>",
|
|
5802
|
-
"Target environment: dev or prod (default: dev)",
|
|
6474
|
+
"Target environment: dev, staging, or prod (default: dev)",
|
|
5803
6475
|
"dev"
|
|
5804
6476
|
).action(logoutCommand);
|
|
5805
6477
|
program.command("whoami").description("Show current logged-in developer").option(
|
|
5806
6478
|
"--env <env>",
|
|
5807
|
-
"Target environment: dev or prod (default: dev)",
|
|
6479
|
+
"Target environment: dev, staging, or prod (default: dev)",
|
|
5808
6480
|
"dev"
|
|
5809
6481
|
).action(whoamiCommand);
|
|
5810
6482
|
var mcpCmd = program.command("mcp").description("Manage MCP server registration and AI-context files");
|
|
@@ -5820,8 +6492,17 @@ program.command("publish").description("Build, scan, and publish theme to market
|
|
|
5820
6492
|
"Auto-bump version before publish (patch|minor|major)"
|
|
5821
6493
|
).option(
|
|
5822
6494
|
"--env <env>",
|
|
5823
|
-
"Target environment: dev or prod (default: dev)",
|
|
6495
|
+
"Target environment: dev, staging, or prod (default: dev)",
|
|
5824
6496
|
"dev"
|
|
6497
|
+
).option(
|
|
6498
|
+
"--dry-run",
|
|
6499
|
+
"Build locally and print the schema-diff classification without publishing"
|
|
6500
|
+
).option(
|
|
6501
|
+
"--confirm-defaults",
|
|
6502
|
+
"Confirm that changed section/block defaults should propagate to live sites"
|
|
6503
|
+
).option(
|
|
6504
|
+
"--force",
|
|
6505
|
+
"Publish even when the diff gate detects a breaking change"
|
|
5825
6506
|
).action(publishCommand);
|
|
5826
6507
|
program.configureOutput({
|
|
5827
6508
|
writeErr: (str) => process.stderr.write(chalk4__default.default.red(str))
|