@object-ui/cli 17.5.0 → 17.6.0

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,10 +3,12 @@ import {
3
3
  createTempApp,
4
4
  createTempAppWithRouting,
5
5
  init,
6
- parseSchemaFile,
7
- scanPagesDirectory,
6
+ isWorkspaceRoot,
7
+ prepareWorkspaceTempApp,
8
+ reportProjectSource,
9
+ resolveProjectSource,
8
10
  serve
9
- } from "./chunk-2MZA766D.js";
11
+ } from "./chunk-AP2INOE7.js";
10
12
 
11
13
  // src/cli.ts
12
14
  import { Command } from "commander";
@@ -15,103 +17,22 @@ import chalk14 from "chalk";
15
17
  // src/commands/dev.ts
16
18
  import { createServer } from "vite";
17
19
  import react from "@vitejs/plugin-react";
18
- import { existsSync, mkdirSync, unlinkSync, statSync } from "fs";
19
- import { join, resolve, dirname } from "path";
20
+ import { mkdirSync } from "fs";
21
+ import { join } from "path";
20
22
  import chalk from "chalk";
21
23
  import { execSync } from "child_process";
22
- import { createRequire } from "module";
23
- async function loadTempAppPostcssPlugins() {
24
- try {
25
- const [tailwindPostcss, autoprefixer] = await Promise.all([
26
- import("@tailwindcss/postcss"),
27
- import("autoprefixer")
28
- ]);
29
- return [tailwindPostcss.default(), autoprefixer.default()];
30
- } catch (error) {
31
- throw new Error(
32
- `Failed to load the Tailwind CSS PostCSS pipeline: ${error instanceof Error ? error.message : error}
33
- Both '@tailwindcss/postcss' and 'autoprefixer' are dependencies of @object-ui/cli \u2014 a
34
- broken install of the CLI is the likeliest cause; reinstall it and try again.
35
- (Refusing to start unstyled: that failure is silent in the browser.)`
36
- );
37
- }
38
- }
39
24
  async function dev(schemaPath, options) {
40
25
  const cwd = process.cwd();
41
- let _projectRoot = cwd;
42
- const targetSchemaPath = schemaPath;
43
- let hasPagesDir = false;
44
- let pagesDir = "";
45
- let appConfig = null;
46
- const absoluteSchemaPath = resolve(cwd, schemaPath);
47
- if (existsSync(absoluteSchemaPath) && statSync(absoluteSchemaPath).isFile()) {
48
- const fileDir = dirname(absoluteSchemaPath);
49
- const potentialPagesDir = join(fileDir, "pages");
50
- if (existsSync(potentialPagesDir)) {
51
- console.log(chalk.blue(`\u{1F4C2} Detected project structure at ${fileDir}`));
52
- _projectRoot = fileDir;
53
- hasPagesDir = true;
54
- pagesDir = potentialPagesDir;
55
- try {
56
- appConfig = parseSchemaFile(absoluteSchemaPath);
57
- console.log(chalk.blue("\u2699\uFE0F Loaded App Config from app.json"));
58
- } catch (_e) {
59
- console.warn("Failed to parse app config");
60
- }
61
- }
62
- }
63
- if (!hasPagesDir) {
64
- const localPagesDir = join(cwd, "pages");
65
- if (existsSync(localPagesDir)) {
66
- hasPagesDir = true;
67
- pagesDir = localPagesDir;
68
- const appJsonPath = join(cwd, "app.json");
69
- if (existsSync(appJsonPath)) {
70
- try {
71
- appConfig = parseSchemaFile(appJsonPath);
72
- console.log(chalk.blue("\u2699\uFE0F Loaded App Config from app.json"));
73
- } catch (_e) {
74
- console.warn("Failed to parse app.json config");
75
- }
76
- }
77
- }
78
- }
79
- const require2 = createRequire(join(cwd, "package.json"));
80
- let routes = [];
81
- let schema = null;
82
- let useFileSystemRouting = false;
83
- if (hasPagesDir) {
84
- console.log(chalk.blue(`\u{1F4C1} Using file-system routing from ${pagesDir}`));
85
- routes = scanPagesDirectory(pagesDir);
86
- useFileSystemRouting = true;
87
- if (routes.length === 0) {
88
- throw new Error(`No schema files found in ${pagesDir}`);
89
- }
90
- console.log(chalk.green(`\u2713 Found ${routes.length} route(s)`));
91
- routes.forEach((route) => {
92
- console.log(chalk.dim(` ${route.path} \u2192 ${route.filePath.replace(cwd, ".")}`));
93
- });
94
- } else {
95
- const fullSchemaPath = resolve(cwd, schemaPath);
96
- if (!existsSync(fullSchemaPath)) {
97
- throw new Error(`Schema file not found: ${schemaPath}
98
- Run 'objectui init' to create a sample schema.`);
99
- }
100
- console.log(chalk.blue("\u{1F4CB} Loading schema:"), chalk.cyan(schemaPath));
101
- try {
102
- schema = parseSchemaFile(fullSchemaPath);
103
- } catch (error) {
104
- throw new Error(`Invalid schema file: ${error instanceof Error ? error.message : error}`);
105
- }
106
- }
26
+ const source = resolveProjectSource(cwd, schemaPath);
27
+ reportProjectSource(source, cwd);
107
28
  const tmpDir = join(cwd, ".objectui-tmp");
108
29
  mkdirSync(tmpDir, { recursive: true });
109
- if (useFileSystemRouting) {
110
- createTempAppWithRouting(tmpDir, routes, appConfig);
30
+ if (source.mode === "routes") {
31
+ createTempAppWithRouting(tmpDir, source.routes, source.appConfig);
111
32
  } else {
112
- createTempApp(tmpDir, schema);
33
+ createTempApp(tmpDir, source.schema);
113
34
  }
114
- const isMonorepo = existsSync(join(cwd, "pnpm-workspace.yaml"));
35
+ const isMonorepo = isWorkspaceRoot(cwd);
115
36
  if (isMonorepo) {
116
37
  console.log(chalk.blue("\u{1F4E6} Detected monorepo - using root node_modules"));
117
38
  } else {
@@ -129,6 +50,10 @@ Run 'objectui init' to create a sample schema.`);
129
50
  }
130
51
  console.log(chalk.green("\u2713 Schema loaded successfully"));
131
52
  console.log(chalk.blue("\u{1F680} Starting development server...\n"));
53
+ if (isMonorepo) {
54
+ console.log(chalk.blue("\u{1F4E6} Detected monorepo - configuring workspace aliases"));
55
+ }
56
+ const workspaceConfig = isMonorepo ? await prepareWorkspaceTempApp(cwd, tmpDir) : {};
132
57
  const viteConfig = {
133
58
  root: tmpDir,
134
59
  server: {
@@ -140,38 +65,9 @@ Run 'objectui init' to create a sample schema.`);
140
65
  allow: [cwd]
141
66
  }
142
67
  },
143
- resolve: {
144
- alias: {}
145
- },
146
- plugins: [react()]
68
+ plugins: [react()],
69
+ ...workspaceConfig
147
70
  };
148
- if (isMonorepo) {
149
- console.log(chalk.blue("\u{1F4E6} Detected monorepo - configuring workspace aliases"));
150
- const postcssPath = join(tmpDir, "postcss.config.js");
151
- if (existsSync(postcssPath)) {
152
- unlinkSync(postcssPath);
153
- }
154
- viteConfig.resolve.alias = {
155
- "@object-ui/react": join(cwd, "packages/react/src/index.ts"),
156
- "@object-ui/components": join(cwd, "packages/components/src/index.ts"),
157
- "@object-ui/core": join(cwd, "packages/core/src/index.ts"),
158
- "@object-ui/types": join(cwd, "packages/types/src/index.ts"),
159
- "@object-ui/plugin-charts": join(cwd, "packages/plugin-charts/src/index.tsx"),
160
- "@object-ui/plugin-editor": join(cwd, "packages/plugin-editor/src/index.tsx"),
161
- "@object-ui/plugin-kanban": join(cwd, "packages/plugin-kanban/src/index.tsx"),
162
- "@object-ui/plugin-markdown": join(cwd, "packages/plugin-markdown/src/index.tsx"),
163
- "@object-ui/plugin-form": join(cwd, "packages/plugin-form/src/index.tsx"),
164
- "@object-ui/plugin-grid": join(cwd, "packages/plugin-grid/src/index.tsx"),
165
- "@object-ui/plugin-view": join(cwd, "packages/plugin-view/src/index.tsx")
166
- };
167
- try {
168
- const lucidePath = require2.resolve("lucide-react", { paths: [join(cwd, "packages/components")] });
169
- viteConfig.resolve.alias["lucide-react"] = lucidePath;
170
- } catch (e) {
171
- console.warn("\u26A0\uFE0F Could not resolve lucide-react automatically:", e);
172
- }
173
- viteConfig.css = { postcss: { plugins: await loadTempAppPostcssPlugins() } };
174
- }
175
71
  const server = await createServer(viteConfig);
176
72
  await server.listen();
177
73
  const { port, host } = server.config.server;
@@ -189,62 +85,47 @@ Run 'objectui init' to create a sample schema.`);
189
85
  // src/commands/build.ts
190
86
  import { build as viteBuild } from "vite";
191
87
  import react2 from "@vitejs/plugin-react";
192
- import { existsSync as existsSync2, mkdirSync as mkdirSync2, cpSync, rmSync } from "fs";
193
- import { join as join2, resolve as resolve2 } from "path";
88
+ import { existsSync, mkdirSync as mkdirSync2, cpSync, rmSync } from "fs";
89
+ import { join as join2, resolve } from "path";
194
90
  import chalk2 from "chalk";
195
91
  import { execSync as execSync2 } from "child_process";
196
92
  async function buildApp(schemaPath, options) {
197
93
  const cwd = process.cwd();
198
94
  const outDir = options.outDir || "dist";
199
- const outputPath = resolve2(cwd, outDir);
95
+ const outputPath = resolve(cwd, outDir);
200
96
  console.log(chalk2.blue("\u{1F528} Building application for production..."));
201
97
  console.log();
202
- const pagesDir = join2(cwd, "pages");
203
- const hasPagesDir = existsSync2(pagesDir);
204
- let routes = [];
205
- let schema = null;
206
- let useFileSystemRouting = false;
207
- if (hasPagesDir) {
208
- console.log(chalk2.blue("\u{1F4C1} Using file-system routing"));
209
- routes = scanPagesDirectory(pagesDir);
210
- useFileSystemRouting = true;
211
- if (routes.length === 0) {
212
- throw new Error("No schema files found in pages/ directory");
213
- }
214
- console.log(chalk2.green(`\u2713 Found ${routes.length} route(s)`));
215
- } else {
216
- const fullSchemaPath = resolve2(cwd, schemaPath);
217
- if (!existsSync2(fullSchemaPath)) {
218
- throw new Error(`Schema file not found: ${schemaPath}
219
- Run 'objectui init' to create a sample schema.`);
220
- }
221
- console.log(chalk2.blue("\u{1F4CB} Loading schema:"), chalk2.cyan(schemaPath));
222
- try {
223
- schema = parseSchemaFile(fullSchemaPath);
224
- } catch (error) {
225
- throw new Error(`Invalid schema file: ${error instanceof Error ? error.message : error}`);
226
- }
227
- }
98
+ const source = resolveProjectSource(cwd, schemaPath);
99
+ reportProjectSource(source, cwd);
228
100
  const tmpDir = join2(cwd, ".objectui-tmp");
229
101
  mkdirSync2(tmpDir, { recursive: true });
230
- if (useFileSystemRouting) {
231
- createTempAppWithRouting(tmpDir, routes);
102
+ if (source.mode === "routes") {
103
+ createTempAppWithRouting(tmpDir, source.routes, source.appConfig);
232
104
  } else {
233
- createTempApp(tmpDir, schema);
105
+ createTempApp(tmpDir, source.schema);
234
106
  }
235
- console.log(chalk2.blue("\u{1F4E6} Installing dependencies..."));
236
- try {
237
- execSync2("npm install --silent --prefer-offline", {
238
- cwd: tmpDir,
239
- stdio: "pipe"
240
- });
241
- console.log(chalk2.green("\u2713 Dependencies installed"));
242
- } catch {
243
- throw new Error("Failed to install dependencies. Please check your internet connection and try again.");
107
+ const isMonorepo = isWorkspaceRoot(cwd);
108
+ if (isMonorepo) {
109
+ console.log(chalk2.blue("\u{1F4E6} Detected monorepo - using root node_modules"));
110
+ } else {
111
+ console.log(chalk2.blue("\u{1F4E6} Installing dependencies..."));
112
+ try {
113
+ execSync2("npm install --silent --prefer-offline", {
114
+ cwd: tmpDir,
115
+ stdio: "pipe"
116
+ });
117
+ console.log(chalk2.green("\u2713 Dependencies installed"));
118
+ } catch {
119
+ throw new Error("Failed to install dependencies. Please check your internet connection and try again.");
120
+ }
244
121
  }
122
+ if (isMonorepo) {
123
+ console.log(chalk2.blue("\u{1F4E6} Detected monorepo - configuring workspace aliases"));
124
+ }
125
+ const workspaceConfig = isMonorepo ? await prepareWorkspaceTempApp(cwd, tmpDir) : {};
245
126
  console.log(chalk2.blue("\u2699\uFE0F Building with Vite..."));
246
127
  console.log();
247
- if (options.clean && existsSync2(outputPath)) {
128
+ if (options.clean && existsSync(outputPath)) {
248
129
  console.log(chalk2.dim(` Cleaning ${outDir}/ directory...`));
249
130
  rmSync(outputPath, { recursive: true, force: true });
250
131
  }
@@ -257,7 +138,8 @@ Run 'objectui init' to create a sample schema.`);
257
138
  reportCompressedSize: true
258
139
  },
259
140
  plugins: [react2()],
260
- logLevel: "info"
141
+ logLevel: "info",
142
+ ...workspaceConfig
261
143
  });
262
144
  mkdirSync2(outputPath, { recursive: true });
263
145
  cpSync(join2(tmpDir, "dist"), outputPath, { recursive: true });
@@ -277,21 +159,21 @@ Run 'objectui init' to create a sample schema.`);
277
159
  // src/commands/start.ts
278
160
  import express from "express";
279
161
  import rateLimit from "express-rate-limit";
280
- import { existsSync as existsSync3 } from "fs";
281
- import { join as join3, resolve as resolve3 } from "path";
162
+ import { existsSync as existsSync2 } from "fs";
163
+ import { join as join3, resolve as resolve2 } from "path";
282
164
  import chalk3 from "chalk";
283
165
  async function start(options) {
284
166
  const cwd = process.cwd();
285
167
  const distDir = options.dir || "dist";
286
- const distPath = resolve3(cwd, distDir);
287
- if (!existsSync3(distPath)) {
168
+ const distPath = resolve2(cwd, distDir);
169
+ if (!existsSync2(distPath)) {
288
170
  throw new Error(
289
171
  `Build directory not found: ${distDir}
290
172
  Run 'objectui build' first to create a production build.`
291
173
  );
292
174
  }
293
175
  const indexPath = join3(distPath, "index.html");
294
- if (!existsSync3(indexPath)) {
176
+ if (!existsSync2(indexPath)) {
295
177
  throw new Error(
296
178
  `index.html not found in ${distDir}/
297
179
  Make sure you have a valid production build.`
@@ -332,14 +214,14 @@ Make sure you have a valid production build.`
332
214
 
333
215
  // src/commands/lint.ts
334
216
  import { execSync as execSync3 } from "child_process";
335
- import { existsSync as existsSync4 } from "fs";
217
+ import { existsSync as existsSync3 } from "fs";
336
218
  import { join as join4 } from "path";
337
219
  import chalk4 from "chalk";
338
220
  async function lint(options) {
339
221
  const cwd = process.cwd();
340
222
  console.log(chalk4.blue("\u{1F50D} Running linter...\n"));
341
223
  const tmpDir = join4(cwd, ".objectui-tmp");
342
- const hasTempApp = existsSync4(tmpDir);
224
+ const hasTempApp = existsSync3(tmpDir);
343
225
  if (!hasTempApp) {
344
226
  throw new Error(
345
227
  "No Object UI application found. Run 'objectui dev' first to generate the application."
@@ -347,7 +229,7 @@ async function lint(options) {
347
229
  }
348
230
  const packageJsonPath = join4(tmpDir, "package.json");
349
231
  const nodeModulesPath = join4(tmpDir, "node_modules");
350
- if (!existsSync4(packageJsonPath) || !existsSync4(nodeModulesPath)) {
232
+ if (!existsSync3(packageJsonPath) || !existsSync3(nodeModulesPath)) {
351
233
  throw new Error(
352
234
  "Dependencies not installed. Run 'objectui dev' first to set up the application."
353
235
  );
@@ -377,14 +259,14 @@ async function lint(options) {
377
259
 
378
260
  // src/commands/test.ts
379
261
  import { execSync as execSync4 } from "child_process";
380
- import { existsSync as existsSync5 } from "fs";
262
+ import { existsSync as existsSync4 } from "fs";
381
263
  import { join as join5 } from "path";
382
264
  import chalk5 from "chalk";
383
265
  async function test(options) {
384
266
  const cwd = process.cwd();
385
267
  console.log(chalk5.blue("\u{1F9EA} Running tests...\n"));
386
268
  const tmpDir = join5(cwd, ".objectui-tmp");
387
- const hasTempApp = existsSync5(tmpDir);
269
+ const hasTempApp = existsSync4(tmpDir);
388
270
  if (!hasTempApp) {
389
271
  throw new Error(
390
272
  "No Object UI application found. Run 'objectui dev' first to generate the application."
@@ -392,7 +274,7 @@ async function test(options) {
392
274
  }
393
275
  const packageJsonPath = join5(tmpDir, "package.json");
394
276
  const nodeModulesPath = join5(tmpDir, "node_modules");
395
- if (!existsSync5(packageJsonPath) || !existsSync5(nodeModulesPath)) {
277
+ if (!existsSync4(packageJsonPath) || !existsSync4(nodeModulesPath)) {
396
278
  throw new Error(
397
279
  "Dependencies not installed. Run 'objectui dev' first to set up the application."
398
280
  );
@@ -430,7 +312,7 @@ async function test(options) {
430
312
 
431
313
  // src/commands/generate.ts
432
314
  import chalk6 from "chalk";
433
- import { existsSync as existsSync6, mkdirSync as mkdirSync3, writeFileSync } from "fs";
315
+ import { existsSync as existsSync5, mkdirSync as mkdirSync3, writeFileSync } from "fs";
434
316
  import { join as join6 } from "path";
435
317
  async function generate(type, name) {
436
318
  const cwd = process.cwd();
@@ -453,10 +335,10 @@ async function generate(type, name) {
453
335
  }
454
336
  function generateResource(cwd, name) {
455
337
  const dir = join6(cwd, "objects");
456
- if (!existsSync6(dir)) mkdirSync3(dir, { recursive: true });
338
+ if (!existsSync5(dir)) mkdirSync3(dir, { recursive: true });
457
339
  const fileName = `${name.toLowerCase()}.json`;
458
340
  const filePath = join6(dir, fileName);
459
- if (existsSync6(filePath)) {
341
+ if (existsSync5(filePath)) {
460
342
  console.log(chalk6.yellow(`Object ${name} already exists at ${filePath}`));
461
343
  return;
462
344
  }
@@ -471,10 +353,10 @@ function generateResource(cwd, name) {
471
353
  }
472
354
  function generatePage(cwd, name) {
473
355
  const dir = join6(cwd, "pages");
474
- if (!existsSync6(dir)) mkdirSync3(dir, { recursive: true });
356
+ if (!existsSync5(dir)) mkdirSync3(dir, { recursive: true });
475
357
  const fileName = `${name.toLowerCase()}.json`;
476
358
  const filePath = join6(dir, fileName);
477
- if (existsSync6(filePath)) {
359
+ if (existsSync5(filePath)) {
478
360
  console.log(chalk6.yellow(`Page ${name} already exists at ${filePath}`));
479
361
  return;
480
362
  }
@@ -493,7 +375,7 @@ function generatePage(cwd, name) {
493
375
  }
494
376
  function generatePlugin(cwd, name) {
495
377
  const dir = join6(cwd, "plugins", name);
496
- if (existsSync6(dir)) {
378
+ if (existsSync5(dir)) {
497
379
  console.log(chalk6.yellow(`Plugin ${name} already exists`));
498
380
  return;
499
381
  }
@@ -512,8 +394,8 @@ export const ${name}Plugin = {
512
394
 
513
395
  // src/commands/doctor.ts
514
396
  import chalk7 from "chalk";
515
- import { existsSync as existsSync7, readFileSync } from "fs";
516
- import { dirname as dirname2, join as join7, resolve as resolvePath } from "path";
397
+ import { existsSync as existsSync6, readFileSync } from "fs";
398
+ import { dirname, join as join7, resolve as resolvePath } from "path";
517
399
  var CSS_ENTRY_CANDIDATES = [
518
400
  "src/index.css",
519
401
  "src/main.css",
@@ -548,7 +430,7 @@ var V4_POSTCSS_PLUGIN = /@tailwindcss\/postcss/;
548
430
  var V3_POSTCSS_PLUGIN = /["']tailwindcss["']|(?:^|[{,\s])tailwindcss\s*:/m;
549
431
  function readIfExists(path) {
550
432
  try {
551
- return existsSync7(path) ? readFileSync(path, "utf-8") : null;
433
+ return existsSync6(path) ? readFileSync(path, "utf-8") : null;
552
434
  } catch {
553
435
  return null;
554
436
  }
@@ -556,7 +438,7 @@ function readIfExists(path) {
556
438
  function findFile(cwd, candidates) {
557
439
  for (const rel of candidates) {
558
440
  const abs = join7(cwd, rel);
559
- if (existsSync7(abs)) return abs;
441
+ if (existsSync6(abs)) return abs;
560
442
  }
561
443
  return null;
562
444
  }
@@ -569,8 +451,8 @@ function majorOf(range) {
569
451
  function isInstalledFrom(cwd, specifier) {
570
452
  let dir = resolvePath(cwd);
571
453
  for (; ; ) {
572
- if (existsSync7(join7(dir, "node_modules", ...specifier.split("/")))) return true;
573
- const parent = dirname2(dir);
454
+ if (existsSync6(join7(dir, "node_modules", ...specifier.split("/")))) return true;
455
+ const parent = dirname(dir);
574
456
  if (parent === dir) return false;
575
457
  dir = parent;
576
458
  }
@@ -688,7 +570,7 @@ function runDiagnostics(cwd) {
688
570
  ok("tailwind-config-active", "JS Tailwind config is loaded via `@config`");
689
571
  }
690
572
  }
691
- if (existsSync7(join7(cwd, "tsconfig.json"))) {
573
+ if (existsSync6(join7(cwd, "tsconfig.json"))) {
692
574
  ok("tsconfig-found", "tsconfig.json found");
693
575
  const tsRange = deps.typescript;
694
576
  if (tsRange) {
@@ -748,22 +630,22 @@ async function add(component) {
748
630
  // src/commands/studio.ts
749
631
  import chalk9 from "chalk";
750
632
  import { spawn } from "child_process";
751
- import { existsSync as existsSync8 } from "fs";
752
- import { join as join8, resolve as resolve4, dirname as dirname3 } from "path";
633
+ import { existsSync as existsSync7 } from "fs";
634
+ import { join as join8, resolve as resolve3, dirname as dirname2 } from "path";
753
635
  import { fileURLToPath } from "url";
754
636
  async function studio() {
755
637
  console.log(chalk9.bold("\n\u{1F3A8} Starting ObjectUI Studio...\n"));
756
638
  const cwd = process.cwd();
757
639
  const __filename3 = fileURLToPath(import.meta.url);
758
- const __dirname3 = dirname3(__filename3);
640
+ const __dirname3 = dirname2(__filename3);
759
641
  const candidates = [
760
642
  join8(cwd, "apps/console"),
761
- resolve4(__dirname3, "../../apps/console"),
762
- resolve4(__dirname3, "../../../apps/console")
643
+ resolve3(__dirname3, "../../apps/console"),
644
+ resolve3(__dirname3, "../../../apps/console")
763
645
  ];
764
646
  let consolePath = null;
765
647
  for (const candidate of candidates) {
766
- if (existsSync8(join8(candidate, "package.json"))) {
648
+ if (existsSync7(join8(candidate, "package.json"))) {
767
649
  consolePath = candidate;
768
650
  break;
769
651
  }
@@ -795,41 +677,735 @@ import chalk10 from "chalk";
795
677
  import { globSync } from "glob";
796
678
  import { readFileSync as readFileSync2 } from "fs";
797
679
  import { join as join9 } from "path";
798
- async function check() {
680
+ import { parse as parseJsonc, printParseErrorCode } from "jsonc-parser";
681
+
682
+ // src/utils/known-schema-types.ts
683
+ var KNOWN_SCHEMA_TYPES = [
684
+ "a",
685
+ "abbr",
686
+ "accordion",
687
+ "action:bar",
688
+ "action:button",
689
+ "action:group",
690
+ "action:icon",
691
+ "action:menu",
692
+ "address",
693
+ "advanced-chart",
694
+ "ai-form-assist",
695
+ "ai-recommendations",
696
+ "ai:feedback",
697
+ "ai:input",
698
+ "ai:suggestion",
699
+ "alert",
700
+ "alert-dialog",
701
+ "app",
702
+ "app-creation-wizard",
703
+ "app-schema-renderer",
704
+ "app-shell:cloud-connection:panel",
705
+ "app-shell:cloud:ai-model-status",
706
+ "app-shell:cloud:onboarding-next",
707
+ "app-shell:marketplace:installed-list",
708
+ "app-shell:mcp:connect-agent",
709
+ "app:launcher",
710
+ "area-chart",
711
+ "article",
712
+ "aside",
713
+ "aspect-ratio",
714
+ "auto_number",
715
+ "avatar",
716
+ "b",
717
+ "badge",
718
+ "bar-chart",
719
+ "blockquote",
720
+ "boolean",
721
+ "br",
722
+ "branding-editor",
723
+ "breadcrumb",
724
+ "button",
725
+ "button-group",
726
+ "calendar",
727
+ "calendar-view",
728
+ "card",
729
+ "carousel",
730
+ "chart",
731
+ "chart:bar",
732
+ "chatbot",
733
+ "chatbot-enhanced",
734
+ "chatbot-floating",
735
+ "checkbox",
736
+ "checkboxes",
737
+ "cite",
738
+ "cloud-connection:panel",
739
+ "cloud:ai-model-status",
740
+ "cloud:onboarding-next",
741
+ "code",
742
+ "code-editor",
743
+ "collapsible",
744
+ "color",
745
+ "combobox",
746
+ "command",
747
+ "container",
748
+ "context-menu",
749
+ "currency",
750
+ "dashboard",
751
+ "dashboard-editor",
752
+ "dashboard-grid",
753
+ "data-model-designer",
754
+ "data-table",
755
+ "date",
756
+ "date-picker",
757
+ "datetime",
758
+ "dd",
759
+ "del",
760
+ "detail",
761
+ "detail-section",
762
+ "detail-view",
763
+ "dialog",
764
+ "div",
765
+ "dl",
766
+ "donut-chart",
767
+ "drawer",
768
+ "dropdown-menu",
769
+ "dt",
770
+ "element:button",
771
+ "element:definition-list",
772
+ "element:divider",
773
+ "element:image",
774
+ "element:metadata_viewer",
775
+ "element:number",
776
+ "element:record_picker",
777
+ "element:repeater",
778
+ "element:text",
779
+ "element:text_input",
780
+ "em",
781
+ "email",
782
+ "embeddable-form",
783
+ "empty",
784
+ "field-designer",
785
+ "field:address",
786
+ "field:audio",
787
+ "field:auto_number",
788
+ "field:avatar",
789
+ "field:boolean",
790
+ "field:checkboxes",
791
+ "field:code",
792
+ "field:color",
793
+ "field:currency",
794
+ "field:date",
795
+ "field:datetime",
796
+ "field:duration",
797
+ "field:email",
798
+ "field:file",
799
+ "field:filter-condition",
800
+ "field:formula",
801
+ "field:geolocation",
802
+ "field:grid",
803
+ "field:html",
804
+ "field:image",
805
+ "field:json",
806
+ "field:location",
807
+ "field:lookup",
808
+ "field:markdown",
809
+ "field:master_detail",
810
+ "field:multiselect",
811
+ "field:number",
812
+ "field:object",
813
+ "field:object-ref",
814
+ "field:password",
815
+ "field:percent",
816
+ "field:permission-facet-link",
817
+ "field:phone",
818
+ "field:progress",
819
+ "field:qrcode",
820
+ "field:radio",
821
+ "field:rating",
822
+ "field:recipient-picker",
823
+ "field:richtext",
824
+ "field:select",
825
+ "field:signature",
826
+ "field:slider",
827
+ "field:summary",
828
+ "field:tags",
829
+ "field:text",
830
+ "field:textarea",
831
+ "field:time",
832
+ "field:tree",
833
+ "field:url",
834
+ "field:user",
835
+ "field:vector",
836
+ "field:video",
837
+ "figcaption",
838
+ "figure",
839
+ "file",
840
+ "file-upload",
841
+ "filter-builder",
842
+ "filter-ui",
843
+ "flex",
844
+ "footer",
845
+ "form",
846
+ "form-analytics",
847
+ "formula",
848
+ "gantt",
849
+ "geolocation",
850
+ "global:notifications",
851
+ "global:search",
852
+ "grid",
853
+ "h1",
854
+ "h2",
855
+ "h3",
856
+ "h4",
857
+ "h5",
858
+ "h6",
859
+ "header",
860
+ "header-bar",
861
+ "home",
862
+ "hover-card",
863
+ "hr",
864
+ "html",
865
+ "i",
866
+ "icon",
867
+ "image",
868
+ "img",
869
+ "import-wizard",
870
+ "input",
871
+ "input-otp",
872
+ "ins",
873
+ "kanban",
874
+ "kanban-enhanced",
875
+ "kanban-ui",
876
+ "kbd",
877
+ "label",
878
+ "layout:app-schema-renderer",
879
+ "layout:navigation-renderer",
880
+ "layout:page-header",
881
+ "layout:page:card",
882
+ "layout:responsive-grid",
883
+ "li",
884
+ "line-chart",
885
+ "list",
886
+ "list-view",
887
+ "loading",
888
+ "location",
889
+ "lookup",
890
+ "main",
891
+ "map",
892
+ "mark",
893
+ "markdown",
894
+ "marketplace:installed-list",
895
+ "master_detail",
896
+ "mcp:connect-agent",
897
+ "menubar",
898
+ "metric",
899
+ "metric-card",
900
+ "multiselect",
901
+ "nav",
902
+ "nav:breadcrumb",
903
+ "nav:menu",
904
+ "navigation-designer",
905
+ "navigation-menu",
906
+ "navigation-renderer",
907
+ "nl-query",
908
+ "number",
909
+ "object",
910
+ "object-calendar",
911
+ "object-chart",
912
+ "object-data-table",
913
+ "object-form",
914
+ "object-gallery",
915
+ "object-gantt",
916
+ "object-grid",
917
+ "object-kanban",
918
+ "object-manager",
919
+ "object-map",
920
+ "object-master-detail-form",
921
+ "object-metric",
922
+ "object-pivot",
923
+ "object-timeline",
924
+ "object-tree",
925
+ "object-view",
926
+ "ol",
927
+ "p",
928
+ "page",
929
+ "page-designer",
930
+ "page-header",
931
+ "page:accordion",
932
+ "page:card",
933
+ "page:footer",
934
+ "page:header",
935
+ "page:section",
936
+ "page:sidebar",
937
+ "page:tabs",
938
+ "pagination",
939
+ "password",
940
+ "percent",
941
+ "phone",
942
+ "pie-chart",
943
+ "pivot",
944
+ "plugin-calendar:calendar-view",
945
+ "plugin-calendar:object-calendar",
946
+ "plugin-charts:advanced-chart",
947
+ "plugin-charts:area-chart",
948
+ "plugin-charts:bar-chart",
949
+ "plugin-charts:chart",
950
+ "plugin-charts:chart:bar",
951
+ "plugin-charts:donut-chart",
952
+ "plugin-charts:line-chart",
953
+ "plugin-charts:object-chart",
954
+ "plugin-charts:pie-chart",
955
+ "plugin-charts:radar-chart",
956
+ "plugin-charts:scatter-chart",
957
+ "plugin-chatbot:chatbot",
958
+ "plugin-chatbot:chatbot-enhanced",
959
+ "plugin-chatbot:chatbot-floating",
960
+ "plugin-dashboard:dashboard",
961
+ "plugin-dashboard:dashboard-grid",
962
+ "plugin-dashboard:metric",
963
+ "plugin-dashboard:metric-card",
964
+ "plugin-dashboard:object-data-table",
965
+ "plugin-dashboard:object-metric",
966
+ "plugin-dashboard:object-pivot",
967
+ "plugin-dashboard:pivot",
968
+ "plugin-designer:app-creation-wizard",
969
+ "plugin-designer:branding-editor",
970
+ "plugin-designer:dashboard-editor",
971
+ "plugin-designer:data-model-designer",
972
+ "plugin-designer:field-designer",
973
+ "plugin-designer:navigation-designer",
974
+ "plugin-designer:object-manager",
975
+ "plugin-designer:page-designer",
976
+ "plugin-designer:process-designer",
977
+ "plugin-designer:report-designer",
978
+ "plugin-detail:detail-section",
979
+ "plugin-detail:detail-view",
980
+ "plugin-detail:related-list",
981
+ "plugin-editor:code-editor",
982
+ "plugin-form:embeddable-form",
983
+ "plugin-form:form-analytics",
984
+ "plugin-form:object-form",
985
+ "plugin-form:object-master-detail-form",
986
+ "plugin-gantt:object-gantt",
987
+ "plugin-grid:import-wizard",
988
+ "plugin-grid:object-grid",
989
+ "plugin-kanban:kanban-enhanced",
990
+ "plugin-kanban:kanban-ui",
991
+ "plugin-kanban:object-kanban",
992
+ "plugin-list:list-view",
993
+ "plugin-list:object-gallery",
994
+ "plugin-map:object-map",
995
+ "plugin-markdown:markdown",
996
+ "plugin-report:report",
997
+ "plugin-report:report-viewer",
998
+ "plugin-report:spec-report",
999
+ "plugin-timeline:object-timeline",
1000
+ "plugin-timeline:timeline",
1001
+ "plugin-tree:object-tree",
1002
+ "plugin-view:object-view",
1003
+ "plugin-view:view",
1004
+ "plugin-view:view:simple",
1005
+ "popover",
1006
+ "pre",
1007
+ "process-designer",
1008
+ "progress",
1009
+ "protocol-placeholder:ai:feedback",
1010
+ "protocol-placeholder:ai:input",
1011
+ "protocol-placeholder:ai:suggestion",
1012
+ "protocol-placeholder:app:launcher",
1013
+ "protocol-placeholder:field:address",
1014
+ "protocol-placeholder:field:audio",
1015
+ "protocol-placeholder:field:avatar",
1016
+ "protocol-placeholder:field:boolean",
1017
+ "protocol-placeholder:field:checkboxes",
1018
+ "protocol-placeholder:field:code",
1019
+ "protocol-placeholder:field:color",
1020
+ "protocol-placeholder:field:currency",
1021
+ "protocol-placeholder:field:date",
1022
+ "protocol-placeholder:field:datetime",
1023
+ "protocol-placeholder:field:duration",
1024
+ "protocol-placeholder:field:email",
1025
+ "protocol-placeholder:field:file",
1026
+ "protocol-placeholder:field:html",
1027
+ "protocol-placeholder:field:image",
1028
+ "protocol-placeholder:field:json",
1029
+ "protocol-placeholder:field:location",
1030
+ "protocol-placeholder:field:lookup",
1031
+ "protocol-placeholder:field:markdown",
1032
+ "protocol-placeholder:field:master_detail",
1033
+ "protocol-placeholder:field:multiselect",
1034
+ "protocol-placeholder:field:number",
1035
+ "protocol-placeholder:field:password",
1036
+ "protocol-placeholder:field:percent",
1037
+ "protocol-placeholder:field:phone",
1038
+ "protocol-placeholder:field:progress",
1039
+ "protocol-placeholder:field:qrcode",
1040
+ "protocol-placeholder:field:radio",
1041
+ "protocol-placeholder:field:rating",
1042
+ "protocol-placeholder:field:select",
1043
+ "protocol-placeholder:field:signature",
1044
+ "protocol-placeholder:field:slider",
1045
+ "protocol-placeholder:field:text",
1046
+ "protocol-placeholder:field:textarea",
1047
+ "protocol-placeholder:field:time",
1048
+ "protocol-placeholder:field:tree",
1049
+ "protocol-placeholder:field:url",
1050
+ "protocol-placeholder:field:video",
1051
+ "protocol-placeholder:global:notifications",
1052
+ "protocol-placeholder:global:search",
1053
+ "protocol-placeholder:nav:breadcrumb",
1054
+ "protocol-placeholder:nav:menu",
1055
+ "protocol-placeholder:page-header",
1056
+ "protocol-placeholder:page:accordion",
1057
+ "protocol-placeholder:page:card",
1058
+ "protocol-placeholder:page:footer",
1059
+ "protocol-placeholder:page:header",
1060
+ "protocol-placeholder:page:sidebar",
1061
+ "protocol-placeholder:page:tabs",
1062
+ "protocol-placeholder:record:activity",
1063
+ "protocol-placeholder:record:chatter",
1064
+ "protocol-placeholder:record:details",
1065
+ "protocol-placeholder:record:highlights",
1066
+ "protocol-placeholder:record:path",
1067
+ "protocol-placeholder:record:related_list",
1068
+ "protocol-placeholder:user:profile",
1069
+ "protocol-placeholder:view:calendar",
1070
+ "protocol-placeholder:view:drawer",
1071
+ "protocol-placeholder:view:gallery",
1072
+ "protocol-placeholder:view:gantt",
1073
+ "protocol-placeholder:view:grid",
1074
+ "protocol-placeholder:view:kanban",
1075
+ "protocol-placeholder:view:map",
1076
+ "protocol-placeholder:view:modal",
1077
+ "protocol-placeholder:view:simple",
1078
+ "protocol-placeholder:view:split",
1079
+ "protocol-placeholder:view:tabbed",
1080
+ "protocol-placeholder:view:timeline",
1081
+ "protocol-placeholder:view:wizard",
1082
+ "protocol-placeholder:widget:bar",
1083
+ "protocol-placeholder:widget:funnel",
1084
+ "protocol-placeholder:widget:heatmap",
1085
+ "protocol-placeholder:widget:image",
1086
+ "protocol-placeholder:widget:line",
1087
+ "protocol-placeholder:widget:metric",
1088
+ "protocol-placeholder:widget:pie",
1089
+ "protocol-placeholder:widget:pivot",
1090
+ "protocol-placeholder:widget:radar",
1091
+ "protocol-placeholder:widget:scatter",
1092
+ "protocol-placeholder:widget:table",
1093
+ "protocol-placeholder:widget:text",
1094
+ "q",
1095
+ "qrcode",
1096
+ "radar-chart",
1097
+ "radio",
1098
+ "radio-group",
1099
+ "rating",
1100
+ "record",
1101
+ "record:activity",
1102
+ "record:alert",
1103
+ "record:approvals",
1104
+ "record:attachments",
1105
+ "record:chatter",
1106
+ "record:details",
1107
+ "record:discussion",
1108
+ "record:highlights",
1109
+ "record:history",
1110
+ "record:line_items",
1111
+ "record:path",
1112
+ "record:quick_actions",
1113
+ "record:reference_rail",
1114
+ "record:related_list",
1115
+ "related-list",
1116
+ "report",
1117
+ "report-designer",
1118
+ "report-viewer",
1119
+ "report:report",
1120
+ "report:report-viewer",
1121
+ "report:spec-report",
1122
+ "resizable",
1123
+ "responsive-grid",
1124
+ "richtext",
1125
+ "scatter-chart",
1126
+ "scroll-area",
1127
+ "section",
1128
+ "select",
1129
+ "separator",
1130
+ "shared-view-link",
1131
+ "sheet",
1132
+ "sidebar",
1133
+ "sidebar-content",
1134
+ "sidebar-footer",
1135
+ "sidebar-group",
1136
+ "sidebar-header",
1137
+ "sidebar-inset",
1138
+ "sidebar-menu",
1139
+ "sidebar-menu-button",
1140
+ "sidebar-menu-item",
1141
+ "sidebar-provider",
1142
+ "sidebar-trigger",
1143
+ "signature",
1144
+ "skeleton",
1145
+ "slider",
1146
+ "small",
1147
+ "sonner",
1148
+ "sort-ui",
1149
+ "span",
1150
+ "spec-report",
1151
+ "spinner",
1152
+ "stack",
1153
+ "statistic",
1154
+ "strong",
1155
+ "sub",
1156
+ "summary",
1157
+ "sup",
1158
+ "switch",
1159
+ "table",
1160
+ "tabs",
1161
+ "tags",
1162
+ "text",
1163
+ "textarea",
1164
+ "time",
1165
+ "timeline",
1166
+ "toast",
1167
+ "toaster",
1168
+ "toggle",
1169
+ "toggle-group",
1170
+ "tooltip",
1171
+ "tree",
1172
+ "tree-view",
1173
+ "u",
1174
+ "ui:a",
1175
+ "ui:abbr",
1176
+ "ui:accordion",
1177
+ "ui:address",
1178
+ "ui:alert",
1179
+ "ui:alert-dialog",
1180
+ "ui:article",
1181
+ "ui:aside",
1182
+ "ui:aspect-ratio",
1183
+ "ui:avatar",
1184
+ "ui:b",
1185
+ "ui:badge",
1186
+ "ui:blockquote",
1187
+ "ui:br",
1188
+ "ui:breadcrumb",
1189
+ "ui:button",
1190
+ "ui:button-group",
1191
+ "ui:calendar",
1192
+ "ui:card",
1193
+ "ui:carousel",
1194
+ "ui:checkbox",
1195
+ "ui:cite",
1196
+ "ui:collapsible",
1197
+ "ui:combobox",
1198
+ "ui:command",
1199
+ "ui:container",
1200
+ "ui:context-menu",
1201
+ "ui:data-table",
1202
+ "ui:date-picker",
1203
+ "ui:dd",
1204
+ "ui:del",
1205
+ "ui:dialog",
1206
+ "ui:div",
1207
+ "ui:dl",
1208
+ "ui:drawer",
1209
+ "ui:dropdown-menu",
1210
+ "ui:dt",
1211
+ "ui:em",
1212
+ "ui:email",
1213
+ "ui:empty",
1214
+ "ui:figcaption",
1215
+ "ui:figure",
1216
+ "ui:file-upload",
1217
+ "ui:filter-builder",
1218
+ "ui:flex",
1219
+ "ui:footer",
1220
+ "ui:grid",
1221
+ "ui:h1",
1222
+ "ui:h2",
1223
+ "ui:h3",
1224
+ "ui:h4",
1225
+ "ui:h5",
1226
+ "ui:h6",
1227
+ "ui:header",
1228
+ "ui:header-bar",
1229
+ "ui:hover-card",
1230
+ "ui:hr",
1231
+ "ui:html",
1232
+ "ui:i",
1233
+ "ui:icon",
1234
+ "ui:image",
1235
+ "ui:img",
1236
+ "ui:input",
1237
+ "ui:input-otp",
1238
+ "ui:ins",
1239
+ "ui:kbd",
1240
+ "ui:label",
1241
+ "ui:li",
1242
+ "ui:list",
1243
+ "ui:loading",
1244
+ "ui:main",
1245
+ "ui:mark",
1246
+ "ui:menubar",
1247
+ "ui:nav",
1248
+ "ui:navigation-menu",
1249
+ "ui:ol",
1250
+ "ui:p",
1251
+ "ui:pagination",
1252
+ "ui:password",
1253
+ "ui:popover",
1254
+ "ui:pre",
1255
+ "ui:progress",
1256
+ "ui:q",
1257
+ "ui:radio-group",
1258
+ "ui:resizable",
1259
+ "ui:scroll-area",
1260
+ "ui:section",
1261
+ "ui:select",
1262
+ "ui:separator",
1263
+ "ui:sheet",
1264
+ "ui:sidebar",
1265
+ "ui:sidebar-content",
1266
+ "ui:sidebar-footer",
1267
+ "ui:sidebar-group",
1268
+ "ui:sidebar-header",
1269
+ "ui:sidebar-inset",
1270
+ "ui:sidebar-menu",
1271
+ "ui:sidebar-menu-button",
1272
+ "ui:sidebar-menu-item",
1273
+ "ui:sidebar-provider",
1274
+ "ui:sidebar-trigger",
1275
+ "ui:skeleton",
1276
+ "ui:slider",
1277
+ "ui:small",
1278
+ "ui:sonner",
1279
+ "ui:span",
1280
+ "ui:spinner",
1281
+ "ui:stack",
1282
+ "ui:statistic",
1283
+ "ui:strong",
1284
+ "ui:sub",
1285
+ "ui:sup",
1286
+ "ui:switch",
1287
+ "ui:table",
1288
+ "ui:tabs",
1289
+ "ui:text",
1290
+ "ui:textarea",
1291
+ "ui:time",
1292
+ "ui:toast",
1293
+ "ui:toaster",
1294
+ "ui:toggle",
1295
+ "ui:toggle-group",
1296
+ "ui:tooltip",
1297
+ "ui:tree-view",
1298
+ "ui:u",
1299
+ "ui:ul",
1300
+ "ul",
1301
+ "url",
1302
+ "user",
1303
+ "user:profile",
1304
+ "utility",
1305
+ "vector",
1306
+ "view",
1307
+ "view-switcher",
1308
+ "view:calendar",
1309
+ "view:chart",
1310
+ "view:dashboard",
1311
+ "view:detail",
1312
+ "view:drawer",
1313
+ "view:filter-ui",
1314
+ "view:form",
1315
+ "view:gallery",
1316
+ "view:gantt",
1317
+ "view:grid",
1318
+ "view:kanban",
1319
+ "view:list",
1320
+ "view:map",
1321
+ "view:modal",
1322
+ "view:shared-view-link",
1323
+ "view:simple",
1324
+ "view:sort-ui",
1325
+ "view:split",
1326
+ "view:tabbed",
1327
+ "view:timeline",
1328
+ "view:tree",
1329
+ "view:view-switcher",
1330
+ "view:wizard",
1331
+ "widget:bar",
1332
+ "widget:funnel",
1333
+ "widget:heatmap",
1334
+ "widget:image",
1335
+ "widget:line",
1336
+ "widget:metric",
1337
+ "widget:pie",
1338
+ "widget:pivot",
1339
+ "widget:radar",
1340
+ "widget:scatter",
1341
+ "widget:table",
1342
+ "widget:text"
1343
+ ];
1344
+ var KNOWN_SCHEMA_TYPE_SET = new Set(KNOWN_SCHEMA_TYPES);
1345
+ function isKnownSchemaType(type) {
1346
+ return KNOWN_SCHEMA_TYPE_SET.has(type);
1347
+ }
1348
+
1349
+ // src/commands/check.ts
1350
+ var OBJECTUI_STRUCTURAL_KEYS = [
1351
+ // Composition — the `children`/`body`-class keys the ruling names.
1352
+ "body",
1353
+ "children",
1354
+ // Presentation.
1355
+ "className",
1356
+ "style",
1357
+ "placeholder",
1358
+ // Conditional rendering and interaction state.
1359
+ "visible",
1360
+ "visibleWhen",
1361
+ "visibleOn",
1362
+ "hidden",
1363
+ "hiddenOn",
1364
+ "disabled",
1365
+ "disabledOn",
1366
+ // Test and accessibility handles.
1367
+ "testId",
1368
+ "ariaLabel"
1369
+ ];
1370
+ function isObjectUiSchemaFile(content) {
1371
+ return OBJECTUI_STRUCTURAL_KEYS.some((key) => key in content);
1372
+ }
1373
+ function describeParseError(text, error) {
1374
+ const upTo = text.slice(0, error.offset);
1375
+ const line = upTo.split("\n").length;
1376
+ const column = error.offset - (upTo.lastIndexOf("\n") + 1) + 1;
1377
+ return `${printParseErrorCode(error.error)} at line ${line} column ${column}`;
1378
+ }
1379
+ async function check(cwd = process.cwd()) {
799
1380
  console.log(chalk10.bold("Object UI Schema Check"));
800
- const cwd = process.cwd();
801
1381
  const files = globSync("**/*.{json,yaml,yml}", {
802
1382
  cwd,
803
1383
  ignore: ["node_modules/**", "dist/**", ".git/**"]
804
1384
  });
805
1385
  console.log(`Analyzing ${files.length} files...`);
806
1386
  let errors = 0;
1387
+ let skipped = 0;
807
1388
  for (const file of files) {
808
1389
  try {
809
1390
  if (file.endsWith(".json")) {
810
- const content = JSON.parse(readFileSync2(join9(cwd, file), "utf-8"));
1391
+ const text = readFileSync2(join9(cwd, file), "utf-8");
1392
+ const parseErrors = [];
1393
+ const content = parseJsonc(text, parseErrors, { allowTrailingComma: true });
1394
+ if (parseErrors.length > 0) {
1395
+ const [first] = parseErrors;
1396
+ console.log(
1397
+ chalk10.red(`x Invalid JSON in ${file}: ${describeParseError(text, first)}`)
1398
+ );
1399
+ errors++;
1400
+ continue;
1401
+ }
811
1402
  if (content && typeof content === "object" && content.type) {
812
- const knownTypes = [
813
- "page",
814
- "form",
815
- "grid",
816
- "crud",
817
- "kanban",
818
- "calendar",
819
- "dashboard",
820
- "chart",
821
- "detail",
822
- "list",
823
- "timeline",
824
- "gantt",
825
- "map",
826
- "gallery",
827
- "object-view",
828
- "detail-view",
829
- "object-chart"
830
- ];
831
- if (typeof content.type === "string" && !knownTypes.includes(content.type)) {
832
- console.log(chalk10.yellow(`\u26A0\uFE0F Unknown schema type "${content.type}" in ${file}`));
1403
+ if (typeof content.type === "string") {
1404
+ if (!isObjectUiSchemaFile(content)) {
1405
+ skipped++;
1406
+ } else if (!isKnownSchemaType(content.type)) {
1407
+ console.log(chalk10.yellow(`\u26A0\uFE0F Unknown schema type "${content.type}" in ${file}`));
1408
+ }
833
1409
  }
834
1410
  }
835
1411
  }
@@ -838,6 +1414,18 @@ async function check() {
838
1414
  errors++;
839
1415
  }
840
1416
  }
1417
+ if (skipped > 0) {
1418
+ console.log(
1419
+ chalk10.dim(
1420
+ `Skipped ${skipped} file${skipped === 1 ? "" : "s"} with a root "type" and no ObjectUI schema marker.`
1421
+ )
1422
+ );
1423
+ console.log(
1424
+ chalk10.dim(
1425
+ ` A file is checked when its root carries an ObjectUI structural key: ${OBJECTUI_STRUCTURAL_KEYS.join(", ")}.`
1426
+ )
1427
+ );
1428
+ }
841
1429
  if (errors === 0) {
842
1430
  console.log(chalk10.green("\u2713 All checks passed"));
843
1431
  } else {
@@ -848,8 +1436,8 @@ async function check() {
848
1436
 
849
1437
  // src/commands/validate.ts
850
1438
  import chalk11 from "chalk";
851
- import { readFileSync as readFileSync3, existsSync as existsSync9 } from "fs";
852
- import { resolve as resolve5 } from "path";
1439
+ import { readFileSync as readFileSync3, existsSync as existsSync8 } from "fs";
1440
+ import { resolve as resolve4 } from "path";
853
1441
  import { load as loadYaml } from "js-yaml";
854
1442
  import { safeValidateSchema } from "@object-ui/types/zod";
855
1443
 
@@ -885,8 +1473,8 @@ function findSpecVocabularyFormFields(node, path = "") {
885
1473
  // src/commands/validate.ts
886
1474
  async function validate(schemaPath) {
887
1475
  console.log(chalk11.blue("\u{1F50D} ObjectUI Schema Validator\n"));
888
- const resolvedPath = resolve5(process.cwd(), schemaPath);
889
- if (!existsSync9(resolvedPath)) {
1476
+ const resolvedPath = resolve4(process.cwd(), schemaPath);
1477
+ if (!existsSync8(resolvedPath)) {
890
1478
  console.error(chalk11.red(`\u2717 Error: Schema file not found: ${schemaPath}`));
891
1479
  process.exit(1);
892
1480
  }
@@ -977,17 +1565,17 @@ ${index + 1}. ${issue.message}`));
977
1565
  // src/commands/create-plugin.ts
978
1566
  import chalk12 from "chalk";
979
1567
  import { spawn as spawn2 } from "child_process";
980
- import { resolve as resolve6, dirname as dirname4 } from "path";
1568
+ import { resolve as resolve5, dirname as dirname3 } from "path";
981
1569
  import { fileURLToPath as fileURLToPath2 } from "url";
982
1570
  var __filename = fileURLToPath2(import.meta.url);
983
- var __dirname = dirname4(__filename);
1571
+ var __dirname = dirname3(__filename);
984
1572
  async function createPlugin(pluginName) {
985
1573
  console.log(chalk12.blue("\u{1F680} Creating ObjectUI plugin...\n"));
986
- const createPluginScript = resolve6(
1574
+ const createPluginScript = resolve5(
987
1575
  __dirname,
988
1576
  "../../../create-plugin/dist/index.js"
989
1577
  );
990
- return new Promise((resolve8, reject) => {
1578
+ return new Promise((resolve7, reject) => {
991
1579
  const child = spawn2("node", [createPluginScript, pluginName], {
992
1580
  stdio: "inherit",
993
1581
  shell: true
@@ -998,7 +1586,7 @@ async function createPlugin(pluginName) {
998
1586
  });
999
1587
  child.on("exit", (code) => {
1000
1588
  if (code === 0) {
1001
- resolve8();
1589
+ resolve7();
1002
1590
  } else {
1003
1591
  reject(new Error(`create-plugin exited with code ${code}`));
1004
1592
  }
@@ -1008,12 +1596,12 @@ async function createPlugin(pluginName) {
1008
1596
 
1009
1597
  // src/commands/analyze.ts
1010
1598
  import chalk13 from "chalk";
1011
- import { existsSync as existsSync10, statSync as statSync2, readdirSync } from "fs";
1012
- import { resolve as resolve7, join as join10, extname } from "path";
1599
+ import { existsSync as existsSync9, statSync, readdirSync } from "fs";
1600
+ import { resolve as resolve6, join as join10, extname } from "path";
1013
1601
  async function analyzeBundleSize() {
1014
1602
  console.log(chalk13.bold("\n\u{1F4E6} Bundle Size Analysis\n"));
1015
- const distDir = resolve7(process.cwd(), "dist");
1016
- if (!existsSync10(distDir)) {
1603
+ const distDir = resolve6(process.cwd(), "dist");
1604
+ if (!existsSync9(distDir)) {
1017
1605
  console.log(chalk13.yellow("\u26A0 No dist directory found. Run build first."));
1018
1606
  return;
1019
1607
  }
@@ -1022,7 +1610,7 @@ async function analyzeBundleSize() {
1022
1610
  const items = readdirSync(dir);
1023
1611
  for (const item of items) {
1024
1612
  const fullPath = join10(dir, item);
1025
- const stat = statSync2(fullPath);
1613
+ const stat = statSync(fullPath);
1026
1614
  if (stat.isDirectory()) {
1027
1615
  scanDirectory(fullPath);
1028
1616
  } else {
@@ -1104,15 +1692,15 @@ async function analyze(options = {}) {
1104
1692
  // src/cli.ts
1105
1693
  import { readFileSync as readFileSync4 } from "fs";
1106
1694
  import { fileURLToPath as fileURLToPath3 } from "url";
1107
- import { dirname as dirname5, join as join11 } from "path";
1695
+ import { dirname as dirname4, join as join11 } from "path";
1108
1696
  var __filename2 = fileURLToPath3(import.meta.url);
1109
- var __dirname2 = dirname5(__filename2);
1697
+ var __dirname2 = dirname4(__filename2);
1110
1698
  var packageJson = JSON.parse(
1111
1699
  readFileSync4(join11(__dirname2, "../package.json"), "utf-8")
1112
1700
  );
1113
1701
  var program = new Command();
1114
1702
  program.name("objectui").description("CLI tool for Object UI - Build applications from JSON schemas").version(packageJson.version);
1115
- program.command("serve").description("Start a development server with your JSON/YAML schema").argument("[schema]", "Path to JSON/YAML schema file", "app.json").option("-p, --port <port>", "Port to run the server on", "3000").option("-h, --host <host>", "Host to bind the server to", "localhost").action(async (schema, options) => {
1703
+ program.command("serve").description("Start a development server with your JSON/YAML schema").argument("[schema]", "Path to JSON/YAML schema file, or a project / pages directory", "app.json").option("-p, --port <port>", "Port to run the server on", "3000").option("-h, --host <host>", "Host to bind the server to", "localhost").option("--no-open", "Do not open browser automatically").action(async (schema, options) => {
1116
1704
  try {
1117
1705
  await serve(schema, options);
1118
1706
  } catch (error) {
@@ -1120,7 +1708,7 @@ program.command("serve").description("Start a development server with your JSON/
1120
1708
  process.exit(1);
1121
1709
  }
1122
1710
  });
1123
- program.command("dev").description("Start development server (alias for serve)").argument("[schema]", "Path to JSON/YAML schema file", "app.json").option("-p, --port <port>", "Port to run the server on", "3000").option("-h, --host <host>", "Host to bind the server to", "localhost").option("--no-open", "Do not open browser automatically").action(async (schema, options) => {
1711
+ program.command("dev").description("Start development server (alias for serve)").argument("[schema]", "Path to JSON/YAML schema file, or a project / pages directory", "app.json").option("-p, --port <port>", "Port to run the server on", "3000").option("-h, --host <host>", "Host to bind the server to", "localhost").option("--no-open", "Do not open browser automatically").action(async (schema, options) => {
1124
1712
  try {
1125
1713
  await dev(schema, options);
1126
1714
  } catch (error) {
@@ -1128,7 +1716,7 @@ program.command("dev").description("Start development server (alias for serve)")
1128
1716
  process.exit(1);
1129
1717
  }
1130
1718
  });
1131
- program.command("build").description("Build application for production").argument("[schema]", "Path to JSON/YAML schema file", "app.json").option("-o, --out-dir <dir>", "Output directory", "dist").option("--clean", "Clean output directory before build", false).action(async (schema, options) => {
1719
+ program.command("build").description("Build application for production").argument("[schema]", "Path to JSON/YAML schema file, or a project / pages directory", "app.json").option("-o, --out-dir <dir>", "Output directory", "dist").option("--clean", "Clean output directory before build", false).action(async (schema, options) => {
1132
1720
  try {
1133
1721
  await buildApp(schema, options);
1134
1722
  } catch (error) {