@formspec/build 0.1.0-alpha.57 → 0.1.0-alpha.59

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.js CHANGED
@@ -884,7 +884,7 @@ function generateJsonSchemaFromIR(ir, options) {
884
884
  applyConstraints(ctx.defs[schemaName], typeDef.constraints, ctx);
885
885
  }
886
886
  if (typeDef.annotations && typeDef.annotations.length > 0) {
887
- applyAnnotations(ctx.defs[schemaName], typeDef.annotations, ctx);
887
+ applyAnnotations(ctx.defs[schemaName], typeDef.annotations, ctx, typeDef.type);
888
888
  }
889
889
  }
890
890
  const properties = {};
@@ -957,7 +957,7 @@ function generateFieldSchema(field, ctx) {
957
957
  }
958
958
  }
959
959
  applyResolvedMetadata(schema, field.metadata);
960
- applyAnnotations(schema, rootAnnotations, ctx);
960
+ applyAnnotations(schema, rootAnnotations, ctx, field.type);
961
961
  if (itemStringSchema !== void 0) {
962
962
  applyAnnotations(itemStringSchema, itemAnnotations, ctx);
963
963
  }
@@ -1000,32 +1000,36 @@ function applyPathTargetedConstraints(schema, pathConstraints, ctx, typeNode) {
1000
1000
  return schema;
1001
1001
  }
1002
1002
  if (schema.$ref) {
1003
- const { $ref, ...rest } = schema;
1004
- const refPart = { $ref };
1005
- const overridePart = {
1006
- properties: propertyOverrides,
1007
- ...rest
1003
+ return {
1004
+ ...schema,
1005
+ properties: propertyOverrides
1008
1006
  };
1009
- return { allOf: [refPart, overridePart] };
1010
1007
  }
1011
1008
  if (schema.type === "object" && schema.properties) {
1012
- const missingOverrides = {};
1013
1009
  for (const [target, overrideSchema] of Object.entries(propertyOverrides)) {
1014
- if (schema.properties[target]) {
1015
- mergeSchemaOverride(schema.properties[target], overrideSchema);
1016
- } else {
1017
- missingOverrides[target] = overrideSchema;
1010
+ if (Object.hasOwn(schema.properties, target)) {
1011
+ const existing = schema.properties[target];
1012
+ if (existing) {
1013
+ mergeSchemaOverride(existing, overrideSchema);
1014
+ continue;
1015
+ }
1018
1016
  }
1017
+ Object.defineProperty(schema.properties, target, {
1018
+ value: overrideSchema,
1019
+ writable: true,
1020
+ enumerable: true,
1021
+ configurable: true
1022
+ });
1019
1023
  }
1020
- if (Object.keys(missingOverrides).length === 0) {
1021
- return schema;
1022
- }
1023
- return {
1024
- allOf: [schema, { properties: missingOverrides }]
1025
- };
1024
+ return schema;
1026
1025
  }
1027
1026
  if (schema.allOf) {
1028
- schema.allOf = [...schema.allOf, { properties: propertyOverrides }];
1027
+ const overrideMember = { properties: propertyOverrides };
1028
+ const flattened = tryFlattenAllOfToSiblings(schema, overrideMember);
1029
+ if (flattened !== void 0) {
1030
+ return flattened;
1031
+ }
1032
+ schema.allOf = [...schema.allOf, overrideMember];
1029
1033
  return schema;
1030
1034
  }
1031
1035
  return schema;
@@ -1138,7 +1142,7 @@ function generatePropertySchema(prop, ctx) {
1138
1142
  const schema = generateTypeNode(prop.type, ctx);
1139
1143
  applyConstraints(schema, prop.constraints, ctx);
1140
1144
  applyResolvedMetadata(schema, prop.metadata);
1141
- applyAnnotations(schema, prop.annotations, ctx);
1145
+ applyAnnotations(schema, prop.annotations, ctx, prop.type);
1142
1146
  return schema;
1143
1147
  }
1144
1148
  function generateUnionType(type, ctx) {
@@ -1241,13 +1245,20 @@ function buildPropertyOverrides(pathConstraints, typeNode, ctx) {
1241
1245
  grouped.push(constraint);
1242
1246
  byTarget.set(target, grouped);
1243
1247
  }
1244
- const overrides = {};
1248
+ const overrides = /* @__PURE__ */ Object.create(null);
1245
1249
  for (const [target, constraints] of byTarget) {
1246
- overrides[resolveSerializedPropertyName(target, typeNode, ctx)] = buildPathOverrideSchema(
1250
+ const resolvedName = resolveSerializedPropertyName(target, typeNode, ctx);
1251
+ const schema = buildPathOverrideSchema(
1247
1252
  constraints.map(stripLeadingPathSegment),
1248
1253
  resolveTargetTypeNode(target, typeNode, ctx),
1249
1254
  ctx
1250
1255
  );
1256
+ Object.defineProperty(overrides, resolvedName, {
1257
+ value: schema,
1258
+ writable: true,
1259
+ enumerable: true,
1260
+ configurable: true
1261
+ });
1251
1262
  }
1252
1263
  return overrides;
1253
1264
  }
@@ -1274,6 +1285,34 @@ function buildPathOverrideSchema(constraints, typeNode, ctx) {
1274
1285
  schema.properties = buildPropertyOverrides(nestedConstraints, effectiveType, ctx);
1275
1286
  return schema;
1276
1287
  }
1288
+ function tryFlattenAllOfToSiblings(schema, overrideMember) {
1289
+ if (schema.allOf?.length !== 1) {
1290
+ return void 0;
1291
+ }
1292
+ const [soleMember] = schema.allOf;
1293
+ if (soleMember === void 0) {
1294
+ return void 0;
1295
+ }
1296
+ const { allOf: _allOf, ...outerRest } = schema;
1297
+ const outerKeys = new Set(Object.keys(outerRest));
1298
+ const memberKeys = new Set(Object.keys(soleMember));
1299
+ const overrideKeys = new Set(Object.keys(overrideMember));
1300
+ for (const key of memberKeys) {
1301
+ if (outerKeys.has(key) || overrideKeys.has(key)) {
1302
+ return void 0;
1303
+ }
1304
+ }
1305
+ for (const key of overrideKeys) {
1306
+ if (outerKeys.has(key)) {
1307
+ return void 0;
1308
+ }
1309
+ }
1310
+ return {
1311
+ ...outerRest,
1312
+ ...soleMember,
1313
+ ...overrideMember
1314
+ };
1315
+ }
1277
1316
  function mergeSchemaOverride(target, override) {
1278
1317
  const nullableValueBranch = getNullableUnionValueSchema(target);
1279
1318
  if (nullableValueBranch !== void 0) {
@@ -1281,11 +1320,16 @@ function mergeSchemaOverride(target, override) {
1281
1320
  return;
1282
1321
  }
1283
1322
  if (override.properties !== void 0) {
1284
- const mergedProperties = target.properties ?? {};
1323
+ const mergedProperties = target.properties ?? /* @__PURE__ */ Object.create(null);
1285
1324
  for (const [name, propertyOverride] of Object.entries(override.properties)) {
1286
- const existing = mergedProperties[name];
1325
+ const existing = Object.hasOwn(mergedProperties, name) ? mergedProperties[name] : void 0;
1287
1326
  if (existing === void 0) {
1288
- mergedProperties[name] = propertyOverride;
1327
+ Object.defineProperty(mergedProperties, name, {
1328
+ value: propertyOverride,
1329
+ writable: true,
1330
+ enumerable: true,
1331
+ configurable: true
1332
+ });
1289
1333
  } else {
1290
1334
  mergeSchemaOverride(existing, propertyOverride);
1291
1335
  }
@@ -1303,7 +1347,12 @@ function mergeSchemaOverride(target, override) {
1303
1347
  if (key === "properties" || key === "items") {
1304
1348
  continue;
1305
1349
  }
1306
- target[key] = value;
1350
+ Object.defineProperty(target, key, {
1351
+ value,
1352
+ writable: true,
1353
+ enumerable: true,
1354
+ configurable: true
1355
+ });
1307
1356
  }
1308
1357
  }
1309
1358
  function stripLeadingPathSegment(constraint) {
@@ -1403,7 +1452,7 @@ function applyConstraints(schema, constraints, ctx) {
1403
1452
  }
1404
1453
  }
1405
1454
  }
1406
- function applyAnnotations(schema, annotations, ctx) {
1455
+ function applyAnnotations(schema, annotations, ctx, typeNode) {
1407
1456
  for (const annotation of annotations) {
1408
1457
  switch (annotation.annotationKind) {
1409
1458
  case "displayName":
@@ -1416,7 +1465,7 @@ function applyAnnotations(schema, annotations, ctx) {
1416
1465
  schema[`${ctx.vendorPrefix}-remarks`] = annotation.value;
1417
1466
  break;
1418
1467
  case "defaultValue":
1419
- schema.default = annotation.value;
1468
+ schema.default = coerceDefaultValue(annotation.value, typeNode, schema, ctx);
1420
1469
  break;
1421
1470
  case "format":
1422
1471
  schema.format = annotation.value;
@@ -1441,6 +1490,34 @@ function applyAnnotations(schema, annotations, ctx) {
1441
1490
  }
1442
1491
  }
1443
1492
  }
1493
+ function coerceDefaultValue(value, typeNode, emittedSchema, ctx) {
1494
+ if (typeNode?.kind !== "custom") {
1495
+ return value;
1496
+ }
1497
+ const registration = ctx.extensionRegistry?.findType(typeNode.typeId);
1498
+ if (registration === void 0) {
1499
+ return value;
1500
+ }
1501
+ if (registration.serializeDefault !== void 0) {
1502
+ return registration.serializeDefault(value, typeNode.payload);
1503
+ }
1504
+ const declaredType = emittedSchema["type"];
1505
+ if (declaredType === "string" && typeof value !== "string") {
1506
+ if (typeof value === "number") {
1507
+ if (!Number.isFinite(value)) {
1508
+ return value;
1509
+ }
1510
+ return String(value);
1511
+ }
1512
+ if (typeof value === "boolean") {
1513
+ return String(value);
1514
+ }
1515
+ if (typeof value === "bigint") {
1516
+ return value.toString();
1517
+ }
1518
+ }
1519
+ return value;
1520
+ }
1444
1521
  function generateCustomType(type, ctx) {
1445
1522
  const registration = ctx.extensionRegistry?.findType(type.typeId);
1446
1523
  if (registration === void 0) {
@@ -1871,7 +1948,9 @@ import {
1871
1948
  import {
1872
1949
  getTagDefinition,
1873
1950
  normalizeFormSpecTagName,
1874
- getSyntheticLogger
1951
+ getSyntheticLogger,
1952
+ _validateExtensionSetup,
1953
+ logSetupDiagnostics
1875
1954
  } from "@formspec/analysis/internal";
1876
1955
  var BUILTIN_METADATA_TAGS = /* @__PURE__ */ new Set(["apiName", "displayName"]);
1877
1956
  function buildConstraintTagSources(extensions) {
@@ -1881,6 +1960,16 @@ function buildConstraintTagSources(extensions) {
1881
1960
  constraintTags: extension.constraintTags.map((tag) => ({
1882
1961
  tagName: normalizeFormSpecTagName(tag.tagName)
1883
1962
  }))
1963
+ } : {},
1964
+ // Include customTypes so _validateExtensionSetup can check tsTypeNames for
1965
+ // unsupported built-in overrides and invalid identifier patterns.
1966
+ ...extension.types !== void 0 ? {
1967
+ customTypes: extension.types.map((type) => ({
1968
+ // tsTypeNames: deprecated in favour of symbol-based detection, but
1969
+ // still required for name-based validation in _validateExtensionSetup
1970
+ // until the bridge is fully retired (see §synthetic-checker-retirement §4C).
1971
+ tsTypeNames: type.tsTypeNames ?? [type.typeName]
1972
+ }))
1884
1973
  } : {}
1885
1974
  }));
1886
1975
  }
@@ -1890,7 +1979,13 @@ function createExtensionRegistry(extensions) {
1890
1979
  extensionCount: extensions.length,
1891
1980
  extensionIds: extensions.map((e) => e.extensionId)
1892
1981
  });
1893
- const reservedTagSources = buildConstraintTagSources(extensions);
1982
+ const extensionTagSources = buildConstraintTagSources(extensions);
1983
+ const setupDiagnostics = _validateExtensionSetup(extensionTagSources);
1984
+ logSetupDiagnostics(registryLog, {
1985
+ diagnosticCount: setupDiagnostics.length,
1986
+ codes: setupDiagnostics.map((d) => d.kind)
1987
+ });
1988
+ const reservedTagSources = extensionTagSources;
1894
1989
  let symbolMap = /* @__PURE__ */ new Map();
1895
1990
  const typeMap = /* @__PURE__ */ new Map();
1896
1991
  const typeNameMap = /* @__PURE__ */ new Map();
@@ -2027,10 +2122,12 @@ function createExtensionRegistry(extensions) {
2027
2122
  constraintTagCount: constraintTagMap.size,
2028
2123
  broadeningCount: builtinBroadeningMap.size,
2029
2124
  annotationCount: annotationMap.size,
2030
- metadataSlotCount: metadataSlotMap.size
2125
+ metadataSlotCount: metadataSlotMap.size,
2126
+ setupDiagnosticCount: setupDiagnostics.length
2031
2127
  });
2032
2128
  return {
2033
2129
  extensions,
2130
+ setupDiagnostics,
2034
2131
  findType: (typeId) => typeMap.get(typeId),
2035
2132
  findTypeByName: (typeName) => typeNameMap.get(typeName),
2036
2133
  findTypeByBrand: (brand) => brandMap.get(brand),