@formspec/build 0.1.0-alpha.44 → 0.1.0-alpha.45

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.
Files changed (44) hide show
  1. package/dist/analyzer/class-analyzer.d.ts.map +1 -1
  2. package/dist/analyzer/program.d.ts +4 -1
  3. package/dist/analyzer/program.d.ts.map +1 -1
  4. package/dist/analyzer/tsdoc-parser.d.ts.map +1 -1
  5. package/dist/browser.cjs +33 -7
  6. package/dist/browser.cjs.map +1 -1
  7. package/dist/browser.js +34 -10
  8. package/dist/browser.js.map +1 -1
  9. package/dist/build-alpha.d.ts +106 -5
  10. package/dist/build-beta.d.ts +106 -5
  11. package/dist/build-internal.d.ts +106 -5
  12. package/dist/build.d.ts +106 -5
  13. package/dist/cli.cjs +324 -71
  14. package/dist/cli.cjs.map +1 -1
  15. package/dist/cli.js +320 -70
  16. package/dist/cli.js.map +1 -1
  17. package/dist/extensions/index.d.ts +1 -1
  18. package/dist/extensions/index.d.ts.map +1 -1
  19. package/dist/extensions/registry.d.ts +64 -5
  20. package/dist/extensions/registry.d.ts.map +1 -1
  21. package/dist/extensions/symbol-registry.d.ts +33 -0
  22. package/dist/extensions/symbol-registry.d.ts.map +1 -0
  23. package/dist/generators/class-schema.d.ts +16 -0
  24. package/dist/generators/class-schema.d.ts.map +1 -1
  25. package/dist/generators/discovered-schema.d.ts.map +1 -1
  26. package/dist/index.cjs +310 -64
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.ts +1 -1
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +311 -67
  31. package/dist/index.js.map +1 -1
  32. package/dist/internals.cjs +106 -23
  33. package/dist/internals.cjs.map +1 -1
  34. package/dist/internals.d.ts +1 -1
  35. package/dist/internals.d.ts.map +1 -1
  36. package/dist/internals.js +107 -26
  37. package/dist/internals.js.map +1 -1
  38. package/dist/json-schema/generator.d.ts.map +1 -1
  39. package/dist/metadata/collision-guards.d.ts.map +1 -1
  40. package/dist/metadata/policy.d.ts.map +1 -1
  41. package/dist/metadata/resolve.d.ts.map +1 -1
  42. package/dist/ui-schema/ir-generator.d.ts.map +1 -1
  43. package/dist/validate/constraint-validator.d.ts.map +1 -1
  44. package/package.json +5 -5
@@ -275,7 +275,9 @@ function resolveTypeNodeMetadata(type, options) {
275
275
  case "object":
276
276
  return {
277
277
  ...type,
278
- properties: type.properties.map((property) => resolveObjectPropertyMetadata(property, options))
278
+ properties: type.properties.map(
279
+ (property) => resolveObjectPropertyMetadata(property, options)
280
+ )
279
281
  };
280
282
  case "record":
281
283
  return {
@@ -1632,30 +1634,70 @@ function isObjectType(type) {
1632
1634
  function isIntersectionType(type) {
1633
1635
  return !!(type.flags & ts3.TypeFlags.Intersection);
1634
1636
  }
1637
+ function collectBrandIdentifiers(type) {
1638
+ if (!type.isIntersection()) {
1639
+ return [];
1640
+ }
1641
+ const brands = [];
1642
+ for (const prop of type.getProperties()) {
1643
+ const decl = prop.valueDeclaration ?? prop.declarations?.[0];
1644
+ if (decl === void 0) continue;
1645
+ if (!ts3.isPropertySignature(decl) && !ts3.isPropertyDeclaration(decl)) continue;
1646
+ if (!ts3.isComputedPropertyName(decl.name)) continue;
1647
+ if (!ts3.isIdentifier(decl.name.expression)) continue;
1648
+ brands.push(decl.name.expression.text);
1649
+ }
1650
+ return brands;
1651
+ }
1652
+ function resolveCanonicalSymbol(type, checker) {
1653
+ const raw = type.aliasSymbol ?? type.getSymbol();
1654
+ if (raw === void 0) return void 0;
1655
+ return raw.flags & ts3.SymbolFlags.Alias ? checker.getAliasedSymbol(raw) : raw;
1656
+ }
1657
+ function resolveSymbolBasedCustomType(type, extensionRegistry, checker) {
1658
+ if (extensionRegistry === void 0) {
1659
+ return null;
1660
+ }
1661
+ const canonical = resolveCanonicalSymbol(type, checker);
1662
+ if (canonical === void 0) {
1663
+ return null;
1664
+ }
1665
+ const registration = extensionRegistry.findTypeBySymbol(canonical);
1666
+ if (registration === void 0) {
1667
+ return null;
1668
+ }
1669
+ return {
1670
+ kind: "custom",
1671
+ typeId: `${registration.extensionId}/${registration.registration.typeName}`,
1672
+ payload: null
1673
+ };
1674
+ }
1635
1675
  function isIntegerBrandedType(type) {
1636
1676
  if (!type.isIntersection()) {
1637
1677
  return false;
1638
1678
  }
1639
- const hasNumberBase = type.types.some(
1640
- (member) => !!(member.flags & ts3.TypeFlags.Number)
1641
- );
1679
+ const hasNumberBase = type.types.some((member) => !!(member.flags & ts3.TypeFlags.Number));
1642
1680
  if (!hasNumberBase) {
1643
1681
  return false;
1644
1682
  }
1645
- return type.getProperties().some((prop) => {
1646
- const declaration = prop.valueDeclaration ?? prop.declarations?.[0];
1647
- if (declaration === void 0) {
1648
- return false;
1649
- }
1650
- if (!ts3.isPropertySignature(declaration) && !ts3.isPropertyDeclaration(declaration)) {
1651
- return false;
1652
- }
1653
- const name = declaration.name;
1654
- if (!ts3.isComputedPropertyName(name)) {
1655
- return false;
1683
+ return collectBrandIdentifiers(type).includes("__integerBrand");
1684
+ }
1685
+ function resolveBrandedCustomType(type, extensionRegistry) {
1686
+ if (extensionRegistry === void 0) {
1687
+ return null;
1688
+ }
1689
+ for (const brand of collectBrandIdentifiers(type)) {
1690
+ const registration = extensionRegistry.findTypeByBrand(brand);
1691
+ if (registration === void 0) {
1692
+ continue;
1656
1693
  }
1657
- return ts3.isIdentifier(name.expression) && name.expression.text === "__integerBrand";
1658
- });
1694
+ return {
1695
+ kind: "custom",
1696
+ typeId: `${registration.extensionId}/${registration.registration.typeName}`,
1697
+ payload: null
1698
+ };
1699
+ }
1700
+ return null;
1659
1701
  }
1660
1702
  function isResolvableObjectLikeAliasTypeNode(typeNode) {
1661
1703
  if (ts3.isParenthesizedTypeNode(typeNode)) {
@@ -2768,6 +2810,14 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
2768
2810
  if (customType) {
2769
2811
  return customType;
2770
2812
  }
2813
+ const symbolCustomType = resolveSymbolBasedCustomType(type, extensionRegistry, checker);
2814
+ if (symbolCustomType) {
2815
+ return symbolCustomType;
2816
+ }
2817
+ const brandedCustomType = resolveBrandedCustomType(type, extensionRegistry);
2818
+ if (brandedCustomType) {
2819
+ return brandedCustomType;
2820
+ }
2771
2821
  const primitiveAlias = tryResolveNamedPrimitiveAlias(
2772
2822
  type,
2773
2823
  checker,
@@ -3712,7 +3762,7 @@ function createProgramContextFromProgram(program, filePath) {
3712
3762
  sourceFile
3713
3763
  };
3714
3764
  }
3715
- function createProgramContext(filePath) {
3765
+ function createProgramContext(filePath, additionalFiles) {
3716
3766
  const absolutePath = path.resolve(filePath);
3717
3767
  const fileDir = path.dirname(absolutePath);
3718
3768
  const configPath = ts4.findConfigFile(fileDir, ts4.sys.fileExists.bind(ts4.sys), "tsconfig.json");
@@ -3735,7 +3785,8 @@ function createProgramContext(filePath) {
3735
3785
  throw new Error(`Error parsing tsconfig.json: ${errorMessages}`);
3736
3786
  }
3737
3787
  compilerOptions = parsed.options;
3738
- fileNames = parsed.fileNames.includes(absolutePath) ? parsed.fileNames : [...parsed.fileNames, absolutePath];
3788
+ const normalizedAdditional = (additionalFiles ?? []).map((f) => path.resolve(f));
3789
+ fileNames = [.../* @__PURE__ */ new Set([...parsed.fileNames, absolutePath, ...normalizedAdditional])];
3739
3790
  } else {
3740
3791
  compilerOptions = {
3741
3792
  target: ts4.ScriptTarget.ES2022,
@@ -3745,7 +3796,8 @@ function createProgramContext(filePath) {
3745
3796
  skipLibCheck: true,
3746
3797
  declaration: true
3747
3798
  };
3748
- fileNames = [absolutePath];
3799
+ const normalizedAdditional = (additionalFiles ?? []).map((f) => path.resolve(f));
3800
+ fileNames = [.../* @__PURE__ */ new Set([absolutePath, ...normalizedAdditional])];
3749
3801
  }
3750
3802
  const program = ts4.createProgram(fileNames, compilerOptions);
3751
3803
  const sourceFile = program.getSourceFile(absolutePath);
@@ -4039,7 +4091,7 @@ function makeFileProvenance(filePath) {
4039
4091
  }
4040
4092
 
4041
4093
  // src/generators/class-schema.ts
4042
- var ts5 = __toESM(require("typescript"), 1);
4094
+ var ts6 = __toESM(require("typescript"), 1);
4043
4095
 
4044
4096
  // src/metadata/collision-guards.ts
4045
4097
  function assertUniqueSerializedNames(entries, scope) {
@@ -4886,8 +4938,10 @@ function buildConstraintTagSources(extensions) {
4886
4938
  }
4887
4939
  function createExtensionRegistry(extensions) {
4888
4940
  const reservedTagSources = buildConstraintTagSources(extensions);
4941
+ let symbolMap = /* @__PURE__ */ new Map();
4889
4942
  const typeMap = /* @__PURE__ */ new Map();
4890
4943
  const typeNameMap = /* @__PURE__ */ new Map();
4944
+ const brandMap = /* @__PURE__ */ new Map();
4891
4945
  const constraintMap = /* @__PURE__ */ new Map();
4892
4946
  const constraintTagMap = /* @__PURE__ */ new Map();
4893
4947
  const builtinBroadeningMap = /* @__PURE__ */ new Map();
@@ -4911,6 +4965,20 @@ function createExtensionRegistry(extensions) {
4911
4965
  registration: type
4912
4966
  });
4913
4967
  }
4968
+ if (type.brand !== void 0) {
4969
+ if (type.brand === "__integerBrand") {
4970
+ throw new Error(
4971
+ `Brand "__integerBrand" is reserved for the builtin Integer type and cannot be registered by extensions`
4972
+ );
4973
+ }
4974
+ if (brandMap.has(type.brand)) {
4975
+ throw new Error(`Duplicate custom type brand: "${type.brand}"`);
4976
+ }
4977
+ brandMap.set(type.brand, {
4978
+ extensionId: ext.extensionId,
4979
+ registration: type
4980
+ });
4981
+ }
4914
4982
  if (type.builtinConstraintBroadenings !== void 0) {
4915
4983
  for (const broadening of type.builtinConstraintBroadenings) {
4916
4984
  const key = `${qualifiedId}:${broadening.tagName}`;
@@ -4980,7 +5048,10 @@ function createExtensionRegistry(extensions) {
4980
5048
  `Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${canonicalTagName}".`
4981
5049
  );
4982
5050
  }
4983
- if (Object.hasOwn(import_internals5.BUILTIN_CONSTRAINT_DEFINITIONS, (0, import_internals5.normalizeConstraintTagName)(canonicalTagName))) {
5051
+ if (Object.hasOwn(
5052
+ import_internals5.BUILTIN_CONSTRAINT_DEFINITIONS,
5053
+ (0, import_internals5.normalizeConstraintTagName)(canonicalTagName)
5054
+ )) {
4984
5055
  throw new Error(
4985
5056
  `Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${(0, import_internals5.normalizeConstraintTagName)(canonicalTagName)}".`
4986
5057
  );
@@ -5001,6 +5072,11 @@ function createExtensionRegistry(extensions) {
5001
5072
  extensions,
5002
5073
  findType: (typeId) => typeMap.get(typeId),
5003
5074
  findTypeByName: (typeName) => typeNameMap.get(typeName),
5075
+ findTypeByBrand: (brand) => brandMap.get(brand),
5076
+ findTypeBySymbol: (symbol) => symbolMap.get(symbol),
5077
+ setSymbolMap: (map) => {
5078
+ symbolMap = map;
5079
+ },
5004
5080
  findConstraint: (constraintId) => constraintMap.get(constraintId),
5005
5081
  findConstraintTag: (tagName) => constraintTagMap.get((0, import_internal3.normalizeFormSpecTagName)(tagName)),
5006
5082
  findBuiltinConstraintBroadening: (typeId, tagName) => builtinBroadeningMap.get(`${typeId}:${tagName}`),
@@ -5008,6 +5084,10 @@ function createExtensionRegistry(extensions) {
5008
5084
  };
5009
5085
  }
5010
5086
 
5087
+ // src/extensions/symbol-registry.ts
5088
+ var ts5 = __toESM(require("typescript"), 1);
5089
+ var path2 = __toESM(require("path"), 1);
5090
+
5011
5091
  // src/ui-schema/schema.ts
5012
5092
  var import_zod = require("zod");
5013
5093
  var jsonPointerSchema = import_zod.z.string();
@@ -5216,7 +5296,10 @@ function irElementsToUiSchema(elements, fieldNameMap, parentRule) {
5216
5296
  break;
5217
5297
  }
5218
5298
  case "conditional": {
5219
- const newRule = createShowRule(fieldNameMap.get(element.fieldName) ?? element.fieldName, element.value);
5299
+ const newRule = createShowRule(
5300
+ fieldNameMap.get(element.fieldName) ?? element.fieldName,
5301
+ element.value
5302
+ );
5220
5303
  const combinedRule = parentRule !== void 0 ? combineRules(parentRule, newRule) : newRule;
5221
5304
  const childElements = irElementsToUiSchema(element.elements, fieldNameMap, combinedRule);
5222
5305
  result.push(...childElements);