@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/dist/cli.js CHANGED
@@ -3,18 +3,18 @@
3
3
 
4
4
  var chalk4 = require('chalk');
5
5
  var ora = require('ora');
6
- var esbuild = require('esbuild');
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 esbuild__namespace = /*#__PURE__*/_interopNamespace(esbuild);
53
- var path9__default = /*#__PURE__*/_interopDefault(path9);
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
- path9__default.default.join(themePath, "sections/**/*.{ts,tsx}"),
151
- path9__default.default.join(themePath, "components/**/*.{ts,tsx}")
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 fs8__default.default.writeFile(path9__default.default.join(outDir, "bundle.css"), result.css);
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 = path9__default.default.join(dir, "node_modules", relativePath);
372
+ const candidate = path11__default.default.join(dir, "node_modules", relativePath);
173
373
  try {
174
- await fs8__default.default.access(candidate);
374
+ await fs9__default.default.access(candidate);
175
375
  return candidate;
176
376
  } catch {
177
- const parent = path9__default.default.dirname(dir);
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 fs8__default.default.readFile(path9__default.default.join(sourceDir, file), "utf-8");
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
- path9__default.default.join("@onexapis", "core", "dist", distFileName)
455
+ path11__default.default.join("@onexapis", "core", "dist", distFileName)
256
456
  );
257
457
  if (!distPath) {
258
458
  distPath = await resolveNodeModulesFile(
259
459
  __dirname,
260
- path9__default.default.join("@onexapis", "core", "dist", distFileName)
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 fs8__default.default.readFile(distPath, "utf-8");
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(path9__default.default.join(themePath, `theme.config${ext}`));
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(path9__default.default.join(themePath, `theme.layout${ext}`));
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 = path9__default.default.join(themePath, "sections");
709
+ const sectionsDir = path11__default.default.join(themePath, "sections");
510
710
  try {
511
- const sectionDirs = await fs8__default.default.readdir(sectionsDir);
711
+ const sectionDirs = await fs9__default.default.readdir(sectionsDir);
512
712
  for (const dir of sectionDirs) {
513
- const schemaFile = path9__default.default.join(sectionsDir, dir, `${dir}.schema.ts`);
713
+ const schemaFile = path11__default.default.join(sectionsDir, dir, `${dir}.schema.ts`);
514
714
  try {
515
- await fs8__default.default.access(schemaFile);
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 = path9__default.default.join(themePath, "pages");
727
+ const pagesDir = path11__default.default.join(themePath, "pages");
528
728
  try {
529
- const files = await fs8__default.default.readdir(pagesDir);
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(path9__default.default.join(pagesDir, file));
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 fs8__default.default.writeFile(
563
- path9__default.default.join(outputDir, "theme-data.json"),
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 = path9__default.default.join(outputDir, "bundle-entry.js");
587
- const mapPath = path9__default.default.join(outputDir, "bundle-entry.js.map");
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 fs8__default.default.readFile(entryPath, "utf-8");
790
+ entryContent = await fs9__default.default.readFile(entryPath, "utf-8");
591
791
  } catch {
592
- const indexPath = path9__default.default.join(outputDir, "index.js");
792
+ const indexPath = path11__default.default.join(outputDir, "index.js");
593
793
  try {
594
- entryContent = await fs8__default.default.readFile(indexPath, "utf-8");
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 = path9__default.default.join(outputDir, "index.js.map");
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 fs8__default.default.unlink(path9__default.default.join(outputDir, f));
809
+ await fs9__default.default.unlink(path11__default.default.join(outputDir, f));
610
810
  }
611
- await fs8__default.default.writeFile(path9__default.default.join(outputDir, hashedName2), entryContent);
612
- await fs8__default.default.unlink(indexPath);
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 fs8__default.default.unlink(entryPath);
814
+ await fs9__default.default.unlink(entryPath);
615
815
  } catch {
616
816
  }
617
- await fs8__default.default.writeFile(entryPath, entryContent);
817
+ await fs9__default.default.writeFile(entryPath, entryContent);
618
818
  try {
619
- await fs8__default.default.access(indexMapPath);
620
- await fs8__default.default.rename(indexMapPath, path9__default.default.join(outputDir, hashedMapName2));
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 fs8__default.default.unlink(path9__default.default.join(outputDir, f));
835
+ await fs9__default.default.unlink(path11__default.default.join(outputDir, f));
636
836
  }
637
- await fs8__default.default.writeFile(path9__default.default.join(outputDir, hashedName), entryContent);
837
+ await fs9__default.default.writeFile(path11__default.default.join(outputDir, hashedName), entryContent);
638
838
  try {
639
- await fs8__default.default.unlink(entryPath);
839
+ await fs9__default.default.unlink(entryPath);
640
840
  } catch {
641
841
  }
642
- await fs8__default.default.writeFile(entryPath, entryContent);
842
+ await fs9__default.default.writeFile(entryPath, entryContent);
643
843
  try {
644
- await fs8__default.default.access(mapPath);
645
- await fs8__default.default.rename(mapPath, path9__default.default.join(outputDir, hashedMapName));
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(path9__default.default.join(themePath, file));
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 fs8__default.default.readFile(
677
- path9__default.default.join(themePath, "package.json"),
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 fs8__default.default.access(path9__default.default.join(themePath, "theme.config.ts"));
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 fs8__default.default.writeFile(
737
- path9__default.default.join(outputDir, "manifest.json"),
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 = path9__default.default.join(themePath, "dist");
743
- const bundleEntry = path9__default.default.join(themePath, "bundle-entry.ts");
744
- const indexEntry = path9__default.default.join(themePath, "index.ts");
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 fs8__default.default.access(bundleEntry);
981
+ await fs9__default.default.access(bundleEntry);
748
982
  entryPoint = bundleEntry;
749
983
  } catch {
750
984
  }
751
- const shimPath = path9__default.default.join(outputDir, ".process-shim.js");
752
- await fs8__default.default.mkdir(outputDir, { recursive: true });
753
- await fs8__default.default.writeFile(shimPath, PROCESS_SHIM);
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 fs8__default.default.unlink(shimPath);
1038
+ await fs9__default.default.unlink(shimPath);
805
1039
  } catch {
806
1040
  }
807
1041
  await contentHashEntry(outputDir);
808
- const themeAssetsDir = path9__default.default.join(themePath, "assets");
809
- const distThemeAssets = path9__default.default.join(outputDir, "theme-assets");
1042
+ const themeAssetsDir = path11__default.default.join(themePath, "assets");
1043
+ const distThemeAssets = path11__default.default.join(outputDir, "theme-assets");
810
1044
  try {
811
- await fs8__default.default.access(themeAssetsDir);
812
- await fs8__default.default.cp(themeAssetsDir, distThemeAssets, { recursive: true });
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 fs8__default.default.unlink(shimPath);
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 = path9__default.default.join(themePath, "dist");
840
- const bundleEntry = path9__default.default.join(themePath, "bundle-entry.ts");
841
- const indexEntry = path9__default.default.join(themePath, "index.ts");
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 fs8__default.default.access(bundleEntry);
1079
+ await fs9__default.default.access(bundleEntry);
845
1080
  entryPoint = bundleEntry;
846
1081
  } catch {
847
1082
  }
848
- const shimPath = path9__default.default.join(outputDir, ".process-shim.js");
849
- await fs8__default.default.mkdir(outputDir, { recursive: true });
850
- await fs8__default.default.writeFile(shimPath, PROCESS_SHIM);
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 = path9__default.default.join(themePath, "dist");
905
- await fs8__default.default.mkdir(outputDir, { recursive: true });
906
- const outputPath = path9__default.default.join(outputDir, "preview-runtime.js");
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
- path9__default.default.join(__dirname, "..", "preview", "preview-app.tsx"),
909
- path9__default.default.join(__dirname, "preview", "preview-app.tsx"),
910
- path9__default.default.join(__dirname, "..", "..", "src", "preview", "preview-app.tsx")
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 fs8__default.default.access(loc);
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
- path9__default.default.join(themePath, "node_modules", "@onexapis", "core", "src"),
999
- path9__default.default.join(themePath, "..", "..", "packages", "core", "src"),
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
- path9__default.default.join(
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 fs8__default.default.access(candidate);
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
- path9__default.default.join(themePath, "node_modules", "@onexapis", "core", "dist")
1270
+ path11__default.default.join(themePath, "node_modules", "@onexapis", "core", "dist")
1036
1271
  ];
1037
1272
  const resolvedDist = await resolveNodeModulesFile(
1038
1273
  __dirname,
1039
- path9__default.default.join("@onexapis", "core", "dist")
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 fs8__default.default.access(candidate);
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 fs8__default.default.readFile(
1049
- path9__default.default.join(candidate, file),
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 = path9__default.default.join(pkgDir, "dist", "es", "index.mjs");
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 = path9__default.default.join(outputDir, ".process-shim-preview.js");
1204
- await fs8__default.default.writeFile(shimPath, PROCESS_SHIM);
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 fs8__default.default.unlink(shimPath);
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 = path9__default.default.join(options.distDir, "theme-data.json");
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 = path9__default.default.join(options.themePath, "assets", assetSubpath);
1430
- if (!assetPath.startsWith(path9__default.default.join(options.themePath, "assets"))) {
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 = path9__default.default.join(options.themePath, "assets", match[1]);
1442
- if (!assetPath.startsWith(path9__default.default.join(options.themePath, "assets"))) {
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 = path9__default.default.join(options.themePath, "assets");
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 = path9__default.default.join(assetsBase, segments.slice(1).join("/"));
1694
+ assetPath = path11__default.default.join(assetsBase, segments.slice(1).join("/"));
1458
1695
  } else {
1459
- assetPath = path9__default.default.join(assetsBase, subpath);
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 = path9__default.default.join(assetsBase, segments.slice(1).join("/"));
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 = path9__default.default.join(options.distDir, pathname);
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 = path9__default.default.extname(filePath);
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(path9__default.default.dirname(filePath));
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
- path9__default.default.join(__dirname, "../../templates"),
1879
+ path11__default.default.join(__dirname, "../../templates"),
1643
1880
  // Development
1644
- path9__default.default.join(__dirname, "../templates"),
1881
+ path11__default.default.join(__dirname, "../templates"),
1645
1882
  // Production (dist/)
1646
- path9__default.default.join(process.cwd(), "templates"),
1883
+ path11__default.default.join(process.cwd(), "templates"),
1647
1884
  // Fallback
1648
- path9__default.default.join(process.cwd(), "packages/cli/templates")
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 = path9__default.default.join(templatesDir, templateName);
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 = path9__default.default.join(templateDir, file);
1670
- const targetPath = path9__default.default.join(targetDir, file);
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 = path9__default.default.join(templateDir, file);
1688
- const targetPath = path9__default.default.join(targetDir, file);
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 !== path9__default.default.parse(currentDir).root) {
1704
- const packageJsonPath = path9__default.default.join(currentDir, "package.json");
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(path9__default.default.join(currentDir, "src/themes")) || fs__default.default.existsSync(path9__default.default.join(currentDir, "themes"))) {
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 = path9__default.default.dirname(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(path9__default.default.join(root, "themes")))
1718
- return path9__default.default.join(root, "themes");
1719
- if (fs__default.default.existsSync(path9__default.default.join(root, "src/themes")))
1720
- return path9__default.default.join(root, "src/themes");
1721
- return path9__default.default.dirname(root);
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 path9__default.default.join(getProjectRoot(), "src/features");
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(path9__default.default.join(root, "themes")) || fs__default.default.existsSync(path9__default.default.join(root, "src/themes")) || fs__default.default.existsSync(path9__default.default.join(root, "theme.config.ts")) || fs__default.default.existsSync(path9__default.default.join(root, "bundle-entry.ts"));
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 = path9__default.default.join(themesDir, name);
1745
- return fs__default.default.statSync(themePath).isDirectory() && (fs__default.default.existsSync(path9__default.default.join(themePath, "theme.config.ts")) || fs__default.default.existsSync(path9__default.default.join(themePath, "bundle-entry.ts")) || fs__default.default.existsSync(path9__default.default.join(themePath, "manifest.ts")));
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 = path9__default.default.join(getThemesDir(), themeName);
1750
- return fs__default.default.existsSync(themePath) && (fs__default.default.existsSync(path9__default.default.join(themePath, "theme.config.ts")) || fs__default.default.existsSync(path9__default.default.join(themePath, "bundle-entry.ts")) || fs__default.default.existsSync(path9__default.default.join(themePath, "manifest.ts")));
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(path9__default.default.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
1759
- if (fs__default.default.existsSync(path9__default.default.join(cwd, "yarn.lock"))) return "yarn";
1760
- if (fs__default.default.existsSync(path9__default.default.join(cwd, "bun.lockb"))) return "bun";
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 = path9__default.default.join(os__default.default.homedir(), ".onexthm");
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
- prod: "https://platform-staging.onexeos.com"
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 = path9__default.default.join(AUTH_DIR, `auth-${env}.json`);
2053
+ const newFile = path11__default.default.join(AUTH_DIR, `auth-${env}.json`);
1816
2054
  if (env === "dev") {
1817
- const legacyFile = path9__default.default.join(AUTH_DIR, "auth.json");
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(path9__default.default.join(process.cwd(), kebabName))) {
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 = path9__default.default.join(process.cwd(), name);
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 = path9__default.default.join(projectPath, ".mcp.json");
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 = path9__default.default.join(projectPath, "theme.config.ts");
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 = path9__default.default.join(projectPath, "package.json");
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(path9__default.default.join(process.cwd(), f))
2448
+ (f) => fs__default.default.existsSync(path11__default.default.join(process.cwd(), f))
2211
2449
  );
2212
2450
  if (isStandaloneTheme) {
2213
- options.theme = path9__default.default.basename(process.cwd());
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 = path9__default.default.join(getThemesDir(), themeName);
2277
- const sectionPath = path9__default.default.join(themePath, "sections", sectionName);
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
- path9__default.default.join(sectionPath, `${sectionName}.schema.ts`),
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
- path9__default.default.join(sectionPath, `${sectionName}-default.tsx`),
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(path9__default.default.join(sectionPath, "index.ts"), indexContent);
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: ${path9__default.default.relative(process.cwd(), path9__default.default.join(sectionPath, `${sectionName}.schema.ts`))}`
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: ${path9__default.default.relative(process.cwd(), path9__default.default.join(sectionPath, `${sectionName}-default.tsx`))}`
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: ${path9__default.default.relative(process.cwd(), path9__default.default.join(themePath, "manifest.ts"))}`
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(path9__default.default.join(process.cwd(), f))
2690
+ (f) => fs__default.default.existsSync(path11__default.default.join(process.cwd(), f))
2453
2691
  );
2454
2692
  if (isStandaloneTheme) {
2455
- options.theme = path9__default.default.basename(process.cwd());
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" ? path9__default.default.join(getFeaturesDir(), "blocks", blockName) : path9__default.default.join(getThemesDir(), themeName, "blocks", blockName);
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
- path9__default.default.join(blockPath, `${blockName}.schema.ts`),
2771
+ path11__default.default.join(blockPath, `${blockName}.schema.ts`),
2534
2772
  schemaContent
2535
2773
  );
2536
2774
  const componentContent = generateBlockComponent(data);
2537
- await writeFile(path9__default.default.join(blockPath, `${blockName}.tsx`), componentContent);
2775
+ await writeFile(path11__default.default.join(blockPath, `${blockName}.tsx`), componentContent);
2538
2776
  const indexContent = generateBlockIndex(data);
2539
- await writeFile(path9__default.default.join(blockPath, "index.ts"), indexContent);
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: ${path9__default.default.relative(process.cwd(), path9__default.default.join(blockPath, `${blockName}.schema.ts`))}`
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: ${path9__default.default.relative(process.cwd(), path9__default.default.join(blockPath, `${blockName}.tsx`))}`
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 = path9__default.default.join(
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
- path9__default.default.join(componentPath, `${componentName}.schema.ts`),
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
- path9__default.default.join(componentPath, `${componentName}.tsx`),
2975
+ path11__default.default.join(componentPath, `${componentName}.tsx`),
2738
2976
  componentContent
2739
2977
  );
2740
2978
  const indexContent = generateComponentIndex(data);
2741
- await writeFile(path9__default.default.join(componentPath, "index.ts"), indexContent);
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: ${path9__default.default.relative(process.cwd(), path9__default.default.join(componentPath, `${componentName}.schema.ts`))}`
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: ${path9__default.default.relative(process.cwd(), path9__default.default.join(componentPath, `${componentName}.tsx`))}`
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 = path9__default.default.join(getThemesDir(), theme, "sections");
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 = path9__default.default.join(sectionsDir, name);
2912
- return fs__default.default.statSync(sectionPath).isDirectory() && fs__default.default.existsSync(path9__default.default.join(sectionPath, "index.ts"));
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 = path9__default.default.join(getFeaturesDir(), "blocks");
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 = path9__default.default.join(sharedBlocksDir, name);
2930
- return fs__default.default.statSync(blockPath).isDirectory() && fs__default.default.existsSync(path9__default.default.join(blockPath, "index.ts"));
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 = path9__default.default.join(getThemesDir(), theme, "blocks");
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 = path9__default.default.join(blocksDir, name);
2947
- return fs__default.default.statSync(blockPath).isDirectory() && fs__default.default.existsSync(path9__default.default.join(blockPath, "index.ts"));
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 = path9__default.default.join(getFeaturesDir(), "components");
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 = path9__default.default.join(componentsDir, name);
2968
- return fs__default.default.statSync(componentPath).isDirectory() && fs__default.default.existsSync(path9__default.default.join(componentPath, "index.ts"));
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 = path9__default.default.join(getThemesDir(), theme);
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 = path9__default.default.join(themeDir, candidate);
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(path9__default.default.join(process.cwd(), f)));
3269
+ ].some((f) => fs__default.default.existsSync(path11__default.default.join(process.cwd(), f)));
3032
3270
  if (isThemeDir2) {
3033
- themeToValidate = path9__default.default.basename(process.cwd());
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 = path9__default.default.join(getThemesDir(), themeToValidate);
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(path9__default.default.join(themePath, f))
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
- path9__default.default.join(themePath, foundEntry),
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 = path9__default.default.join(themePath, "theme.config.ts");
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 = path9__default.default.join(themePath, "index.ts");
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 = path9__default.default.join(themePath, "sections");
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(path9__default.default.join(sectionsDir, name)).isDirectory()
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 = path9__default.default.join(sectionsDir, sectionName);
3096
- const schemaFile = path9__default.default.join(sectionPath, `${sectionName}.schema.ts`);
3097
- const defaultTemplate = path9__default.default.join(
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 = path9__default.default.join(sectionPath, "index.ts");
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 = path9__default.default.join(themePath, "blocks");
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(path9__default.default.join(blocksDir, name)).isDirectory());
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 = path9__default.default.join(blocksDir, blockName);
3130
- const schemaFile = path9__default.default.join(blockPath, `${blockName}.schema.ts`);
3131
- const componentFile = path9__default.default.join(blockPath, `${blockName}.tsx`);
3132
- const indexFile = path9__default.default.join(blockPath, "index.ts");
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(path9__default.default.join(sectionsDir, name)).isDirectory()
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 = path9__default.default.join(sectionsDir, sectionName);
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 = path9__default.default.join(sectionPath, tsxFile);
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 = path9__default.default.join(themePath, "sections-registry.ts");
3213
- const bundleEntryPath = path9__default.default.join(themePath, "bundle-entry.ts");
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(path9__default.default.join(sectionsDir, name)).isDirectory()
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 = path9__default.default.join(themePath, "pages");
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(path9__default.default.join(sectionsDir, name)).isDirectory());
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 = path9__default.default.join(
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(path9__default.default.join(pagesDir, file), "utf-8");
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 typeMatches = sectionsBlock.matchAll(/\btype:\s*["']([^"']+)["']/g);
3346
- for (const match of typeMatches) {
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 = path9__default.default.join(getThemesDir(), themeName);
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 = path9__default.default.join(process.cwd(), themeName);
3714
+ themePath = path11__default.default.join(process.cwd(), themeName);
3415
3715
  }
3416
3716
  } catch {
3417
- themePath = path9__default.default.join(process.cwd(), themeName);
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(path9__default.default.join(process.cwd(), f)));
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 = path9__default.default.basename(themePath);
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 = path9__default.default.join(themePath, "package.json");
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 = path9__default.default.join(themePath, "dist");
3796
+ const distPath = path11__default.default.join(themePath, "dist");
3497
3797
  if (fs__default.default.existsSync(distPath)) {
3498
- logger.log(`Output: ${path9__default.default.relative(process.cwd(), distPath)}`);
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 = path9__default.default.join(getThemesDir(), themeName);
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(path9__default.default.join(process.cwd(), f)));
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 = path9__default.default.basename(themePath);
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 = path9__default.default.join(themePath, "package.json");
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 = path9__default.default.join(
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 || path9__default.default.join(process.cwd(), "dist");
3621
- const outputPath = path9__default.default.join(outputDir, `${packageName}.zip`);
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: ${path9__default.default.relative(process.cwd(), outputPath)}`);
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 ${path9__default.default.relative(process.cwd(), outputPath)}`
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 = path9__default.default.resolve(options.package);
3996
+ packagePath = path11__default.default.resolve(options.package);
3697
3997
  } else if (options.theme) {
3698
- const distDir = path9__default.default.join(process.cwd(), "dist");
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 = path9__default.default.join(distDir, packageFiles[0]);
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 = path9__default.default.basename(packagePath);
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: ${path9__default.default.relative(process.cwd(), packagePath)}`);
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 = path9__default.default.join(outputDir, entryFile);
3889
- const stablePath = path9__default.default.join(outputDir, "bundle-entry.js");
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 = path9__default.default.join(outputDir, "sections-registry.js");
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 = path9__default.default.join(outputDir, "package.json");
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 = path9__default.default.join(outputDir, "manifest.json");
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 = path9__default.default.join(themeDir, "package.json");
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 = path9__default.default.join(themeDir, "theme.config.ts");
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 = path9__default.default.join(themeDir, "theme.layout.ts");
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 = path9__default.default.join(themeDir, file);
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 || path9__default.default.resolve(process.cwd(), newName);
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 = path9__default.default.join(outputDir, ".env.example");
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 = path9__default.default.join(outputDir, ".mcp.json");
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
- path9__default.default.join(outputDir, "package.json")
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 ${path9__default.default.relative(process.cwd(), outputDir)}`));
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 = path9__default.default.join(getThemesDir(), themeName);
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 = path9__default.default.join(process.cwd(), themeName);
4649
+ themePath = path11__default.default.join(process.cwd(), themeName);
4350
4650
  }
4351
4651
  } catch {
4352
- themePath = path9__default.default.join(process.cwd(), themeName);
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(path9__default.default.join(process.cwd(), f)));
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 = path9__default.default.basename(themePath);
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 = path9__default.default.join(outputDir, ".process-shim.js");
4735
+ const shimPath = path11__default.default.join(outputDir, ".process-shim.js");
4436
4736
  try {
4437
- await fs8__default.default.unlink(shimPath);
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 = path9__default.default.join(os__default.default.homedir(), ".onexthm");
4447
- var CONFIG_FILE = path9__default.default.join(CONFIG_DIR, ".env");
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
- var MIME_MAP = {
4716
- ".png": "image/png",
4717
- ".jpg": "image/jpeg",
4718
- ".jpeg": "image/jpeg",
4719
- ".gif": "image/gif",
4720
- ".webp": "image/webp",
4721
- ".avif": "image/avif",
4722
- ".svg": "image/svg+xml",
4723
- ".ico": "image/x-icon",
4724
- ".bmp": "image/bmp",
4725
- ".woff": "font/woff",
4726
- ".woff2": "font/woff2",
4727
- ".ttf": "font/ttf",
4728
- ".otf": "font/otf",
4729
- ".eot": "application/vnd.ms-fontobject",
4730
- ".mp4": "video/mp4",
4731
- ".webm": "video/webm",
4732
- ".mov": "video/quicktime",
4733
- ".ogg": "video/ogg",
4734
- ".json": "application/json"
4735
- };
4736
- var HASH_LEN = 8;
4737
- var VIDEO_EXTENSIONS = [
4738
- ".mp4",
4739
- ".webm",
4740
- ".ogg",
4741
- ".mov",
4742
- ".avi",
4743
- ".mkv"
4744
- ];
4745
- function isVideoAsset(filePath) {
4746
- const lower = filePath.toLowerCase();
4747
- return VIDEO_EXTENSIONS.some((ext) => lower.endsWith(ext));
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
- function mimeFor(filename) {
4750
- const ext = path9__default.default.extname(filename).toLowerCase();
4751
- return MIME_MAP[ext] || "application/octet-stream";
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
- async function sha256Prefix(absPath, len) {
4754
- const buf = await fs__default.default.readFile(absPath);
4755
- return crypto__default.default.createHash("sha256").update(buf).digest("hex").slice(0, len);
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 insertHashIntoName(relPath, hash) {
4758
- const dir = path9__default.default.posix.dirname(relPath);
4759
- const base = path9__default.default.posix.basename(relPath);
4760
- const ext = path9__default.default.posix.extname(base);
4761
- const stem = ext ? base.slice(0, -ext.length) : base;
4762
- const hashed = `${stem}-${hash}${ext}`;
4763
- return dir === "." ? hashed : `${dir}/${hashed}`;
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
- async function scanThemeAssets(distDir) {
4766
- const assetsDir = path9__default.default.join(distDir, "theme-assets");
4767
- if (!await fs__default.default.pathExists(assetsDir)) return [];
4768
- const files = await glob.glob("**/*", {
4769
- cwd: assetsDir,
4770
- nodir: true,
4771
- dot: false
4772
- });
4773
- const results = [];
4774
- for (const rel of files) {
4775
- const absPath = path9__default.default.join(assetsDir, rel);
4776
- const stat = await fs__default.default.stat(absPath);
4777
- if (!stat.isFile()) continue;
4778
- const originalPath = rel.split(path9__default.default.sep).join("/");
4779
- const hash = await sha256Prefix(absPath, HASH_LEN);
4780
- const hashedPath = insertHashIntoName(originalPath, hash);
4781
- const contentType = mimeFor(rel);
4782
- results.push({
4783
- originalPath,
4784
- hashedPath,
4785
- hash,
4786
- size: stat.size,
4787
- contentType,
4788
- absPath
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 buildAssetMap(entries) {
4795
- const map = {};
4796
- for (const e of entries) {
4797
- map[e.originalPath] = e.hashedPath;
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
- return map;
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 = path9__default.default.resolve(options.theme);
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(path9__default.default.join(process.cwd(), f)));
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 = path9__default.default.join(themePath, "package.json");
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/", "") || path9__default.default.basename(themePath);
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
- logger.startSpinner("Registering theme...");
4865
- try {
4866
- const regResponse = await authenticatedFetch(
4867
- `${apiUrl}/website-api/themes/register`,
4868
- {
4869
- method: "POST",
4870
- body: JSON.stringify({
4871
- themeId,
4872
- name: pkg.displayName || themeId,
4873
- description: pkg.description || "",
4874
- email: tokens.user.email,
4875
- author: typeof pkg.author === "string" ? pkg.author : pkg.author?.name || tokens.user.name || "",
4876
- category: pkg.onex?.category || "MINIMAL",
4877
- tags: pkg.keywords || [],
4878
- thumbnail_url: pkg.onex?.thumbnail || ""
4879
- })
4880
- },
4881
- env
4882
- );
4883
- const regData = await regResponse.json();
4884
- const regBody = regData.statusCode ? regData.body : regData;
4885
- if (!regResponse.ok) {
4886
- const errMsg = regBody.error || regBody.message || "Registration failed";
4887
- if (!errMsg.includes("already registered")) {
4888
- logger.stopSpinner(false, "Registration failed");
4889
- logger.error(errMsg);
4890
- process.exit(1);
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
- logger.startSpinner("Checking version availability...");
4900
- try {
4901
- const checkResponse = await authenticatedFetch(
4902
- `${apiUrl}/website-api/themes/${encodeURIComponent(themeId)}/versions/${encodeURIComponent(version2)}/exists`,
4903
- { method: "GET" },
4904
- env
4905
- );
4906
- const checkData = await checkResponse.json();
4907
- const checkBody = checkData.statusCode ? checkData.body : checkData;
4908
- if (checkBody.exists) {
4909
- logger.stopSpinner(false, "Version already published");
4910
- const patchVer = semver__default.default.inc(version2, "patch") || "?";
4911
- const minorVer = semver__default.default.inc(version2, "minor") || "?";
4912
- const majorVer = semver__default.default.inc(version2, "major") || "?";
4913
- logger.error(
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 = path9__default.default.join(themePath, "dist");
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 = path9__default.default.join(distDir, "asset-map.json");
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 = path9__default.default.join(themePath, "dist", "bundle.zip");
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 = path9__default.default.join(themePath, "dist", "source.zip");
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 = path9__default.default.join(themePath, file);
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 = path9__default.default.basename(themePath);
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 = path9__default.default.basename(video.originalPath);
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 path9__default.default.resolve(opts.cwd ?? process.cwd());
6191
+ return path11__default.default.resolve(opts.cwd ?? process.cwd());
5520
6192
  }
5521
6193
  function resolveDefaultTemplateDir() {
5522
- return path9__default.default.join(getTemplatesDir(), "default");
6194
+ return path11__default.default.join(getTemplatesDir(), "default");
5523
6195
  }
5524
6196
  function isThemeDir(dir) {
5525
- return fs__default.default.existsSync(path9__default.default.join(dir, "theme.config.ts")) || fs__default.default.existsSync(path9__default.default.join(dir, "theme.config.js"));
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 = path9__default.default.join(templateDir, name);
5530
- const targetPath = path9__default.default.join(targetDir, name);
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 = path9__default.default.join(targetDir, ".mcp.json");
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 = path9__default.default.join(targetDir, "sections-registry.ts");
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: path9__default.default.join(process.cwd(), ".env.local"),
6395
+ path: path11__default.default.join(process.cwd(), ".env.local"),
5724
6396
  override: true
5725
6397
  });
5726
- dotenv__default.default.config({ path: path9__default.default.join(process.cwd(), ".env") });
6398
+ dotenv__default.default.config({ path: path11__default.default.join(process.cwd(), ".env") });
5727
6399
  try {
5728
6400
  const projectRoot = getProjectRoot();
5729
- if (path9__default.default.resolve(projectRoot) !== path9__default.default.resolve(process.cwd())) {
6401
+ if (path11__default.default.resolve(projectRoot) !== path11__default.default.resolve(process.cwd())) {
5730
6402
  dotenv__default.default.config({
5731
- path: path9__default.default.join(projectRoot, ".env.local")
6403
+ path: path11__default.default.join(projectRoot, ".env.local")
5732
6404
  });
5733
- dotenv__default.default.config({ path: path9__default.default.join(projectRoot, ".env") });
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: path9__default.default.join(os__default.default.homedir(), ".onexthm", ".env"),
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))