@formspec/build 0.1.0-alpha.53 → 0.1.0-alpha.55

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/cli.cjs CHANGED
@@ -1241,10 +1241,11 @@ function generatePrimitiveType(type) {
1241
1241
  function generateEnumType(type, ctx) {
1242
1242
  if (ctx.enumSerialization === "oneOf") {
1243
1243
  return {
1244
- oneOf: type.members.map((m) => ({
1245
- const: m.value,
1246
- title: m.displayName ?? String(m.value)
1247
- }))
1244
+ oneOf: type.members.map((m) => {
1245
+ const stringValue = String(m.value);
1246
+ const title = m.displayName !== void 0 && m.displayName !== stringValue ? m.displayName : void 0;
1247
+ return title !== void 0 ? { const: m.value, title } : { const: m.value };
1248
+ })
1248
1249
  };
1249
1250
  }
1250
1251
  const schema = { enum: type.members.map((m) => m.value) };
@@ -2072,6 +2073,11 @@ function buildConstraintTagSources(extensions) {
2072
2073
  }));
2073
2074
  }
2074
2075
  function createExtensionRegistry(extensions) {
2076
+ const registryLog = (0, import_internal.getSyntheticLogger)();
2077
+ registryLog.debug("createExtensionRegistry: constructing", {
2078
+ extensionCount: extensions.length,
2079
+ extensionIds: extensions.map((e) => e.extensionId)
2080
+ });
2075
2081
  const reservedTagSources = buildConstraintTagSources(extensions);
2076
2082
  let symbolMap = /* @__PURE__ */ new Map();
2077
2083
  const typeMap = /* @__PURE__ */ new Map();
@@ -2203,6 +2209,14 @@ function createExtensionRegistry(extensions) {
2203
2209
  }
2204
2210
  }
2205
2211
  }
2212
+ registryLog.debug("createExtensionRegistry: complete", {
2213
+ typeCount: typeMap.size,
2214
+ constraintCount: constraintMap.size,
2215
+ constraintTagCount: constraintTagMap.size,
2216
+ broadeningCount: builtinBroadeningMap.size,
2217
+ annotationCount: annotationMap.size,
2218
+ metadataSlotCount: metadataSlotMap.size
2219
+ });
2206
2220
  return {
2207
2221
  extensions,
2208
2222
  findType: (typeId) => typeMap.get(typeId),
@@ -2851,56 +2865,82 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
2851
2865
  if (definition === null) {
2852
2866
  return [];
2853
2867
  }
2868
+ const nonNullPlacement = placement;
2869
+ const log2 = (0, import_internal4.getBuildLogger)();
2870
+ const broadeningLog = (0, import_internal4.getBroadeningLogger)();
2871
+ const syntheticLog = (0, import_internal4.getSyntheticLogger)();
2872
+ const logsEnabled = log2 !== import_core4.noopLogger || broadeningLog !== import_core4.noopLogger;
2873
+ const syntheticTraceEnabled = syntheticLog !== import_core4.noopLogger;
2874
+ const logStart = logsEnabled ? (0, import_internal4.nowMicros)() : 0;
2875
+ const subjectTypeKind = logsEnabled ? (0, import_internal4.describeTypeKind)(subjectType, checker) : "";
2876
+ function emit(outcome, result2) {
2877
+ if (!logsEnabled) {
2878
+ return result2;
2879
+ }
2880
+ const entry = {
2881
+ consumer: "build",
2882
+ tag: tagName,
2883
+ placement: nonNullPlacement,
2884
+ subjectTypeKind,
2885
+ roleOutcome: outcome,
2886
+ elapsedMicros: (0, import_internal4.elapsedMicros)(logStart)
2887
+ };
2888
+ (0, import_internal4.logTagApplication)(log2, entry);
2889
+ if (outcome === "bypass" || outcome === "D1" || outcome === "D2") {
2890
+ (0, import_internal4.logTagApplication)(broadeningLog, entry);
2891
+ }
2892
+ return result2;
2893
+ }
2854
2894
  if (!definition.placements.includes(placement)) {
2855
- return [
2895
+ return emit("A-reject", [
2856
2896
  makeDiagnostic(
2857
2897
  "INVALID_TAG_PLACEMENT",
2858
2898
  `Tag "@${tagName}" is not allowed on ${placementLabel(placement)}.`,
2859
2899
  provenance
2860
2900
  )
2861
- ];
2901
+ ]);
2862
2902
  }
2863
2903
  const target = parsedTag?.target ?? null;
2864
2904
  let evaluatedType = subjectType;
2865
2905
  let targetLabel = node.getText(sourceFile);
2866
2906
  if (target !== null) {
2867
2907
  if (target.kind !== "path") {
2868
- return [
2908
+ return emit("B-reject", [
2869
2909
  makeDiagnostic(
2870
2910
  "UNSUPPORTED_TARGETING_SYNTAX",
2871
2911
  `Tag "@${tagName}" does not support ${target.kind} targeting syntax.`,
2872
2912
  provenance
2873
2913
  )
2874
- ];
2914
+ ]);
2875
2915
  }
2876
2916
  if (!target.valid || target.path === null) {
2877
- return [
2917
+ return emit("B-reject", [
2878
2918
  makeDiagnostic(
2879
2919
  "UNSUPPORTED_TARGETING_SYNTAX",
2880
2920
  `Tag "@${tagName}" has invalid path targeting syntax.`,
2881
2921
  provenance
2882
2922
  )
2883
- ];
2923
+ ]);
2884
2924
  }
2885
2925
  const resolution = (0, import_internal3.resolvePathTargetType)(subjectType, checker, target.path.segments);
2886
2926
  if (resolution.kind === "missing-property") {
2887
- return [
2927
+ return emit("B-reject", [
2888
2928
  makeDiagnostic(
2889
2929
  "UNKNOWN_PATH_TARGET",
2890
2930
  `Target "${target.rawText}": path-targeted constraint "${tagName}" references unknown path segment "${resolution.segment}"`,
2891
2931
  provenance
2892
2932
  )
2893
- ];
2933
+ ]);
2894
2934
  }
2895
2935
  if (resolution.kind === "unresolvable") {
2896
2936
  const actualType = checker.typeToString(resolution.type, node, SYNTHETIC_TYPE_FORMAT_FLAGS);
2897
- return [
2937
+ return emit("B-reject", [
2898
2938
  makeDiagnostic(
2899
2939
  "TYPE_MISMATCH",
2900
2940
  `Target "${target.rawText}": path-targeted constraint "${tagName}" is invalid because type "${actualType}" cannot be traversed`,
2901
2941
  provenance
2902
2942
  )
2903
- ];
2943
+ ]);
2904
2944
  }
2905
2945
  evaluatedType = resolution.type;
2906
2946
  targetLabel = target.rawText;
@@ -2929,13 +2969,13 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
2929
2969
  tagName,
2930
2970
  parsedTag?.argumentText
2931
2971
  ) : null;
2932
- return [
2972
+ return emit("B-reject", [
2933
2973
  makeDiagnostic(
2934
2974
  "TYPE_MISMATCH",
2935
2975
  hint === null ? baseMessage : `${baseMessage}. ${hint}`,
2936
2976
  provenance
2937
2977
  )
2938
- ];
2978
+ ]);
2939
2979
  }
2940
2980
  }
2941
2981
  const argumentExpression = renderSyntheticArgumentExpression(
@@ -2943,14 +2983,23 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
2943
2983
  parsedTag?.argumentText ?? ""
2944
2984
  );
2945
2985
  if (definition.requiresArgument && argumentExpression === null) {
2946
- return [];
2986
+ return emit("A-pass", []);
2947
2987
  }
2948
2988
  if (hasBroadening) {
2949
- return [];
2989
+ return emit("bypass", []);
2950
2990
  }
2951
2991
  const subjectTypeText = checker.typeToString(subjectType, node, SYNTHETIC_TYPE_FORMAT_FLAGS);
2952
2992
  const hostType = options?.hostType ?? subjectType;
2953
2993
  const hostTypeText = checker.typeToString(hostType, node, SYNTHETIC_TYPE_FORMAT_FLAGS);
2994
+ if (syntheticTraceEnabled) {
2995
+ syntheticLog.trace("invoking synthetic checker", {
2996
+ consumer: "build",
2997
+ tag: tagName,
2998
+ placement,
2999
+ subjectTypeKind,
3000
+ subjectTypeText
3001
+ });
3002
+ }
2954
3003
  const result = (0, import_internal3.checkSyntheticTagApplication)({
2955
3004
  tagName,
2956
3005
  placement,
@@ -2977,26 +3026,26 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
2977
3026
  } : {}
2978
3027
  });
2979
3028
  if (result.diagnostics.length === 0) {
2980
- return [];
3029
+ return emit("C-pass", []);
2981
3030
  }
2982
3031
  const setupDiagnostic = result.diagnostics.find((diagnostic) => diagnostic.kind !== "typescript");
2983
3032
  if (setupDiagnostic !== void 0) {
2984
- return [
3033
+ return emit("C-reject", [
2985
3034
  makeDiagnostic(
2986
3035
  setupDiagnostic.kind === "unsupported-custom-type-override" ? "UNSUPPORTED_CUSTOM_TYPE_OVERRIDE" : "SYNTHETIC_SETUP_FAILURE",
2987
3036
  setupDiagnostic.message,
2988
3037
  provenance
2989
3038
  )
2990
- ];
3039
+ ]);
2991
3040
  }
2992
3041
  const expectedLabel = definition.valueKind === null ? "compatible argument" : capabilityLabel(definition.valueKind);
2993
- return [
3042
+ return emit("C-reject", [
2994
3043
  makeDiagnostic(
2995
3044
  "TYPE_MISMATCH",
2996
3045
  `Tag "@${tagName}" received an invalid argument for ${expectedLabel}.`,
2997
3046
  provenance
2998
3047
  )
2999
- ];
3048
+ ]);
3000
3049
  }
3001
3050
  function getExtensionTagNames(options) {
3002
3051
  return [
@@ -3308,7 +3357,7 @@ function getTagCommentText(tag) {
3308
3357
  }
3309
3358
  return ts4.getTextOfJSDocComment(tag.comment);
3310
3359
  }
3311
- var ts4, import_internal3, import_internals4, import_internals5, SYNTHETIC_TYPE_FORMAT_FLAGS, MAX_HINT_CANDIDATES, MAX_HINT_DEPTH, parseResultCache;
3360
+ var ts4, import_internal3, import_internals4, import_internals5, import_core4, import_internal4, SYNTHETIC_TYPE_FORMAT_FLAGS, MAX_HINT_CANDIDATES, MAX_HINT_DEPTH, parseResultCache;
3312
3361
  var init_tsdoc_parser = __esm({
3313
3362
  "src/analyzer/tsdoc-parser.ts"() {
3314
3363
  "use strict";
@@ -3316,8 +3365,10 @@ var init_tsdoc_parser = __esm({
3316
3365
  import_internal3 = require("@formspec/analysis/internal");
3317
3366
  import_internals4 = require("@formspec/core/internals");
3318
3367
  import_internals5 = require("@formspec/core/internals");
3368
+ import_core4 = require("@formspec/core");
3319
3369
  init_resolve_custom_type();
3320
3370
  init_builtin_brands();
3371
+ import_internal4 = require("@formspec/analysis/internal");
3321
3372
  SYNTHETIC_TYPE_FORMAT_FLAGS = ts4.TypeFormatFlags.NoTruncation | ts4.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope;
3322
3373
  MAX_HINT_CANDIDATES = 5;
3323
3374
  MAX_HINT_DEPTH = 3;
@@ -3424,7 +3475,7 @@ function createAnalyzerMetadataPolicy(input, discriminator) {
3424
3475
  };
3425
3476
  }
3426
3477
  function resolveNodeMetadata(metadataPolicy, declarationKind, logicalName, node, checker, extensionRegistry, buildContext) {
3427
- const analysis = (0, import_internal4.analyzeMetadataForNodeWithChecker)({
3478
+ const analysis = (0, import_internal5.analyzeMetadataForNodeWithChecker)({
3428
3479
  checker,
3429
3480
  node,
3430
3481
  logicalName,
@@ -3765,7 +3816,7 @@ function getLeadingParsedTags(node) {
3765
3816
  if (!commentText.startsWith("/**")) {
3766
3817
  continue;
3767
3818
  }
3768
- parsedTags.push(...(0, import_internal4.parseCommentBlock)(commentText, { offset: range.pos }).tags);
3819
+ parsedTags.push(...(0, import_internal5.parseCommentBlock)(commentText, { offset: range.pos }).tags);
3769
3820
  }
3770
3821
  return parsedTags;
3771
3822
  }
@@ -4174,6 +4225,22 @@ function extractReferenceTypeArguments(type, checker, file, typeRegistry, visiti
4174
4225
  }
4175
4226
  return referenceTypeNode.typeArguments.map((argumentNode) => {
4176
4227
  const argumentType = checker.getTypeFromTypeNode(argumentNode);
4228
+ const baseSymbol = argumentType.aliasSymbol ?? argumentType.getSymbol();
4229
+ const argumentSymbol = baseSymbol !== void 0 && baseSymbol.flags & ts6.SymbolFlags.Alias ? checker.getAliasedSymbol(baseSymbol) : baseSymbol;
4230
+ const argumentDecl = argumentSymbol?.declarations?.[0];
4231
+ if (argumentDecl !== void 0 && argumentDecl.getSourceFile().fileName !== file) {
4232
+ const argumentName = argumentSymbol?.getName() ?? baseSymbol?.getName();
4233
+ if (argumentName !== void 0) {
4234
+ return {
4235
+ tsType: argumentType,
4236
+ typeNode: {
4237
+ kind: "reference",
4238
+ name: argumentName,
4239
+ typeArguments: []
4240
+ }
4241
+ };
4242
+ }
4243
+ }
4177
4244
  return {
4178
4245
  tsType: argumentType,
4179
4246
  typeNode: resolveTypeNode(
@@ -4627,6 +4694,21 @@ function getReferencedTypeAliasDeclaration(sourceNode, checker) {
4627
4694
  }
4628
4695
  return getTypeAliasDeclarationFromTypeReference(typeNode, checker);
4629
4696
  }
4697
+ function resolveNamedTypeWithSourceRecovery(type, sourceNode, checker) {
4698
+ const typeName = getNamedTypeName(type);
4699
+ const namedDecl = getNamedTypeDeclaration(type);
4700
+ if (typeName !== null && namedDecl !== void 0) {
4701
+ return { typeName, namedDecl };
4702
+ }
4703
+ if (sourceNode === void 0) {
4704
+ return null;
4705
+ }
4706
+ const refAliasDecl = getReferencedTypeAliasDeclaration(sourceNode, checker);
4707
+ if (refAliasDecl === void 0) {
4708
+ return null;
4709
+ }
4710
+ return { typeName: refAliasDecl.name.text, namedDecl: refAliasDecl };
4711
+ }
4630
4712
  function shouldEmitPrimitiveAliasDefinition(typeNode, checker) {
4631
4713
  if (!ts6.isTypeReferenceNode(typeNode)) {
4632
4714
  return false;
@@ -4685,8 +4767,23 @@ function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiti
4685
4767
  );
4686
4768
  }
4687
4769
  function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4688
- const typeName = getNamedTypeName(type);
4689
- const namedDecl = getNamedTypeDeclaration(type);
4770
+ const recovered = resolveNamedTypeWithSourceRecovery(type, sourceNode, checker);
4771
+ let typeName = null;
4772
+ let namedDecl;
4773
+ if (recovered !== null) {
4774
+ const recoveredAliasDecl = ts6.isTypeAliasDeclaration(recovered.namedDecl) ? recovered.namedDecl : void 0;
4775
+ if (recoveredAliasDecl !== void 0) {
4776
+ const aliasUnderlyingType = checker.getTypeFromTypeNode(recoveredAliasDecl.type);
4777
+ const isNonGeneric = recoveredAliasDecl.typeParameters === void 0 || recoveredAliasDecl.typeParameters.length === 0;
4778
+ if (isNonGeneric && (aliasUnderlyingType.isUnion() || isObjectType(aliasUnderlyingType))) {
4779
+ typeName = recovered.typeName;
4780
+ namedDecl = recovered.namedDecl;
4781
+ }
4782
+ } else {
4783
+ typeName = recovered.typeName;
4784
+ namedDecl = recovered.namedDecl;
4785
+ }
4786
+ }
4690
4787
  if (typeName && typeName in typeRegistry) {
4691
4788
  return { kind: "reference", name: typeName, typeArguments: [] };
4692
4789
  }
@@ -4718,6 +4815,10 @@ function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNod
4718
4815
  if (!typeName) {
4719
4816
  return result;
4720
4817
  }
4818
+ const existing = typeRegistry[typeName];
4819
+ if (existing !== void 0 && existing.type !== RESOLVING_TYPE_PLACEHOLDER) {
4820
+ return { kind: "reference", name: typeName, typeArguments: [] };
4821
+ }
4721
4822
  const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
4722
4823
  const metadata = namedDecl !== void 0 ? resolveNodeMetadata(
4723
4824
  metadataPolicy,
@@ -5365,12 +5466,12 @@ function detectFormSpecReference(typeNode) {
5365
5466
  }
5366
5467
  return null;
5367
5468
  }
5368
- var ts6, import_internal4, RESOLVING_TYPE_PLACEHOLDER, MAX_ALIAS_CHAIN_DEPTH;
5469
+ var ts6, import_internal5, RESOLVING_TYPE_PLACEHOLDER, MAX_ALIAS_CHAIN_DEPTH;
5369
5470
  var init_class_analyzer = __esm({
5370
5471
  "src/analyzer/class-analyzer.ts"() {
5371
5472
  "use strict";
5372
5473
  ts6 = __toESM(require("typescript"), 1);
5373
- import_internal4 = require("@formspec/analysis/internal");
5474
+ import_internal5 = require("@formspec/analysis/internal");
5374
5475
  init_jsdoc_constraints();
5375
5476
  init_tsdoc_parser();
5376
5477
  init_resolve_custom_type();
@@ -5877,7 +5978,7 @@ var init_symbol_registry = __esm({
5877
5978
 
5878
5979
  // src/validate/constraint-validator.ts
5879
5980
  function validateFieldNode(ctx, field) {
5880
- const analysis = (0, import_internal5.analyzeConstraintTargets)(
5981
+ const analysis = (0, import_internal6.analyzeConstraintTargets)(
5881
5982
  field.name,
5882
5983
  field.type,
5883
5984
  field.constraints,
@@ -5895,7 +5996,7 @@ function validateFieldNode(ctx, field) {
5895
5996
  }
5896
5997
  function validateObjectProperty(ctx, parentName, property) {
5897
5998
  const qualifiedName = `${parentName}.${property.name}`;
5898
- const analysis = (0, import_internal5.analyzeConstraintTargets)(
5999
+ const analysis = (0, import_internal6.analyzeConstraintTargets)(
5899
6000
  qualifiedName,
5900
6001
  property.type,
5901
6002
  property.constraints,
@@ -5946,11 +6047,11 @@ function validateIR(ir, options) {
5946
6047
  valid: ctx.diagnostics.every((diagnostic) => diagnostic.severity !== "error")
5947
6048
  };
5948
6049
  }
5949
- var import_internal5;
6050
+ var import_internal6;
5950
6051
  var init_constraint_validator = __esm({
5951
6052
  "src/validate/constraint-validator.ts"() {
5952
6053
  "use strict";
5953
- import_internal5 = require("@formspec/analysis/internal");
6054
+ import_internal6 = require("@formspec/analysis/internal");
5954
6055
  }
5955
6056
  });
5956
6057
 
@@ -6698,7 +6799,7 @@ function generateSchemasFromReturnType(options) {
6698
6799
  }
6699
6800
  function resolveDeclarationMetadata(options) {
6700
6801
  const resolved = resolveStaticOptions(options);
6701
- const analysis = (0, import_internal6.analyzeMetadataForNodeWithChecker)({
6802
+ const analysis = (0, import_internal7.analyzeMetadataForNodeWithChecker)({
6702
6803
  checker: options.context.checker,
6703
6804
  node: options.declaration,
6704
6805
  metadata: resolved.metadata,
@@ -6744,12 +6845,12 @@ function unwrapPromiseTypeNode(typeNode) {
6744
6845
  function isPromiseTypeReferenceNode(typeNode) {
6745
6846
  return ts11.isTypeReferenceNode(typeNode) && ts11.isIdentifier(typeNode.typeName) && typeNode.typeName.text === "Promise" && typeNode.typeArguments !== void 0 && typeNode.typeArguments.length > 0;
6746
6847
  }
6747
- var ts11, import_internal6, import_internals6;
6848
+ var ts11, import_internal7, import_internals6;
6748
6849
  var init_discovered_schema = __esm({
6749
6850
  "src/generators/discovered-schema.ts"() {
6750
6851
  "use strict";
6751
6852
  ts11 = __toESM(require("typescript"), 1);
6752
- import_internal6 = require("@formspec/analysis/internal");
6853
+ import_internal7 = require("@formspec/analysis/internal");
6753
6854
  init_class_analyzer();
6754
6855
  init_class_schema();
6755
6856
  init_ir_generator();
@@ -6991,7 +7092,7 @@ __export(index_exports, {
6991
7092
  writeSchemas: () => writeSchemas
6992
7093
  });
6993
7094
  function buildFormSchemas(form, options) {
6994
- const logger = options?.logger ?? import_core4.noopLogger;
7095
+ const logger = options?.logger ?? import_core5.noopLogger;
6995
7096
  logger.debug("buildFormSchemas: starting schema generation");
6996
7097
  return {
6997
7098
  jsonSchema: generateJsonSchema(form, options),
@@ -7008,7 +7109,7 @@ function writeSchemas(form, options) {
7008
7109
  metadata,
7009
7110
  logger: rawLogger
7010
7111
  } = options;
7011
- const logger = (rawLogger ?? import_core4.noopLogger).child({ stage: "write" });
7112
+ const logger = (rawLogger ?? import_core5.noopLogger).child({ stage: "write" });
7012
7113
  const buildOptions = vendorPrefix === void 0 && enumSerialization === void 0 && metadata === void 0 ? { logger: rawLogger } : {
7013
7114
  ...vendorPrefix !== void 0 && { vendorPrefix },
7014
7115
  ...enumSerialization !== void 0 && { enumSerialization },
@@ -7027,11 +7128,11 @@ function writeSchemas(form, options) {
7027
7128
  fs.writeFileSync(uiSchemaPath, JSON.stringify(uiSchema2, null, indent));
7028
7129
  return { jsonSchemaPath, uiSchemaPath };
7029
7130
  }
7030
- var import_core4, fs, path3;
7131
+ var import_core5, fs, path3;
7031
7132
  var init_index = __esm({
7032
7133
  "src/index.ts"() {
7033
7134
  "use strict";
7034
- import_core4 = require("@formspec/core");
7135
+ import_core5 = require("@formspec/core");
7035
7136
  init_generator();
7036
7137
  init_generator2();
7037
7138
  init_ir_generator();