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

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 +364 -116
  14. package/dist/cli.cjs.map +1 -1
  15. package/dist/cli.js +360 -115
  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 +32 -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 +350 -109
  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 +351 -112
  31. package/dist/index.js.map +1 -1
  32. package/dist/internals.cjs +121 -23
  33. package/dist/internals.cjs.map +1 -1
  34. package/dist/internals.d.ts +2 -2
  35. package/dist/internals.d.ts.map +1 -1
  36. package/dist/internals.js +121 -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
@@ -18,7 +18,7 @@ export { createProgramContext, createProgramContextFromProgram, findClassByName,
18
18
  export { analyzeClassToIR, analyzeInterfaceToIR, analyzeTypeAliasToIR, } from "./analyzer/class-analyzer.js";
19
19
  export type { DiscriminatorResolutionOptions, IRClassAnalysis, FieldLayoutMetadata, AnalyzeTypeAliasToIRResult, } from "./analyzer/class-analyzer.js";
20
20
  export type { AnalyzeNamedTypeToIRDetailedResult } from "./analyzer/program.js";
21
- export { generateClassSchemas, generateClassSchemasDetailed } from "./generators/class-schema.js";
21
+ export { generateClassSchemas, generateClassSchemasDetailed, resolveStaticOptions, } from "./generators/class-schema.js";
22
22
  export type { ClassSchemas, DetailedClassSchemasResult } from "./generators/class-schema.js";
23
23
  export { generateJsonSchemaFromIR } from "./json-schema/ir-generator.js";
24
24
  export type { GenerateJsonSchemaFromIROptions, JsonSchema2020, } from "./json-schema/ir-generator.js";
@@ -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,EACL,oBAAoB,EACpB,4BAA4B,EAC5B,oBAAoB,GACrB,MAAM,8BAA8B,CAAC;AACtC,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,30 +1600,70 @@ 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
+ }
1601
1641
  function isIntegerBrandedType(type) {
1602
1642
  if (!type.isIntersection()) {
1603
1643
  return false;
1604
1644
  }
1605
- const hasNumberBase = type.types.some(
1606
- (member) => !!(member.flags & ts3.TypeFlags.Number)
1607
- );
1645
+ const hasNumberBase = type.types.some((member) => !!(member.flags & ts3.TypeFlags.Number));
1608
1646
  if (!hasNumberBase) {
1609
1647
  return false;
1610
1648
  }
1611
- return type.getProperties().some((prop) => {
1612
- const declaration = prop.valueDeclaration ?? prop.declarations?.[0];
1613
- if (declaration === void 0) {
1614
- return false;
1615
- }
1616
- if (!ts3.isPropertySignature(declaration) && !ts3.isPropertyDeclaration(declaration)) {
1617
- return false;
1618
- }
1619
- const name = declaration.name;
1620
- if (!ts3.isComputedPropertyName(name)) {
1621
- return false;
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;
1622
1659
  }
1623
- return ts3.isIdentifier(name.expression) && name.expression.text === "__integerBrand";
1624
- });
1660
+ return {
1661
+ kind: "custom",
1662
+ typeId: `${registration.extensionId}/${registration.registration.typeName}`,
1663
+ payload: null
1664
+ };
1665
+ }
1666
+ return null;
1625
1667
  }
1626
1668
  function isResolvableObjectLikeAliasTypeNode(typeNode) {
1627
1669
  if (ts3.isParenthesizedTypeNode(typeNode)) {
@@ -2734,6 +2776,14 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
2734
2776
  if (customType) {
2735
2777
  return customType;
2736
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
+ }
2737
2787
  const primitiveAlias = tryResolveNamedPrimitiveAlias(
2738
2788
  type,
2739
2789
  checker,
@@ -3678,7 +3728,7 @@ function createProgramContextFromProgram(program, filePath) {
3678
3728
  sourceFile
3679
3729
  };
3680
3730
  }
3681
- function createProgramContext(filePath) {
3731
+ function createProgramContext(filePath, additionalFiles) {
3682
3732
  const absolutePath = path.resolve(filePath);
3683
3733
  const fileDir = path.dirname(absolutePath);
3684
3734
  const configPath = ts4.findConfigFile(fileDir, ts4.sys.fileExists.bind(ts4.sys), "tsconfig.json");
@@ -3701,7 +3751,8 @@ function createProgramContext(filePath) {
3701
3751
  throw new Error(`Error parsing tsconfig.json: ${errorMessages}`);
3702
3752
  }
3703
3753
  compilerOptions = parsed.options;
3704
- 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])];
3705
3756
  } else {
3706
3757
  compilerOptions = {
3707
3758
  target: ts4.ScriptTarget.ES2022,
@@ -3711,7 +3762,8 @@ function createProgramContext(filePath) {
3711
3762
  skipLibCheck: true,
3712
3763
  declaration: true
3713
3764
  };
3714
- fileNames = [absolutePath];
3765
+ const normalizedAdditional = (additionalFiles ?? []).map((f) => path.resolve(f));
3766
+ fileNames = [.../* @__PURE__ */ new Set([absolutePath, ...normalizedAdditional])];
3715
3767
  }
3716
3768
  const program = ts4.createProgram(fileNames, compilerOptions);
3717
3769
  const sourceFile = program.getSourceFile(absolutePath);
@@ -4005,7 +4057,7 @@ function makeFileProvenance(filePath) {
4005
4057
  }
4006
4058
 
4007
4059
  // src/generators/class-schema.ts
4008
- import * as ts5 from "typescript";
4060
+ import * as ts6 from "typescript";
4009
4061
 
4010
4062
  // src/metadata/collision-guards.ts
4011
4063
  function assertUniqueSerializedNames(entries, scope) {
@@ -4858,8 +4910,10 @@ function buildConstraintTagSources(extensions) {
4858
4910
  }
4859
4911
  function createExtensionRegistry(extensions) {
4860
4912
  const reservedTagSources = buildConstraintTagSources(extensions);
4913
+ let symbolMap = /* @__PURE__ */ new Map();
4861
4914
  const typeMap = /* @__PURE__ */ new Map();
4862
4915
  const typeNameMap = /* @__PURE__ */ new Map();
4916
+ const brandMap = /* @__PURE__ */ new Map();
4863
4917
  const constraintMap = /* @__PURE__ */ new Map();
4864
4918
  const constraintTagMap = /* @__PURE__ */ new Map();
4865
4919
  const builtinBroadeningMap = /* @__PURE__ */ new Map();
@@ -4883,6 +4937,20 @@ function createExtensionRegistry(extensions) {
4883
4937
  registration: type
4884
4938
  });
4885
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
+ }
4886
4954
  if (type.builtinConstraintBroadenings !== void 0) {
4887
4955
  for (const broadening of type.builtinConstraintBroadenings) {
4888
4956
  const key = `${qualifiedId}:${broadening.tagName}`;
@@ -4952,7 +5020,10 @@ function createExtensionRegistry(extensions) {
4952
5020
  `Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${canonicalTagName}".`
4953
5021
  );
4954
5022
  }
4955
- if (Object.hasOwn(BUILTIN_CONSTRAINT_DEFINITIONS2, normalizeConstraintTagName2(canonicalTagName))) {
5023
+ if (Object.hasOwn(
5024
+ BUILTIN_CONSTRAINT_DEFINITIONS2,
5025
+ normalizeConstraintTagName2(canonicalTagName)
5026
+ )) {
4956
5027
  throw new Error(
4957
5028
  `Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${normalizeConstraintTagName2(canonicalTagName)}".`
4958
5029
  );
@@ -4973,6 +5044,11 @@ function createExtensionRegistry(extensions) {
4973
5044
  extensions,
4974
5045
  findType: (typeId) => typeMap.get(typeId),
4975
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
+ },
4976
5052
  findConstraint: (constraintId) => constraintMap.get(constraintId),
4977
5053
  findConstraintTag: (tagName) => constraintTagMap.get(normalizeFormSpecTagName2(tagName)),
4978
5054
  findBuiltinConstraintBroadening: (typeId, tagName) => builtinBroadeningMap.get(`${typeId}:${tagName}`),
@@ -4980,6 +5056,10 @@ function createExtensionRegistry(extensions) {
4980
5056
  };
4981
5057
  }
4982
5058
 
5059
+ // src/extensions/symbol-registry.ts
5060
+ import * as ts5 from "typescript";
5061
+ import * as path2 from "path";
5062
+
4983
5063
  // src/ui-schema/schema.ts
4984
5064
  import { z } from "zod";
4985
5065
  var jsonPointerSchema = z.string();
@@ -5188,7 +5268,10 @@ function irElementsToUiSchema(elements, fieldNameMap, parentRule) {
5188
5268
  break;
5189
5269
  }
5190
5270
  case "conditional": {
5191
- 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
+ );
5192
5275
  const combinedRule = parentRule !== void 0 ? combineRules(parentRule, newRule) : newRule;
5193
5276
  const childElements = irElementsToUiSchema(element.elements, fieldNameMap, combinedRule);
5194
5277
  result.push(...childElements);
@@ -5235,9 +5318,7 @@ function collectFieldNameMap(elements) {
5235
5318
  }
5236
5319
 
5237
5320
  // src/validate/constraint-validator.ts
5238
- import {
5239
- analyzeConstraintTargets
5240
- } from "@formspec/analysis/internal";
5321
+ import { analyzeConstraintTargets } from "@formspec/analysis/internal";
5241
5322
  function validateFieldNode(ctx, field) {
5242
5323
  const analysis = analyzeConstraintTargets(
5243
5324
  field.name,
@@ -5367,6 +5448,19 @@ ${lines.map((line) => `- ${line}`).join("\n")}`;
5367
5448
  function formatLocation(location) {
5368
5449
  return `${location.file}:${String(location.line)}:${String(location.column)}`;
5369
5450
  }
5451
+ function resolveStaticOptions(options) {
5452
+ const legacyRegistry = options.extensionRegistry;
5453
+ const configRegistry = legacyRegistry === void 0 && options.config?.extensions !== void 0 ? createExtensionRegistry(options.config.extensions) : void 0;
5454
+ return {
5455
+ extensionRegistry: legacyRegistry ?? configRegistry,
5456
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
5457
+ vendorPrefix: options.vendorPrefix ?? options.config?.vendorPrefix,
5458
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
5459
+ enumSerialization: options.enumSerialization ?? options.config?.enumSerialization,
5460
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
5461
+ metadata: options.metadata ?? options.config?.metadata
5462
+ };
5463
+ }
5370
5464
 
5371
5465
  // src/generators/method-schema.ts
5372
5466
  import { IR_VERSION as IR_VERSION3 } from "@formspec/core/internals";
@@ -5510,6 +5604,7 @@ export {
5510
5604
  generateJsonSchemaFromIR,
5511
5605
  generateMethodSchemas,
5512
5606
  generateUiSchemaFromIR,
5607
+ resolveStaticOptions,
5513
5608
  validateIR
5514
5609
  };
5515
5610
  //# sourceMappingURL=internals.js.map