@jxsuite/schema 0.28.2 → 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/class-schema.json +341 -341
- package/defs/cem.schema.ts +11 -11
- package/defs/children-value.schema.ts +6 -6
- package/defs/class-def.schema.ts +131 -131
- package/defs/content-type-def.schema.ts +18 -18
- package/defs/element-def.schema.ts +36 -36
- package/defs/expression-node.schema.ts +37 -37
- package/defs/external-class-def.schema.ts +41 -41
- package/defs/function-def.schema.ts +31 -31
- package/defs/head-entry.schema.ts +6 -6
- package/defs/image-config.schema.ts +16 -16
- package/defs/json-schema-type.schema.ts +1 -1
- package/defs/project-config.schema.ts +122 -122
- package/defs/pure-type-def.schema.ts +12 -12
- package/defs/ref-object.schema.ts +19 -19
- package/defs/state-entry.schema.ts +3 -3
- package/defs/style-object.schema.ts +7 -7
- package/defs/tag-name.schema.ts +1 -1
- package/defs/typed-state-def.schema.ts +14 -14
- package/package.json +3 -1
- package/project-schema.json +284 -284
- package/schema.json +987 -987
- package/src/format-registry.ts +28 -13
- package/src/guards.ts +195 -0
- package/src/parse.ts +57 -0
- package/src/schema.ts +229 -225
- package/types.ts +340 -51
package/src/schema.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
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 {
|
|
36
|
+
import { cemEventSchema, cemParameterSchema } from "../defs/cem.schema";
|
|
37
37
|
import { jsonSchemaTypeSchema } from "../defs/json-schema-type.schema";
|
|
38
38
|
import {
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
anyRefSchema,
|
|
40
|
+
externalComponentRefSchema,
|
|
41
41
|
externalRefSchema,
|
|
42
42
|
globalRefSchema,
|
|
43
|
-
|
|
43
|
+
internalRefSchema,
|
|
44
44
|
mapRefSchema,
|
|
45
|
-
|
|
45
|
+
parentRefSchema,
|
|
46
46
|
refObjectSchema,
|
|
47
|
-
|
|
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
|
-
|
|
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
|
-
|
|
64
|
+
assignmentOperatorSchema,
|
|
65
|
+
binaryOperatorSchema,
|
|
66
|
+
expressionEntrySchema,
|
|
65
67
|
expressionLiteralSchema,
|
|
66
|
-
expressionOperandSchema,
|
|
67
68
|
expressionNodeSchema,
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
assignmentOperatorSchema,
|
|
69
|
+
expressionOperandSchema,
|
|
70
|
+
expressionPointerSchema,
|
|
71
|
+
mapFilterMethodSchema,
|
|
72
72
|
noArgMethodSchema,
|
|
73
73
|
oneArgMethodSchema,
|
|
74
|
-
spliceMethodSchema,
|
|
75
74
|
reduceMethodSchema,
|
|
76
|
-
|
|
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)
|
|
109
|
+
if (!el.obsolete) {
|
|
110
|
+
tagSet.add(el.name);
|
|
111
|
+
}
|
|
110
112
|
}
|
|
111
113
|
}
|
|
112
|
-
const tagExamples = [...tagSet].
|
|
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].
|
|
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")
|
|
126
|
-
|
|
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].
|
|
145
|
+
const eventHandlers = [...handlerSet].toSorted();
|
|
140
146
|
|
|
141
|
-
return {
|
|
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,
|
|
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,
|
|
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
|
-
$
|
|
380
|
+
$defs: {
|
|
381
|
+
ContentTypeDef: contentTypeDefSchema,
|
|
382
|
+
ImageConfig: imageConfigSchema,
|
|
383
|
+
},
|
|
377
384
|
$id: "https://jxsuite.com/schema/project/v1",
|
|
378
|
-
|
|
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
|
-
|
|
387
|
-
|
|
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
|
-
$
|
|
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
|
-
|
|
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
|
-
$
|
|
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
|
-
$
|
|
411
|
-
description:
|
|
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
|
-
|
|
416
|
-
|
|
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
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
type: "
|
|
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
|
-
|
|
469
|
-
|
|
470
|
-
|
|
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-
|
|
493
|
+
// @ts-expect-error — optional peer dependency
|
|
490
494
|
({ default: Ajv } = await import("ajv"));
|
|
491
|
-
// @ts-
|
|
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,
|
|
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 {
|
|
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 [
|
|
527
|
+
const [out] = process.argv.slice(2);
|
|
524
528
|
|
|
525
529
|
if (out) {
|
|
526
530
|
writeFileSync(out, componentStr, "utf8");
|