@jxsuite/schema 0.28.0 → 0.28.3

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/src/schema.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * jx-schema.ts — Jx JSON Schema 2020-12 meta-schema generator
2
+ * Jx-schema.ts — Jx JSON Schema 2020-12 meta-schema generator
3
3
  * @version 2.0.0
4
4
  * @license MIT
5
5
  *
@@ -28,65 +28,65 @@ import idl from "@webref/idl";
28
28
 
29
29
  import { tagNameSchema } from "../defs/tag-name.schema";
30
30
  import {
31
- stringOrRefSchema,
32
31
  boolOrRefSchema,
33
32
  numberOrRefSchema,
33
+ stringOrRefSchema,
34
34
  } from "../defs/string-or-ref.schema";
35
35
  import { headEntrySchema } from "../defs/head-entry.schema";
36
- import { cemParameterSchema, cemEventSchema } from "../defs/cem.schema";
36
+ import { cemEventSchema, cemParameterSchema } from "../defs/cem.schema";
37
37
  import { jsonSchemaTypeSchema } from "../defs/json-schema-type.schema";
38
38
  import {
39
- internalRefSchema,
40
- stateRefSchema,
39
+ anyRefSchema,
40
+ externalComponentRefSchema,
41
41
  externalRefSchema,
42
42
  globalRefSchema,
43
- parentRefSchema,
43
+ internalRefSchema,
44
44
  mapRefSchema,
45
- anyRefSchema,
45
+ parentRefSchema,
46
46
  refObjectSchema,
47
- externalComponentRefSchema,
47
+ stateRefSchema,
48
48
  } from "../defs/ref-object.schema";
49
49
  import { styleObjectSchema } from "../defs/style-object.schema";
50
50
  import { arrayNamespaceSchema, childrenValueSchema } from "../defs/children-value.schema";
51
51
  import {
52
52
  attributesObjectSchema,
53
- propsObjectSchema,
53
+ elementDefSchema,
54
54
  elementPropertyValueSchema,
55
+ propsObjectSchema,
55
56
  switchDefSchema,
56
57
  switchNodeSchema,
57
- elementDefSchema,
58
58
  } from "../defs/element-def.schema";
59
59
  import { typedStateDefSchema } from "../defs/typed-state-def.schema";
60
60
  import { functionDefSchema } from "../defs/function-def.schema";
61
61
  import { externalClassDefSchema } from "../defs/external-class-def.schema";
62
62
  import { pureTypeDefSchema } from "../defs/pure-type-def.schema";
63
63
  import {
64
- expressionPointerSchema,
64
+ assignmentOperatorSchema,
65
+ binaryOperatorSchema,
66
+ expressionEntrySchema,
65
67
  expressionLiteralSchema,
66
- expressionOperandSchema,
67
68
  expressionNodeSchema,
68
- expressionEntrySchema,
69
- unaryOperatorSchema,
70
- binaryOperatorSchema,
71
- assignmentOperatorSchema,
69
+ expressionOperandSchema,
70
+ expressionPointerSchema,
71
+ mapFilterMethodSchema,
72
72
  noArgMethodSchema,
73
73
  oneArgMethodSchema,
74
- spliceMethodSchema,
75
74
  reduceMethodSchema,
76
- mapFilterMethodSchema,
75
+ spliceMethodSchema,
76
+ unaryOperatorSchema,
77
77
  } from "../defs/expression-node.schema";
78
78
  import {
79
+ defsMapSchema,
79
80
  stateEntrySchema,
80
81
  stateMapSchema,
81
- defsMapSchema,
82
82
  typeDefEntrySchema,
83
83
  } from "../defs/state-entry.schema";
84
84
  import {
85
- classParameterDefSchema,
86
- classFieldDefSchema,
87
85
  classConstructorDefSchema,
88
- classMethodDefSchema,
89
86
  classDefSchema,
87
+ classFieldDefSchema,
88
+ classMethodDefSchema,
89
+ classParameterDefSchema,
90
90
  formatDefSchema,
91
91
  studioHintsSchema,
92
92
  } from "../defs/class-def.schema";
@@ -106,10 +106,12 @@ async function loadWebData() {
106
106
  const tagSet = new Set<string>();
107
107
  for (const { elements } of Object.values(elementsData)) {
108
108
  for (const el of elements) {
109
- if (!el.obsolete) tagSet.add(el.name);
109
+ if (!el.obsolete) {
110
+ tagSet.add(el.name);
111
+ }
110
112
  }
111
113
  }
112
- const tagExamples = [...tagSet].sort();
114
+ const tagExamples = [...tagSet].toSorted();
113
115
 
114
116
  const cssSet = new Set<string>();
115
117
  for (const prop of cssData.properties) {
@@ -117,13 +119,17 @@ async function loadWebData() {
117
119
  cssSet.add(decl);
118
120
  }
119
121
  }
120
- const cssProps = [...cssSet].sort();
122
+ const cssProps = [...cssSet].toSorted();
121
123
 
122
124
  const handlerSet = new Set<string>();
123
125
  for (const ast of Object.values(idlData)) {
124
126
  for (const def of ast) {
125
- if (def.type !== "interface" && def.type !== "interface mixin") continue;
126
- if (!def.members) continue;
127
+ if (def.type !== "interface" && def.type !== "interface mixin") {
128
+ continue;
129
+ }
130
+ if (!def.members) {
131
+ continue;
132
+ }
127
133
  for (const member of def.members) {
128
134
  if (
129
135
  member.type === "attribute" &&
@@ -136,15 +142,15 @@ async function loadWebData() {
136
142
  }
137
143
  }
138
144
  }
139
- const eventHandlers = [...handlerSet].sort();
145
+ const eventHandlers = [...handlerSet].toSorted();
140
146
 
141
- return { tagExamples, cssProps, eventHandlers };
147
+ return { cssProps, eventHandlers, tagExamples };
142
148
  }
143
149
 
144
150
  // ─── Injection helpers ─────────────────────────────────────────────────────────
145
151
 
146
152
  function buildEventHandlerProperties(eventHandlers: string[]) {
147
- const properties: Record<string, any> = {};
153
+ const properties: Record<string, unknown> = {};
148
154
  for (const name of eventHandlers) {
149
155
  properties[name] = {
150
156
  description: `Event handler for the "${name.slice(2)}" event.`,
@@ -155,7 +161,7 @@ function buildEventHandlerProperties(eventHandlers: string[]) {
155
161
  }
156
162
 
157
163
  function buildCssProperties(cssProps: string[]) {
158
- const properties: Record<string, any> = {};
164
+ const properties: Record<string, unknown> = {};
159
165
  for (const name of cssProps) {
160
166
  properties[name] = { oneOf: [{ type: "string" }, { type: "number" }] };
161
167
  }
@@ -168,132 +174,6 @@ export async function generateSchema() {
168
174
  const { tagExamples, cssProps, eventHandlers } = await loadWebData();
169
175
 
170
176
  return {
171
- $schema: "https://json-schema.org/draft/2020-12/schema",
172
- $id: "https://jxsuite.com/schema/v1",
173
- title: "Jx Document",
174
- description:
175
- "Schema for Jx component files. " +
176
- "A Jx document is a JSON object that declaratively describes a reactive " +
177
- "web component: its structure (DOM tree), styling, type definitions ($defs), " +
178
- "runtime state, and inline or external functions. Reactivity is powered by @vue/reactivity.",
179
- type: "object",
180
-
181
- properties: {
182
- $schema: {
183
- description: "URI identifying the Jx dialect version. Enables schema-aware IDE tooling.",
184
- type: "string",
185
- examples: ["https://jxsuite.com/schema/v1"],
186
- },
187
- $id: {
188
- description: "Component identifier string. Used by tooling and the builder.",
189
- type: "string",
190
- examples: ["Counter", "TodoApp", "UserCard"],
191
- },
192
- $defs: {
193
- description:
194
- "Pure JSON Schema type definitions for this component. " +
195
- "All entries are reusable type schemas — no runtime artifacts are produced. " +
196
- "Referenced from state entries via $ref. Naming convention: PascalCase.",
197
- $ref: "#/$defs/DefsMap",
198
- },
199
- state: {
200
- description:
201
- "Runtime variables for this component. All entries are reactive by default. " +
202
- "Entry shape is determined by value type: " +
203
- "scalar/array → reactive property, string with ${} → computed, " +
204
- "object with $prototype → function or data source, " +
205
- "object with type and default → typed reactive property.",
206
- $ref: "#/$defs/StateMap",
207
- },
208
- $media: {
209
- description:
210
- "Named media breakpoints following CSS @custom-media convention. " +
211
- "Keys use the CSS custom property -- prefix.",
212
- type: "object",
213
- additionalProperties: { type: "string" },
214
- examples: [
215
- {
216
- "--sm": "(min-width: 640px)",
217
- "--md": "(min-width: 768px)",
218
- "--dark": "(prefers-color-scheme: dark)",
219
- },
220
- ],
221
- },
222
- $elements: {
223
- description:
224
- "Custom element dependencies. Items are either $ref objects pointing to JX " +
225
- "element definitions, or bare npm package name strings for web component libraries.",
226
- type: "array",
227
- items: {
228
- oneOf: [
229
- {
230
- type: "object",
231
- required: ["$ref"],
232
- properties: { $ref: { type: "string" } },
233
- additionalProperties: false,
234
- },
235
- {
236
- type: "string",
237
- description: "npm package specifier (must declare customElements in package.json)",
238
- },
239
- ],
240
- },
241
- },
242
- $head: {
243
- description:
244
- "Page-level <head> entries. Array of element definitions for meta tags, " +
245
- "link tags, script tags, etc. Merged with layout and site-level $head entries.",
246
- type: "array",
247
- items: { $ref: "#/$defs/ElementDef" },
248
- },
249
- $layout: {
250
- description:
251
- "Layout reference for pages. String path to a layout JSON file, " +
252
- "or false to opt out of the default layout.",
253
- oneOf: [{ type: "string" }, { type: "boolean", const: false }],
254
- examples: ["./layouts/base.json"],
255
- },
256
- $paths: {
257
- description:
258
- "Dynamic route parameters. Maps parameter names to data sources " +
259
- "for generating one page per entry at build time.",
260
- type: "object",
261
- },
262
- title: {
263
- description:
264
- "Page title. Can be a static string or a template string with ${} expressions.",
265
- $ref: "#/$defs/StringOrRef",
266
- },
267
- imports: {
268
- description:
269
- "Import map: $prototype names to .class.json file paths. " +
270
- "Allows state entries to reference external classes by name without $src.",
271
- type: "object",
272
- additionalProperties: { type: "string" },
273
- },
274
- observedAttributes: {
275
- description:
276
- "HTML attributes the custom element watches for changes. " +
277
- "Follows the Web Components observedAttributes convention.",
278
- type: "array",
279
- items: { type: "string" },
280
- },
281
- cases: {
282
- description:
283
- "Switch cases object. Maps case values to element definitions or external " +
284
- "component refs. Used alongside $switch for dynamic component rendering.",
285
- type: "object",
286
- additionalProperties: {
287
- oneOf: [{ $ref: "#/$defs/ElementDef" }, { $ref: "#/$defs/ExternalComponentRef" }],
288
- },
289
- },
290
- tagName: { $ref: "#/$defs/TagName" },
291
- children: { $ref: "#/$defs/ChildrenValue" },
292
- style: { $ref: "#/$defs/StyleObject" },
293
- attributes: { $ref: "#/$defs/AttributesObject" },
294
- },
295
- additionalProperties: { $ref: "#/$defs/ElementPropertyValue" },
296
-
297
177
  $defs: {
298
178
  DefsMap: defsMapSchema,
299
179
  TypeDefEntry: typeDefEntrySchema,
@@ -366,6 +246,130 @@ export async function generateSchema() {
366
246
  ImageConfig: imageConfigSchema,
367
247
  ContentTypeDef: contentTypeDefSchema,
368
248
  },
249
+ $id: "https://jxsuite.com/schema/v1",
250
+ $schema: "https://json-schema.org/draft/2020-12/schema",
251
+ additionalProperties: { $ref: "#/$defs/ElementPropertyValue" },
252
+ description:
253
+ "Schema for Jx component files. " +
254
+ "A Jx document is a JSON object that declaratively describes a reactive " +
255
+ "web component: its structure (DOM tree), styling, type definitions ($defs), " +
256
+ "runtime state, and inline or external functions. Reactivity is powered by @vue/reactivity.",
257
+ properties: {
258
+ $defs: {
259
+ $ref: "#/$defs/DefsMap",
260
+ description:
261
+ "Pure JSON Schema type definitions for this component. " +
262
+ "All entries are reusable type schemas — no runtime artifacts are produced. " +
263
+ "Referenced from state entries via $ref. Naming convention: PascalCase.",
264
+ },
265
+ $elements: {
266
+ description:
267
+ "Custom element dependencies. Items are either $ref objects pointing to JX " +
268
+ "element definitions, or bare npm package name strings for web component libraries.",
269
+ items: {
270
+ oneOf: [
271
+ {
272
+ additionalProperties: false,
273
+ properties: { $ref: { type: "string" } },
274
+ required: ["$ref"],
275
+ type: "object",
276
+ },
277
+ {
278
+ description: "npm package specifier (must declare customElements in package.json)",
279
+ type: "string",
280
+ },
281
+ ],
282
+ },
283
+ type: "array",
284
+ },
285
+ $head: {
286
+ description:
287
+ "Page-level <head> entries. Array of element definitions for meta tags, " +
288
+ "link tags, script tags, etc. Merged with layout and site-level $head entries.",
289
+ items: { $ref: "#/$defs/ElementDef" },
290
+ type: "array",
291
+ },
292
+ $id: {
293
+ description: "Component identifier string. Used by tooling and the builder.",
294
+ examples: ["Counter", "TodoApp", "UserCard"],
295
+ type: "string",
296
+ },
297
+ $layout: {
298
+ description:
299
+ "Layout reference for pages. String path to a layout JSON file, " +
300
+ "or false to opt out of the default layout.",
301
+ examples: ["./layouts/base.json"],
302
+ oneOf: [{ type: "string" }, { const: false, type: "boolean" }],
303
+ },
304
+ $media: {
305
+ additionalProperties: { type: "string" },
306
+ description:
307
+ "Named media breakpoints following CSS @custom-media convention. " +
308
+ "Keys use the CSS custom property -- prefix.",
309
+ examples: [
310
+ {
311
+ "--dark": "(prefers-color-scheme: dark)",
312
+ "--md": "(min-width: 768px)",
313
+ "--sm": "(min-width: 640px)",
314
+ },
315
+ ],
316
+ type: "object",
317
+ },
318
+ $paths: {
319
+ description:
320
+ "Dynamic route parameters. Maps parameter names to data sources " +
321
+ "for generating one page per entry at build time.",
322
+ type: "object",
323
+ },
324
+ $schema: {
325
+ description: "URI identifying the Jx dialect version. Enables schema-aware IDE tooling.",
326
+ examples: ["https://jxsuite.com/schema/v1"],
327
+ type: "string",
328
+ },
329
+ attributes: { $ref: "#/$defs/AttributesObject" },
330
+ cases: {
331
+ additionalProperties: {
332
+ oneOf: [{ $ref: "#/$defs/ElementDef" }, { $ref: "#/$defs/ExternalComponentRef" }],
333
+ },
334
+ description:
335
+ "Switch cases object. Maps case values to element definitions or external " +
336
+ "component refs. Used alongside $switch for dynamic component rendering.",
337
+ type: "object",
338
+ },
339
+ children: { $ref: "#/$defs/ChildrenValue" },
340
+ imports: {
341
+ additionalProperties: { type: "string" },
342
+ description:
343
+ "Import map: $prototype names to .class.json file paths. " +
344
+ "Allows state entries to reference external classes by name without $src.",
345
+ type: "object",
346
+ },
347
+ observedAttributes: {
348
+ description:
349
+ "HTML attributes the custom element watches for changes. " +
350
+ "Follows the Web Components observedAttributes convention.",
351
+ items: { type: "string" },
352
+ type: "array",
353
+ },
354
+ state: {
355
+ $ref: "#/$defs/StateMap",
356
+ description:
357
+ "Runtime variables for this component. All entries are reactive by default. " +
358
+ "Entry shape is determined by value type: " +
359
+ "scalar/array → reactive property, string with ${} → computed, " +
360
+ "object with $prototype → function or data source, " +
361
+ "object with type and default → typed reactive property.",
362
+ },
363
+ style: { $ref: "#/$defs/StyleObject" },
364
+ tagName: { $ref: "#/$defs/TagName" },
365
+ title: {
366
+ $ref: "#/$defs/StringOrRef",
367
+ description:
368
+ "Page title. Can be a static string or a template string with ${} expressions.",
369
+ },
370
+ },
371
+ title: "Jx Document",
372
+ type: "object",
369
373
  };
370
374
  }
371
375
 
@@ -373,21 +377,21 @@ export async function generateSchema() {
373
377
 
374
378
  export function generateProjectSchema() {
375
379
  return {
376
- $schema: "https://json-schema.org/draft/2020-12/schema",
380
+ $defs: {
381
+ ContentTypeDef: contentTypeDefSchema,
382
+ ImageConfig: imageConfigSchema,
383
+ },
377
384
  $id: "https://jxsuite.com/schema/project/v1",
378
- title: "Jx Project",
385
+ $schema: "https://json-schema.org/draft/2020-12/schema",
386
+ additionalProperties: false,
379
387
  description:
380
388
  "Schema for Jx project.json files. " +
381
389
  "A project.json file is the root anchor file for a Jx project, " +
382
390
  "declaring site metadata, default settings, global styles, content types, " +
383
391
  "and build configuration.",
384
- type: "object",
385
392
  properties: projectConfigSchema.properties,
386
- additionalProperties: false,
387
- $defs: {
388
- ImageConfig: imageConfigSchema,
389
- ContentTypeDef: contentTypeDefSchema,
390
- },
393
+ title: "Jx Project",
394
+ type: "object",
391
395
  };
392
396
  }
393
397
 
@@ -395,85 +399,85 @@ export function generateProjectSchema() {
395
399
 
396
400
  export function generateClassSchema() {
397
401
  return {
398
- $schema: "https://json-schema.org/draft/2020-12/schema",
402
+ $defs: {
403
+ ClassConstructorDef: classConstructorDefSchema,
404
+ ClassFieldDef: classFieldDefSchema,
405
+ ClassMethodDef: classMethodDefSchema,
406
+ ClassParameterDef: classParameterDefSchema,
407
+ FormatDef: formatDefSchema,
408
+ StudioHints: studioHintsSchema,
409
+ },
399
410
  $id: "https://jxsuite.com/schema/class/v1",
400
- title: "Jx Class Definition",
411
+ $schema: "https://json-schema.org/draft/2020-12/schema",
412
+ additionalProperties: false,
401
413
  description:
402
414
  "Schema for Jx .class.json files. A class definition describes a schema-defined " +
403
415
  "class with fields, constructor, methods, and type parameters. Optionally points " +
404
416
  "to a JS module via $implementation for hybrid execution.",
405
- type: "object",
406
- required: ["$prototype", "title"],
407
417
  properties: {
408
- $schema: { type: "string" },
418
+ $defs: {
419
+ description: "Class members: parameters, returnTypes, fields, constructor, methods.",
420
+ properties: {
421
+ constructor: { $ref: "#/$defs/ClassConstructorDef" },
422
+ fields: {
423
+ additionalProperties: { $ref: "#/$defs/ClassFieldDef" },
424
+ description: "Class fields with role, access, scope, and type information.",
425
+ type: "object",
426
+ },
427
+ methods: {
428
+ additionalProperties: { $ref: "#/$defs/ClassMethodDef" },
429
+ description: "Class methods and accessors.",
430
+ type: "object",
431
+ },
432
+ parameters: {
433
+ additionalProperties: { $ref: "#/$defs/ClassParameterDef" },
434
+ description: "Reusable typed parameter schemas, keyed by name.",
435
+ type: "object",
436
+ },
437
+ returnTypes: {
438
+ additionalProperties: { type: "object" },
439
+ description: "Output type schemas, keyed by name.",
440
+ type: "object",
441
+ },
442
+ },
443
+ type: "object",
444
+ },
409
445
  $id: { type: "string" },
410
- $prototype: {
411
- description: 'Must be "Class" for class definition files.',
446
+ $implementation: {
447
+ description: "Relative path to a JS module containing the actual class implementation.",
448
+ examples: ["./md.js", "./lib/calculator.js"],
412
449
  type: "string",
413
- const: "Class",
414
450
  },
415
- title: {
416
- description: "PascalCase class name, used as the export name.",
451
+ $prototype: {
452
+ const: "Class",
453
+ description: 'Must be "Class" for class definition files.',
417
454
  type: "string",
418
- examples: ["MarkdownFile", "DataSource", "Calculator"],
419
455
  },
456
+ $schema: { type: "string" },
457
+ $studio: { $ref: "#/$defs/StudioHints" },
420
458
  description: { type: "string" },
421
459
  extends: {
422
460
  description: "Base class — string name or $ref to another .class.json.",
423
461
  oneOf: [
424
462
  { type: "string" },
425
463
  {
426
- type: "object",
427
- required: ["$ref"],
428
- properties: { $ref: { type: "string" } },
429
464
  additionalProperties: false,
465
+ properties: { $ref: { type: "string" } },
466
+ required: ["$ref"],
467
+ type: "object",
430
468
  },
431
469
  ],
432
470
  },
433
- $implementation: {
434
- description: "Relative path to a JS module containing the actual class implementation.",
435
- type: "string",
436
- examples: ["./md.js", "./lib/calculator.js"],
437
- },
438
471
  format: { $ref: "#/$defs/FormatDef" },
439
- $studio: { $ref: "#/$defs/StudioHints" },
440
- $defs: {
441
- description: "Class members: parameters, returnTypes, fields, constructor, methods.",
442
- type: "object",
443
- properties: {
444
- parameters: {
445
- description: "Reusable typed parameter schemas, keyed by name.",
446
- type: "object",
447
- additionalProperties: { $ref: "#/$defs/ClassParameterDef" },
448
- },
449
- returnTypes: {
450
- description: "Output type schemas, keyed by name.",
451
- type: "object",
452
- additionalProperties: { type: "object" },
453
- },
454
- fields: {
455
- description: "Class fields with role, access, scope, and type information.",
456
- type: "object",
457
- additionalProperties: { $ref: "#/$defs/ClassFieldDef" },
458
- },
459
- constructor: { $ref: "#/$defs/ClassConstructorDef" },
460
- methods: {
461
- description: "Class methods and accessors.",
462
- type: "object",
463
- additionalProperties: { $ref: "#/$defs/ClassMethodDef" },
464
- },
465
- },
472
+ title: {
473
+ description: "PascalCase class name, used as the export name.",
474
+ examples: ["MarkdownFile", "DataSource", "Calculator"],
475
+ type: "string",
466
476
  },
467
477
  },
468
- additionalProperties: false,
469
- $defs: {
470
- ClassParameterDef: classParameterDefSchema,
471
- ClassFieldDef: classFieldDefSchema,
472
- ClassConstructorDef: classConstructorDefSchema,
473
- ClassMethodDef: classMethodDefSchema,
474
- FormatDef: formatDefSchema,
475
- StudioHints: studioHintsSchema,
476
- },
478
+ required: ["$prototype", "title"],
479
+ title: "Jx Class Definition",
480
+ type: "object",
477
481
  };
478
482
  }
479
483
 
@@ -486,22 +490,22 @@ export async function generateSchemaString() {
486
490
  export async function validateDocument(doc: Record<string, unknown>) {
487
491
  let Ajv, addFormats;
488
492
  try {
489
- // @ts-ignore — optional peer dependency
493
+ // @ts-expect-error — optional peer dependency
490
494
  ({ default: Ajv } = await import("ajv"));
491
- // @ts-ignore — optional peer dependency
495
+ // @ts-expect-error — optional peer dependency
492
496
  ({ default: addFormats } = await import("ajv-formats"));
493
497
  } catch {
494
498
  throw new Error("Schema validation requires ajv and ajv-formats: bun add ajv ajv-formats");
495
499
  }
496
500
 
497
- const ajv = new Ajv({ allErrors: true, strict: false, ownProperties: true });
501
+ const ajv = new Ajv({ allErrors: true, ownProperties: true, strict: false });
498
502
  addFormats(ajv);
499
503
 
500
504
  const schema = await generateSchema();
501
505
  const validate = ajv.compile(schema);
502
506
  const valid = validate(doc);
503
507
 
504
- return { valid, errors: validate.errors ?? null };
508
+ return { errors: validate.errors ?? null, valid };
505
509
  }
506
510
 
507
511
  // ─── CLI ──────────────────────────────────────────────────────────────────────
@@ -520,7 +524,7 @@ if (process.argv[1] && process.argv[1].endsWith("schema.ts")) {
520
524
  const projectStr = JSON.stringify(projectSchema, null, 2);
521
525
  const classStr = JSON.stringify(classSchema, null, 2);
522
526
 
523
- const [, , out] = process.argv;
527
+ const [out] = process.argv.slice(2);
524
528
 
525
529
  if (out) {
526
530
  writeFileSync(out, componentStr, "utf8");