@formspec/build 0.1.0-alpha.40 → 0.1.0-alpha.41
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/browser.cjs +226 -17
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.js +226 -17
- package/dist/browser.js.map +1 -1
- package/dist/build-alpha.d.ts +10 -0
- package/dist/build-beta.d.ts +10 -0
- package/dist/build-internal.d.ts +10 -0
- package/dist/build.d.ts +10 -0
- package/dist/canonicalize/chain-dsl-canonicalizer.d.ts.map +1 -1
- package/dist/cli.cjs +163 -27
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +163 -27
- package/dist/cli.js.map +1 -1
- package/dist/generators/class-schema.d.ts +5 -0
- package/dist/generators/class-schema.d.ts.map +1 -1
- package/dist/generators/discovered-schema.d.ts.map +1 -1
- package/dist/generators/method-schema.d.ts +9 -2
- package/dist/generators/method-schema.d.ts.map +1 -1
- package/dist/index.cjs +143 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +143 -24
- package/dist/index.js.map +1 -1
- package/dist/internals.cjs +120 -27
- package/dist/internals.cjs.map +1 -1
- package/dist/internals.js +120 -27
- package/dist/internals.js.map +1 -1
- package/dist/json-schema/generator.d.ts +5 -0
- package/dist/json-schema/generator.d.ts.map +1 -1
- package/dist/json-schema/ir-generator.d.ts +5 -0
- package/dist/json-schema/ir-generator.d.ts.map +1 -1
- package/dist/metadata/policy.d.ts +3 -2
- package/dist/metadata/policy.d.ts.map +1 -1
- package/dist/metadata/resolve.d.ts +1 -0
- package/dist/metadata/resolve.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/internals.js
CHANGED
|
@@ -51,11 +51,35 @@ function normalizeDeclarationPolicy(input) {
|
|
|
51
51
|
displayName: normalizeScalarPolicy(input?.displayName)
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
|
+
function normalizeEnumMemberDisplayNamePolicy(input) {
|
|
55
|
+
if (input?.mode === "infer-if-missing") {
|
|
56
|
+
return {
|
|
57
|
+
mode: "infer-if-missing",
|
|
58
|
+
infer: input.infer
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
if (input?.mode === "require-explicit") {
|
|
62
|
+
return {
|
|
63
|
+
mode: "require-explicit",
|
|
64
|
+
infer: () => ""
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
mode: "disabled",
|
|
69
|
+
infer: () => ""
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function normalizeEnumMemberPolicy(input) {
|
|
73
|
+
return {
|
|
74
|
+
displayName: normalizeEnumMemberDisplayNamePolicy(input?.displayName)
|
|
75
|
+
};
|
|
76
|
+
}
|
|
54
77
|
function normalizeMetadataPolicy(input) {
|
|
55
78
|
return {
|
|
56
79
|
type: normalizeDeclarationPolicy(input?.type),
|
|
57
80
|
field: normalizeDeclarationPolicy(input?.field),
|
|
58
|
-
method: normalizeDeclarationPolicy(input?.method)
|
|
81
|
+
method: normalizeDeclarationPolicy(input?.method),
|
|
82
|
+
enumMember: normalizeEnumMemberPolicy(input?.enumMember)
|
|
59
83
|
};
|
|
60
84
|
}
|
|
61
85
|
function getDeclarationMetadataPolicy(policy, declarationKind) {
|
|
@@ -152,6 +176,40 @@ function resolveResolvedMetadata(current, policy, context) {
|
|
|
152
176
|
...displayNamePlural !== void 0 && { displayNamePlural }
|
|
153
177
|
};
|
|
154
178
|
}
|
|
179
|
+
function resolveEnumMemberDisplayName(current, policy, context) {
|
|
180
|
+
if (current !== void 0) {
|
|
181
|
+
return current;
|
|
182
|
+
}
|
|
183
|
+
if (policy.mode === "require-explicit") {
|
|
184
|
+
throw new Error(
|
|
185
|
+
`Metadata policy requires explicit displayName for enum member "${context.logicalName}" on the ${context.surface} surface.`
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
if (policy.mode !== "infer-if-missing") {
|
|
189
|
+
return void 0;
|
|
190
|
+
}
|
|
191
|
+
const inferredValue = policy.infer(context).trim();
|
|
192
|
+
return inferredValue !== "" ? inferredValue : void 0;
|
|
193
|
+
}
|
|
194
|
+
function resolveEnumTypeMetadata(type, options) {
|
|
195
|
+
const members = type.members.map((member) => {
|
|
196
|
+
const displayName = resolveEnumMemberDisplayName(
|
|
197
|
+
member.displayName,
|
|
198
|
+
options.policy.enumMember.displayName,
|
|
199
|
+
{
|
|
200
|
+
surface: options.surface,
|
|
201
|
+
logicalName: String(member.value),
|
|
202
|
+
memberValue: member.value,
|
|
203
|
+
...options.buildContext !== void 0 && { buildContext: options.buildContext }
|
|
204
|
+
}
|
|
205
|
+
);
|
|
206
|
+
if (displayName === member.displayName) {
|
|
207
|
+
return member;
|
|
208
|
+
}
|
|
209
|
+
return displayName === void 0 ? { value: member.value } : { value: member.value, displayName };
|
|
210
|
+
});
|
|
211
|
+
return members.some((member, index) => member !== type.members[index]) ? { ...type, members } : type;
|
|
212
|
+
}
|
|
155
213
|
function resolveTypeNodeMetadata(type, options) {
|
|
156
214
|
switch (type.kind) {
|
|
157
215
|
case "array":
|
|
@@ -174,9 +232,10 @@ function resolveTypeNodeMetadata(type, options) {
|
|
|
174
232
|
...type,
|
|
175
233
|
members: type.members.map((member) => resolveTypeNodeMetadata(member, options))
|
|
176
234
|
};
|
|
235
|
+
case "enum":
|
|
236
|
+
return resolveEnumTypeMetadata(type, options);
|
|
177
237
|
case "reference":
|
|
178
238
|
case "primitive":
|
|
179
|
-
case "enum":
|
|
180
239
|
case "dynamic":
|
|
181
240
|
case "custom":
|
|
182
241
|
return type;
|
|
@@ -255,11 +314,10 @@ function getDisplayName(metadata) {
|
|
|
255
314
|
return metadata?.displayName?.value;
|
|
256
315
|
}
|
|
257
316
|
function resolveFormIRMetadata(ir, options) {
|
|
258
|
-
const
|
|
259
|
-
const metadata = resolveResolvedMetadata(ir.metadata, options.policy.type, {
|
|
317
|
+
const metadata = options.resolveRootTypeMetadata === false ? ir.metadata : resolveResolvedMetadata(ir.metadata, options.policy.type, {
|
|
260
318
|
surface: options.surface,
|
|
261
319
|
declarationKind: "type",
|
|
262
|
-
logicalName: rootLogicalName,
|
|
320
|
+
logicalName: options.rootLogicalName ?? ir.name ?? "FormSpec",
|
|
263
321
|
...options.buildContext !== void 0 && { buildContext: options.buildContext }
|
|
264
322
|
});
|
|
265
323
|
return {
|
|
@@ -295,7 +353,7 @@ function canonicalizeChainDSL(form, options) {
|
|
|
295
353
|
const metadataPolicy = normalizeMetadataPolicy(
|
|
296
354
|
options?.metadata ?? _getFormSpecMetadataPolicy(form)
|
|
297
355
|
);
|
|
298
|
-
|
|
356
|
+
const ir = {
|
|
299
357
|
kind: "form-ir",
|
|
300
358
|
irVersion: IR_VERSION,
|
|
301
359
|
elements: canonicalizeElements(form.elements, metadataPolicy),
|
|
@@ -303,6 +361,13 @@ function canonicalizeChainDSL(form, options) {
|
|
|
303
361
|
typeRegistry: {},
|
|
304
362
|
provenance: CHAIN_DSL_PROVENANCE
|
|
305
363
|
};
|
|
364
|
+
return resolveFormIRMetadata(ir, {
|
|
365
|
+
policy: metadataPolicy,
|
|
366
|
+
surface: "chain-dsl",
|
|
367
|
+
// Chain DSL has no root/type-metadata authoring surface, so only resolve
|
|
368
|
+
// field/type-registry metadata and enum-member labels here.
|
|
369
|
+
resolveRootTypeMetadata: false
|
|
370
|
+
});
|
|
306
371
|
}
|
|
307
372
|
function canonicalizeElements(elements, metadataPolicy) {
|
|
308
373
|
return elements.map((element) => canonicalizeElement(element, metadataPolicy));
|
|
@@ -4171,17 +4236,25 @@ function assertNoSerializedNameCollisions(ir) {
|
|
|
4171
4236
|
// src/json-schema/ir-generator.ts
|
|
4172
4237
|
function makeContext(options) {
|
|
4173
4238
|
const vendorPrefix = options?.vendorPrefix ?? "x-formspec";
|
|
4239
|
+
const rawEnumSerialization = options?.enumSerialization;
|
|
4174
4240
|
if (!vendorPrefix.startsWith("x-")) {
|
|
4175
4241
|
throw new Error(
|
|
4176
4242
|
`Invalid vendorPrefix "${vendorPrefix}". Extension JSON Schema keywords must start with "x-".`
|
|
4177
4243
|
);
|
|
4178
4244
|
}
|
|
4245
|
+
if (rawEnumSerialization !== void 0 && rawEnumSerialization !== "enum" && rawEnumSerialization !== "oneOf") {
|
|
4246
|
+
throw new Error(
|
|
4247
|
+
`Invalid enumSerialization "${rawEnumSerialization}". Expected "enum" or "oneOf".`
|
|
4248
|
+
);
|
|
4249
|
+
}
|
|
4250
|
+
const enumSerialization = rawEnumSerialization ?? "enum";
|
|
4179
4251
|
return {
|
|
4180
4252
|
defs: {},
|
|
4181
4253
|
typeNameMap: {},
|
|
4182
4254
|
typeRegistry: {},
|
|
4183
4255
|
extensionRegistry: options?.extensionRegistry,
|
|
4184
|
-
vendorPrefix
|
|
4256
|
+
vendorPrefix,
|
|
4257
|
+
enumSerialization
|
|
4185
4258
|
};
|
|
4186
4259
|
}
|
|
4187
4260
|
function generateJsonSchemaFromIR(ir, options) {
|
|
@@ -4355,7 +4428,7 @@ function generateTypeNode(type, ctx) {
|
|
|
4355
4428
|
case "primitive":
|
|
4356
4429
|
return generatePrimitiveType(type);
|
|
4357
4430
|
case "enum":
|
|
4358
|
-
return generateEnumType(type);
|
|
4431
|
+
return generateEnumType(type, ctx);
|
|
4359
4432
|
case "array":
|
|
4360
4433
|
return generateArrayType(type, ctx);
|
|
4361
4434
|
case "object":
|
|
@@ -4381,20 +4454,37 @@ function generatePrimitiveType(type) {
|
|
|
4381
4454
|
type: type.primitiveKind === "integer" || type.primitiveKind === "bigint" ? "integer" : type.primitiveKind
|
|
4382
4455
|
};
|
|
4383
4456
|
}
|
|
4384
|
-
function generateEnumType(type) {
|
|
4385
|
-
|
|
4386
|
-
if (hasDisplayNames) {
|
|
4457
|
+
function generateEnumType(type, ctx) {
|
|
4458
|
+
if (ctx.enumSerialization === "oneOf") {
|
|
4387
4459
|
return {
|
|
4388
|
-
oneOf: type.members.map((m) => {
|
|
4389
|
-
const
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
}
|
|
4393
|
-
return entry;
|
|
4394
|
-
})
|
|
4460
|
+
oneOf: type.members.map((m) => ({
|
|
4461
|
+
const: m.value,
|
|
4462
|
+
title: m.displayName ?? String(m.value)
|
|
4463
|
+
}))
|
|
4395
4464
|
};
|
|
4396
4465
|
}
|
|
4397
|
-
|
|
4466
|
+
const schema = { enum: type.members.map((m) => m.value) };
|
|
4467
|
+
const displayNames = buildEnumDisplayNameExtension(type);
|
|
4468
|
+
if (displayNames !== void 0) {
|
|
4469
|
+
schema[`${ctx.vendorPrefix}-display-names`] = displayNames;
|
|
4470
|
+
}
|
|
4471
|
+
return schema;
|
|
4472
|
+
}
|
|
4473
|
+
function buildEnumDisplayNameExtension(type) {
|
|
4474
|
+
if (!type.members.some((member) => member.displayName !== void 0)) {
|
|
4475
|
+
return void 0;
|
|
4476
|
+
}
|
|
4477
|
+
const displayNames = /* @__PURE__ */ Object.create(null);
|
|
4478
|
+
for (const member of type.members) {
|
|
4479
|
+
const key = String(member.value);
|
|
4480
|
+
if (Object.hasOwn(displayNames, key)) {
|
|
4481
|
+
throw new Error(
|
|
4482
|
+
`Enum display-name key "${key}" is ambiguous after stringification. Use oneOf serialization for mixed string/number enum values that collide.`
|
|
4483
|
+
);
|
|
4484
|
+
}
|
|
4485
|
+
displayNames[key] = member.displayName ?? key;
|
|
4486
|
+
}
|
|
4487
|
+
return displayNames;
|
|
4398
4488
|
}
|
|
4399
4489
|
function generateArrayType(type, ctx) {
|
|
4400
4490
|
return {
|
|
@@ -5319,7 +5409,7 @@ function createExtensionRegistry(extensions) {
|
|
|
5319
5409
|
|
|
5320
5410
|
// src/generators/method-schema.ts
|
|
5321
5411
|
import { IR_VERSION as IR_VERSION3 } from "@formspec/core/internals";
|
|
5322
|
-
function typeToJsonSchema(type, checker) {
|
|
5412
|
+
function typeToJsonSchema(type, checker, options) {
|
|
5323
5413
|
const typeRegistry = {};
|
|
5324
5414
|
const visiting = /* @__PURE__ */ new Set();
|
|
5325
5415
|
const diagnostics = [];
|
|
@@ -5359,7 +5449,10 @@ function typeToJsonSchema(type, checker) {
|
|
|
5359
5449
|
typeRegistry,
|
|
5360
5450
|
provenance: fieldProvenance
|
|
5361
5451
|
};
|
|
5362
|
-
const schema = generateJsonSchemaFromIR(
|
|
5452
|
+
const schema = generateJsonSchemaFromIR(
|
|
5453
|
+
ir,
|
|
5454
|
+
options?.enumSerialization === void 0 ? void 0 : { enumSerialization: options.enumSerialization }
|
|
5455
|
+
);
|
|
5363
5456
|
const fieldSchema = schema.properties?.["__result"];
|
|
5364
5457
|
if (fieldSchema) {
|
|
5365
5458
|
if (schema.$defs && Object.keys(schema.$defs).length > 0) {
|
|
@@ -5369,16 +5462,16 @@ function typeToJsonSchema(type, checker) {
|
|
|
5369
5462
|
}
|
|
5370
5463
|
return { type: "object" };
|
|
5371
5464
|
}
|
|
5372
|
-
function generateMethodSchemas(method, checker, loadedFormSpecs) {
|
|
5373
|
-
const returnType = typeToJsonSchema(method.returnType, checker);
|
|
5374
|
-
const params = generateParamsSchemas(method.parameters, checker, loadedFormSpecs);
|
|
5465
|
+
function generateMethodSchemas(method, checker, loadedFormSpecs, options) {
|
|
5466
|
+
const returnType = typeToJsonSchema(method.returnType, checker, options);
|
|
5467
|
+
const params = generateParamsSchemas(method.parameters, checker, loadedFormSpecs, options);
|
|
5375
5468
|
return {
|
|
5376
5469
|
name: method.name,
|
|
5377
5470
|
params,
|
|
5378
5471
|
returnType
|
|
5379
5472
|
};
|
|
5380
5473
|
}
|
|
5381
|
-
function generateParamsSchemas(parameters, checker, loadedFormSpecs) {
|
|
5474
|
+
function generateParamsSchemas(parameters, checker, loadedFormSpecs, options) {
|
|
5382
5475
|
if (parameters.length === 0) {
|
|
5383
5476
|
return null;
|
|
5384
5477
|
}
|
|
@@ -5399,7 +5492,7 @@ function generateParamsSchemas(parameters, checker, loadedFormSpecs) {
|
|
|
5399
5492
|
}
|
|
5400
5493
|
if (parameters.length === 1 && parameters[0]) {
|
|
5401
5494
|
const param = parameters[0];
|
|
5402
|
-
const jsonSchema = typeToJsonSchema(param.type, checker);
|
|
5495
|
+
const jsonSchema = typeToJsonSchema(param.type, checker, options);
|
|
5403
5496
|
return {
|
|
5404
5497
|
jsonSchema,
|
|
5405
5498
|
uiSchema: null,
|
|
@@ -5409,7 +5502,7 @@ function generateParamsSchemas(parameters, checker, loadedFormSpecs) {
|
|
|
5409
5502
|
const properties = {};
|
|
5410
5503
|
const required = [];
|
|
5411
5504
|
for (const param of parameters) {
|
|
5412
|
-
const paramSchema = typeToJsonSchema(param.type, checker);
|
|
5505
|
+
const paramSchema = typeToJsonSchema(param.type, checker, options);
|
|
5413
5506
|
properties[param.name] = paramSchema;
|
|
5414
5507
|
if (!param.optional) {
|
|
5415
5508
|
required.push(param.name);
|