@formspec/build 0.1.0-alpha.43 → 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 +35 -9
  6. package/dist/browser.cjs.map +1 -1
  7. package/dist/browser.js +36 -12
  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 +343 -59
  14. package/dist/cli.cjs.map +1 -1
  15. package/dist/cli.js +339 -58
  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 +328 -51
  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 +329 -54
  31. package/dist/index.js.map +1 -1
  32. package/dist/internals.cjs +124 -10
  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 +125 -13
  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
@@ -26,7 +26,7 @@ export { generateUiSchemaFromIR } from "./ui-schema/ir-generator.js";
26
26
  export { validateIR } from "./validate/index.js";
27
27
  export type { ValidationDiagnostic, ValidationResult, ValidateIROptions, } from "./validate/index.js";
28
28
  export { createExtensionRegistry } from "./extensions/index.js";
29
- export type { ExtensionRegistry } from "./extensions/index.js";
29
+ export type { ExtensionRegistry, ExtensionTypeLookupResult, MutableExtensionRegistry, } from "./extensions/index.js";
30
30
  export { generateMethodSchemas, collectFormSpecReferences } from "./generators/method-schema.js";
31
31
  export type { LoadedFormSpecSchemas, MethodSchemas } from "./generators/method-schema.js";
32
32
  //# sourceMappingURL=internals.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"internals.d.ts","sourceRoot":"","sources":["../src/internals.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAG/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,YAAY,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAG3D,OAAO,EACL,oBAAoB,EACpB,+BAA+B,EAC/B,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,8CAA8C,EAC9C,sCAAsC,GACvC,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,8BAA8B,CAAC;AACtC,YAAY,EACV,8BAA8B,EAC9B,eAAe,EACf,mBAAmB,EACnB,0BAA0B,GAC3B,MAAM,8BAA8B,CAAC;AACtC,YAAY,EAAE,kCAAkC,EAAE,MAAM,uBAAuB,CAAC;AAGhF,OAAO,EAAE,oBAAoB,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AAClG,YAAY,EAAE,YAAY,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAG7F,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,YAAY,EACV,+BAA+B,EAC/B,cAAc,GACf,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAGrE,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,YAAY,EACV,oBAAoB,EACpB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,YAAY,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAG/D,OAAO,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AACjG,YAAY,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC"}
1
+ {"version":3,"file":"internals.d.ts","sourceRoot":"","sources":["../src/internals.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAG/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,YAAY,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAG3D,OAAO,EACL,oBAAoB,EACpB,+BAA+B,EAC/B,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,8CAA8C,EAC9C,sCAAsC,GACvC,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,8BAA8B,CAAC;AACtC,YAAY,EACV,8BAA8B,EAC9B,eAAe,EACf,mBAAmB,EACnB,0BAA0B,GAC3B,MAAM,8BAA8B,CAAC;AACtC,YAAY,EAAE,kCAAkC,EAAE,MAAM,uBAAuB,CAAC;AAGhF,OAAO,EAAE,oBAAoB,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AAClG,YAAY,EAAE,YAAY,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAG7F,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,YAAY,EACV,+BAA+B,EAC/B,cAAc,GACf,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAGrE,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,YAAY,EACV,oBAAoB,EACpB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,YAAY,EACV,iBAAiB,EACjB,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AACjG,YAAY,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC"}
package/dist/internals.js CHANGED
@@ -220,7 +220,9 @@ function resolveTypeNodeMetadata(type, options) {
220
220
  case "object":
221
221
  return {
222
222
  ...type,
223
- properties: type.properties.map((property) => resolveObjectPropertyMetadata(property, options))
223
+ properties: type.properties.map(
224
+ (property) => resolveObjectPropertyMetadata(property, options)
225
+ )
224
226
  };
225
227
  case "record":
226
228
  return {
@@ -1598,6 +1600,71 @@ function isObjectType(type) {
1598
1600
  function isIntersectionType(type) {
1599
1601
  return !!(type.flags & ts3.TypeFlags.Intersection);
1600
1602
  }
1603
+ function collectBrandIdentifiers(type) {
1604
+ if (!type.isIntersection()) {
1605
+ return [];
1606
+ }
1607
+ const brands = [];
1608
+ for (const prop of type.getProperties()) {
1609
+ const decl = prop.valueDeclaration ?? prop.declarations?.[0];
1610
+ if (decl === void 0) continue;
1611
+ if (!ts3.isPropertySignature(decl) && !ts3.isPropertyDeclaration(decl)) continue;
1612
+ if (!ts3.isComputedPropertyName(decl.name)) continue;
1613
+ if (!ts3.isIdentifier(decl.name.expression)) continue;
1614
+ brands.push(decl.name.expression.text);
1615
+ }
1616
+ return brands;
1617
+ }
1618
+ function resolveCanonicalSymbol(type, checker) {
1619
+ const raw = type.aliasSymbol ?? type.getSymbol();
1620
+ if (raw === void 0) return void 0;
1621
+ return raw.flags & ts3.SymbolFlags.Alias ? checker.getAliasedSymbol(raw) : raw;
1622
+ }
1623
+ function resolveSymbolBasedCustomType(type, extensionRegistry, checker) {
1624
+ if (extensionRegistry === void 0) {
1625
+ return null;
1626
+ }
1627
+ const canonical = resolveCanonicalSymbol(type, checker);
1628
+ if (canonical === void 0) {
1629
+ return null;
1630
+ }
1631
+ const registration = extensionRegistry.findTypeBySymbol(canonical);
1632
+ if (registration === void 0) {
1633
+ return null;
1634
+ }
1635
+ return {
1636
+ kind: "custom",
1637
+ typeId: `${registration.extensionId}/${registration.registration.typeName}`,
1638
+ payload: null
1639
+ };
1640
+ }
1641
+ function isIntegerBrandedType(type) {
1642
+ if (!type.isIntersection()) {
1643
+ return false;
1644
+ }
1645
+ const hasNumberBase = type.types.some((member) => !!(member.flags & ts3.TypeFlags.Number));
1646
+ if (!hasNumberBase) {
1647
+ return false;
1648
+ }
1649
+ return collectBrandIdentifiers(type).includes("__integerBrand");
1650
+ }
1651
+ function resolveBrandedCustomType(type, extensionRegistry) {
1652
+ if (extensionRegistry === void 0) {
1653
+ return null;
1654
+ }
1655
+ for (const brand of collectBrandIdentifiers(type)) {
1656
+ const registration = extensionRegistry.findTypeByBrand(brand);
1657
+ if (registration === void 0) {
1658
+ continue;
1659
+ }
1660
+ return {
1661
+ kind: "custom",
1662
+ typeId: `${registration.extensionId}/${registration.registration.typeName}`,
1663
+ payload: null
1664
+ };
1665
+ }
1666
+ return null;
1667
+ }
1601
1668
  function isResolvableObjectLikeAliasTypeNode(typeNode) {
1602
1669
  if (ts3.isParenthesizedTypeNode(typeNode)) {
1603
1670
  return isResolvableObjectLikeAliasTypeNode(typeNode.type);
@@ -2709,6 +2776,14 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
2709
2776
  if (customType) {
2710
2777
  return customType;
2711
2778
  }
2779
+ const symbolCustomType = resolveSymbolBasedCustomType(type, extensionRegistry, checker);
2780
+ if (symbolCustomType) {
2781
+ return symbolCustomType;
2782
+ }
2783
+ const brandedCustomType = resolveBrandedCustomType(type, extensionRegistry);
2784
+ if (brandedCustomType) {
2785
+ return brandedCustomType;
2786
+ }
2712
2787
  const primitiveAlias = tryResolveNamedPrimitiveAlias(
2713
2788
  type,
2714
2789
  checker,
@@ -2723,6 +2798,9 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
2723
2798
  if (primitiveAlias) {
2724
2799
  return primitiveAlias;
2725
2800
  }
2801
+ if (isIntegerBrandedType(type)) {
2802
+ return { kind: "primitive", primitiveKind: "integer" };
2803
+ }
2726
2804
  if (type.flags & ts3.TypeFlags.String) {
2727
2805
  return { kind: "primitive", primitiveKind: "string" };
2728
2806
  }
@@ -2825,7 +2903,7 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
2825
2903
  return { kind: "primitive", primitiveKind: "string" };
2826
2904
  }
2827
2905
  function tryResolveNamedPrimitiveAlias(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
2828
- if (!(type.flags & (ts3.TypeFlags.String | ts3.TypeFlags.Number | ts3.TypeFlags.BigInt | ts3.TypeFlags.BigIntLiteral | ts3.TypeFlags.Boolean | ts3.TypeFlags.Null))) {
2906
+ if (!(type.flags & (ts3.TypeFlags.String | ts3.TypeFlags.Number | ts3.TypeFlags.BigInt | ts3.TypeFlags.BigIntLiteral | ts3.TypeFlags.Boolean | ts3.TypeFlags.Null)) && !isIntegerBrandedType(type)) {
2829
2907
  return null;
2830
2908
  }
2831
2909
  const aliasDecl = type.aliasSymbol?.declarations?.find(ts3.isTypeAliasDeclaration) ?? getReferencedTypeAliasDeclaration(sourceNode, checker);
@@ -2911,6 +2989,9 @@ function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiti
2911
2989
  visitedAliases
2912
2990
  );
2913
2991
  }
2992
+ if (isIntegerBrandedType(type)) {
2993
+ return { kind: "primitive", primitiveKind: "integer" };
2994
+ }
2914
2995
  if (type.flags & ts3.TypeFlags.String) {
2915
2996
  return { kind: "primitive", primitiveKind: "string" };
2916
2997
  }
@@ -3647,7 +3728,7 @@ function createProgramContextFromProgram(program, filePath) {
3647
3728
  sourceFile
3648
3729
  };
3649
3730
  }
3650
- function createProgramContext(filePath) {
3731
+ function createProgramContext(filePath, additionalFiles) {
3651
3732
  const absolutePath = path.resolve(filePath);
3652
3733
  const fileDir = path.dirname(absolutePath);
3653
3734
  const configPath = ts4.findConfigFile(fileDir, ts4.sys.fileExists.bind(ts4.sys), "tsconfig.json");
@@ -3670,7 +3751,8 @@ function createProgramContext(filePath) {
3670
3751
  throw new Error(`Error parsing tsconfig.json: ${errorMessages}`);
3671
3752
  }
3672
3753
  compilerOptions = parsed.options;
3673
- fileNames = parsed.fileNames.includes(absolutePath) ? parsed.fileNames : [...parsed.fileNames, absolutePath];
3754
+ const normalizedAdditional = (additionalFiles ?? []).map((f) => path.resolve(f));
3755
+ fileNames = [.../* @__PURE__ */ new Set([...parsed.fileNames, absolutePath, ...normalizedAdditional])];
3674
3756
  } else {
3675
3757
  compilerOptions = {
3676
3758
  target: ts4.ScriptTarget.ES2022,
@@ -3680,7 +3762,8 @@ function createProgramContext(filePath) {
3680
3762
  skipLibCheck: true,
3681
3763
  declaration: true
3682
3764
  };
3683
- fileNames = [absolutePath];
3765
+ const normalizedAdditional = (additionalFiles ?? []).map((f) => path.resolve(f));
3766
+ fileNames = [.../* @__PURE__ */ new Set([absolutePath, ...normalizedAdditional])];
3684
3767
  }
3685
3768
  const program = ts4.createProgram(fileNames, compilerOptions);
3686
3769
  const sourceFile = program.getSourceFile(absolutePath);
@@ -3974,7 +4057,7 @@ function makeFileProvenance(filePath) {
3974
4057
  }
3975
4058
 
3976
4059
  // src/generators/class-schema.ts
3977
- import * as ts5 from "typescript";
4060
+ import * as ts6 from "typescript";
3978
4061
 
3979
4062
  // src/metadata/collision-guards.ts
3980
4063
  function assertUniqueSerializedNames(entries, scope) {
@@ -4690,7 +4773,7 @@ function generateCustomType(type, ctx) {
4690
4773
  }
4691
4774
  return registration.toJsonSchema(type.payload, ctx.vendorPrefix);
4692
4775
  }
4693
- var JSON_SCHEMA_STRUCTURAL_KEYWORDS = /* @__PURE__ */ new Set([
4776
+ var VOCABULARY_MODE_BLOCKED_KEYWORDS = /* @__PURE__ */ new Set([
4694
4777
  "$schema",
4695
4778
  "$ref",
4696
4779
  "$defs",
@@ -4761,7 +4844,7 @@ function applyCustomConstraint(schema, constraint, ctx) {
4761
4844
  if (registration.emitsVocabularyKeywords) {
4762
4845
  const target = schema;
4763
4846
  for (const [key, value] of Object.entries(extensionSchema)) {
4764
- if (JSON_SCHEMA_STRUCTURAL_KEYWORDS.has(key)) {
4847
+ if (VOCABULARY_MODE_BLOCKED_KEYWORDS.has(key)) {
4765
4848
  throw new Error(
4766
4849
  `Custom constraint "${constraint.constraintId}" with emitsVocabularyKeywords must not overwrite standard JSON Schema keyword "${key}"`
4767
4850
  );
@@ -4827,8 +4910,10 @@ function buildConstraintTagSources(extensions) {
4827
4910
  }
4828
4911
  function createExtensionRegistry(extensions) {
4829
4912
  const reservedTagSources = buildConstraintTagSources(extensions);
4913
+ let symbolMap = /* @__PURE__ */ new Map();
4830
4914
  const typeMap = /* @__PURE__ */ new Map();
4831
4915
  const typeNameMap = /* @__PURE__ */ new Map();
4916
+ const brandMap = /* @__PURE__ */ new Map();
4832
4917
  const constraintMap = /* @__PURE__ */ new Map();
4833
4918
  const constraintTagMap = /* @__PURE__ */ new Map();
4834
4919
  const builtinBroadeningMap = /* @__PURE__ */ new Map();
@@ -4852,6 +4937,20 @@ function createExtensionRegistry(extensions) {
4852
4937
  registration: type
4853
4938
  });
4854
4939
  }
4940
+ if (type.brand !== void 0) {
4941
+ if (type.brand === "__integerBrand") {
4942
+ throw new Error(
4943
+ `Brand "__integerBrand" is reserved for the builtin Integer type and cannot be registered by extensions`
4944
+ );
4945
+ }
4946
+ if (brandMap.has(type.brand)) {
4947
+ throw new Error(`Duplicate custom type brand: "${type.brand}"`);
4948
+ }
4949
+ brandMap.set(type.brand, {
4950
+ extensionId: ext.extensionId,
4951
+ registration: type
4952
+ });
4953
+ }
4855
4954
  if (type.builtinConstraintBroadenings !== void 0) {
4856
4955
  for (const broadening of type.builtinConstraintBroadenings) {
4857
4956
  const key = `${qualifiedId}:${broadening.tagName}`;
@@ -4921,7 +5020,10 @@ function createExtensionRegistry(extensions) {
4921
5020
  `Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${canonicalTagName}".`
4922
5021
  );
4923
5022
  }
4924
- if (Object.hasOwn(BUILTIN_CONSTRAINT_DEFINITIONS2, normalizeConstraintTagName2(canonicalTagName))) {
5023
+ if (Object.hasOwn(
5024
+ BUILTIN_CONSTRAINT_DEFINITIONS2,
5025
+ normalizeConstraintTagName2(canonicalTagName)
5026
+ )) {
4925
5027
  throw new Error(
4926
5028
  `Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${normalizeConstraintTagName2(canonicalTagName)}".`
4927
5029
  );
@@ -4942,6 +5044,11 @@ function createExtensionRegistry(extensions) {
4942
5044
  extensions,
4943
5045
  findType: (typeId) => typeMap.get(typeId),
4944
5046
  findTypeByName: (typeName) => typeNameMap.get(typeName),
5047
+ findTypeByBrand: (brand) => brandMap.get(brand),
5048
+ findTypeBySymbol: (symbol) => symbolMap.get(symbol),
5049
+ setSymbolMap: (map) => {
5050
+ symbolMap = map;
5051
+ },
4945
5052
  findConstraint: (constraintId) => constraintMap.get(constraintId),
4946
5053
  findConstraintTag: (tagName) => constraintTagMap.get(normalizeFormSpecTagName2(tagName)),
4947
5054
  findBuiltinConstraintBroadening: (typeId, tagName) => builtinBroadeningMap.get(`${typeId}:${tagName}`),
@@ -4949,6 +5056,10 @@ function createExtensionRegistry(extensions) {
4949
5056
  };
4950
5057
  }
4951
5058
 
5059
+ // src/extensions/symbol-registry.ts
5060
+ import * as ts5 from "typescript";
5061
+ import * as path2 from "path";
5062
+
4952
5063
  // src/ui-schema/schema.ts
4953
5064
  import { z } from "zod";
4954
5065
  var jsonPointerSchema = z.string();
@@ -5157,7 +5268,10 @@ function irElementsToUiSchema(elements, fieldNameMap, parentRule) {
5157
5268
  break;
5158
5269
  }
5159
5270
  case "conditional": {
5160
- const newRule = createShowRule(fieldNameMap.get(element.fieldName) ?? element.fieldName, element.value);
5271
+ const newRule = createShowRule(
5272
+ fieldNameMap.get(element.fieldName) ?? element.fieldName,
5273
+ element.value
5274
+ );
5161
5275
  const combinedRule = parentRule !== void 0 ? combineRules(parentRule, newRule) : newRule;
5162
5276
  const childElements = irElementsToUiSchema(element.elements, fieldNameMap, combinedRule);
5163
5277
  result.push(...childElements);
@@ -5204,9 +5318,7 @@ function collectFieldNameMap(elements) {
5204
5318
  }
5205
5319
 
5206
5320
  // src/validate/constraint-validator.ts
5207
- import {
5208
- analyzeConstraintTargets
5209
- } from "@formspec/analysis/internal";
5321
+ import { analyzeConstraintTargets } from "@formspec/analysis/internal";
5210
5322
  function validateFieldNode(ctx, field) {
5211
5323
  const analysis = analyzeConstraintTargets(
5212
5324
  field.name,