@formspec/build 0.1.0-alpha.37 → 0.1.0-alpha.39

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.
@@ -14,11 +14,12 @@
14
14
  export { canonicalizeChainDSL } from "./canonicalize/index.js";
15
15
  export { canonicalizeTSDoc } from "./canonicalize/index.js";
16
16
  export type { TSDocSource } from "./canonicalize/index.js";
17
- export { createProgramContext, createProgramContextFromProgram, findClassByName, findInterfaceByName, findTypeAliasByName, analyzeNamedTypeToIRFromProgramContext, } from "./analyzer/program.js";
17
+ export { createProgramContext, createProgramContextFromProgram, findClassByName, findInterfaceByName, findTypeAliasByName, analyzeNamedTypeToIRFromProgramContextDetailed, analyzeNamedTypeToIRFromProgramContext, } from "./analyzer/program.js";
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
- export { generateClassSchemas } from "./generators/class-schema.js";
21
- export type { ClassSchemas } from "./generators/class-schema.js";
20
+ export type { AnalyzeNamedTypeToIRDetailedResult } from "./analyzer/program.js";
21
+ export { generateClassSchemas, generateClassSchemasDetailed } from "./generators/class-schema.js";
22
+ export type { ClassSchemas, DetailedClassSchemasResult } from "./generators/class-schema.js";
22
23
  export { generateJsonSchemaFromIR } from "./json-schema/ir-generator.js";
23
24
  export type { GenerateJsonSchemaFromIROptions, JsonSchema2020, } from "./json-schema/ir-generator.js";
24
25
  export { generateUiSchemaFromIR } from "./ui-schema/ir-generator.js";
@@ -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,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;AAGtC,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,YAAY,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAGjE,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,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"}
package/dist/internals.js CHANGED
@@ -897,6 +897,16 @@ function buildSupportingDeclarations(sourceFile, extensionTypeNames) {
897
897
  return true;
898
898
  }).map((statement) => statement.getText(sourceFile));
899
899
  }
900
+ function pushUniqueCompilerDiagnostics(target, additions) {
901
+ for (const diagnostic of additions) {
902
+ if ((diagnostic.code === "UNSUPPORTED_CUSTOM_TYPE_OVERRIDE" || diagnostic.code === "SYNTHETIC_SETUP_FAILURE") && target.some(
903
+ (existing) => existing.code === diagnostic.code && existing.message === diagnostic.message
904
+ )) {
905
+ continue;
906
+ }
907
+ target.push(diagnostic);
908
+ }
909
+ }
900
910
  function renderSyntheticArgumentExpression(valueKind, argumentText) {
901
911
  const trimmed = argumentText.trim();
902
912
  if (trimmed === "") {
@@ -1163,6 +1173,16 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
1163
1173
  if (result.diagnostics.length === 0) {
1164
1174
  return [];
1165
1175
  }
1176
+ const setupDiagnostic = result.diagnostics.find((diagnostic) => diagnostic.kind !== "typescript");
1177
+ if (setupDiagnostic !== void 0) {
1178
+ return [
1179
+ makeDiagnostic(
1180
+ setupDiagnostic.kind === "unsupported-custom-type-override" ? "UNSUPPORTED_CUSTOM_TYPE_OVERRIDE" : "SYNTHETIC_SETUP_FAILURE",
1181
+ setupDiagnostic.message,
1182
+ provenance
1183
+ )
1184
+ ];
1185
+ }
1166
1186
  const expectedLabel = definition.valueKind === null ? "compatible argument" : capabilityLabel(definition.valueKind);
1167
1187
  return [
1168
1188
  makeDiagnostic(
@@ -1328,7 +1348,7 @@ function parseTSDocTags(node, file = "", options) {
1328
1348
  options
1329
1349
  );
1330
1350
  if (compilerDiagnostics.length > 0) {
1331
- diagnostics.push(...compilerDiagnostics);
1351
+ pushUniqueCompilerDiagnostics(diagnostics, compilerDiagnostics);
1332
1352
  continue;
1333
1353
  }
1334
1354
  const constraintNode = parseConstraintTagValue(
@@ -1415,7 +1435,7 @@ function parseTSDocTags(node, file = "", options) {
1415
1435
  options
1416
1436
  );
1417
1437
  if (compilerDiagnostics.length > 0) {
1418
- diagnostics.push(...compilerDiagnostics);
1438
+ pushUniqueCompilerDiagnostics(diagnostics, compilerDiagnostics);
1419
1439
  continue;
1420
1440
  }
1421
1441
  const constraintNode = parseConstraintTagValue(
@@ -1449,7 +1469,7 @@ function parseTSDocTags(node, file = "", options) {
1449
1469
  options
1450
1470
  );
1451
1471
  if (compilerDiagnostics.length > 0) {
1452
- diagnostics.push(...compilerDiagnostics);
1472
+ pushUniqueCompilerDiagnostics(diagnostics, compilerDiagnostics);
1453
1473
  continue;
1454
1474
  }
1455
1475
  const constraintNode = parseConstraintTagValue(
@@ -3862,29 +3882,35 @@ function findFallbackAliasDuplicatePropertyNames(typeNode, checker) {
3862
3882
  }
3863
3883
  return [...duplicates].sort();
3864
3884
  }
3865
- function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensionRegistry, metadataPolicy, discriminatorOptions) {
3885
+ function analyzeNamedTypeToIRFromProgramContextDetailed(ctx, filePath, typeName, extensionRegistry, metadataPolicy, discriminatorOptions) {
3866
3886
  const analysisFilePath = path.resolve(filePath);
3867
3887
  const classDecl = findClassByName(ctx.sourceFile, typeName);
3868
3888
  if (classDecl !== null) {
3869
- return analyzeClassToIR(
3870
- classDecl,
3871
- ctx.checker,
3872
- analysisFilePath,
3873
- extensionRegistry,
3874
- metadataPolicy,
3875
- discriminatorOptions
3876
- );
3889
+ return {
3890
+ ok: true,
3891
+ analysis: analyzeClassToIR(
3892
+ classDecl,
3893
+ ctx.checker,
3894
+ analysisFilePath,
3895
+ extensionRegistry,
3896
+ metadataPolicy,
3897
+ discriminatorOptions
3898
+ )
3899
+ };
3877
3900
  }
3878
3901
  const interfaceDecl = findInterfaceByName(ctx.sourceFile, typeName);
3879
3902
  if (interfaceDecl !== null) {
3880
- return analyzeInterfaceToIR(
3881
- interfaceDecl,
3882
- ctx.checker,
3883
- analysisFilePath,
3884
- extensionRegistry,
3885
- metadataPolicy,
3886
- discriminatorOptions
3887
- );
3903
+ return {
3904
+ ok: true,
3905
+ analysis: analyzeInterfaceToIR(
3906
+ interfaceDecl,
3907
+ ctx.checker,
3908
+ analysisFilePath,
3909
+ extensionRegistry,
3910
+ metadataPolicy,
3911
+ discriminatorOptions
3912
+ )
3913
+ };
3888
3914
  }
3889
3915
  const typeAlias = findTypeAliasByName(ctx.sourceFile, typeName);
3890
3916
  if (typeAlias !== null) {
@@ -3897,11 +3923,20 @@ function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensi
3897
3923
  discriminatorOptions
3898
3924
  );
3899
3925
  if (result.ok) {
3900
- return result.analysis;
3926
+ return { ok: true, analysis: result.analysis };
3901
3927
  }
3902
3928
  const fallbackEligible = result.kind === "not-object-like" && isResolvableObjectLikeAliasTypeNode(typeAlias.type) && containsTypeReferenceInObjectLikeAlias(typeAlias.type);
3903
3929
  if (!fallbackEligible) {
3904
- throw new Error(result.error);
3930
+ return {
3931
+ ok: false,
3932
+ diagnostics: [
3933
+ makeProgramDiagnostic(
3934
+ result.kind === "duplicate-properties" ? "DUPLICATE_ROOT_PROPERTIES" : "UNSUPPORTED_ROOT_TYPE",
3935
+ result.error,
3936
+ makeNodeProvenance(typeAlias, analysisFilePath)
3937
+ )
3938
+ ]
3939
+ };
3905
3940
  }
3906
3941
  const duplicatePropertyNames = findFallbackAliasDuplicatePropertyNames(
3907
3942
  typeAlias.type,
@@ -3910,9 +3945,16 @@ function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensi
3910
3945
  if (duplicatePropertyNames.length > 0) {
3911
3946
  const sourceFile = typeAlias.getSourceFile();
3912
3947
  const { line } = sourceFile.getLineAndCharacterOfPosition(typeAlias.getStart());
3913
- throw new Error(
3914
- `Type alias "${typeAlias.name.text}" at line ${String(line + 1)} contains duplicate property names across object-like members: ${duplicatePropertyNames.join(", ")}`
3915
- );
3948
+ return {
3949
+ ok: false,
3950
+ diagnostics: [
3951
+ makeProgramDiagnostic(
3952
+ "DUPLICATE_ROOT_PROPERTIES",
3953
+ `Type alias "${typeAlias.name.text}" at line ${String(line + 1)} contains duplicate property names across object-like members: ${duplicatePropertyNames.join(", ")}`,
3954
+ makeNodeProvenance(typeAlias, analysisFilePath)
3955
+ )
3956
+ ]
3957
+ };
3916
3958
  }
3917
3959
  const rootInfo = analyzeDeclarationRootInfo(
3918
3960
  typeAlias,
@@ -3942,17 +3984,75 @@ function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensi
3942
3984
  diagnostics
3943
3985
  );
3944
3986
  if (fallbackAnalysis !== null) {
3945
- return fallbackAnalysis;
3987
+ return { ok: true, analysis: fallbackAnalysis };
3946
3988
  }
3947
- throw new Error(result.error);
3989
+ return {
3990
+ ok: false,
3991
+ diagnostics: [
3992
+ makeProgramDiagnostic(
3993
+ "UNSUPPORTED_ROOT_TYPE",
3994
+ result.error,
3995
+ makeNodeProvenance(typeAlias, analysisFilePath)
3996
+ )
3997
+ ]
3998
+ };
3948
3999
  }
3949
- throw new Error(
3950
- `Type "${typeName}" not found as a class, interface, or type alias in ${analysisFilePath}`
4000
+ return {
4001
+ ok: false,
4002
+ diagnostics: [
4003
+ makeProgramDiagnostic(
4004
+ "TYPE_NOT_FOUND",
4005
+ `Type "${typeName}" not found as a class, interface, or type alias in ${analysisFilePath}`,
4006
+ makeFileProvenance(analysisFilePath)
4007
+ )
4008
+ ]
4009
+ };
4010
+ }
4011
+ function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensionRegistry, metadataPolicy, discriminatorOptions) {
4012
+ const result = analyzeNamedTypeToIRFromProgramContextDetailed(
4013
+ ctx,
4014
+ filePath,
4015
+ typeName,
4016
+ extensionRegistry,
4017
+ metadataPolicy,
4018
+ discriminatorOptions
3951
4019
  );
4020
+ if (result.ok) {
4021
+ return result.analysis;
4022
+ }
4023
+ throw new Error(result.diagnostics.map((diagnostic) => diagnostic.message).join("\n"));
4024
+ }
4025
+ function makeProgramDiagnostic(code, message, primaryLocation) {
4026
+ return {
4027
+ code,
4028
+ message,
4029
+ severity: "error",
4030
+ primaryLocation,
4031
+ relatedLocations: []
4032
+ };
4033
+ }
4034
+ function makeNodeProvenance(node, filePath) {
4035
+ const sourceFile = node.getSourceFile();
4036
+ const position = sourceFile.getLineAndCharacterOfPosition(node.getStart());
4037
+ return {
4038
+ surface: "tsdoc",
4039
+ file: filePath,
4040
+ line: position.line + 1,
4041
+ column: position.character,
4042
+ length: node.getWidth()
4043
+ };
4044
+ }
4045
+ function makeFileProvenance(filePath) {
4046
+ return {
4047
+ surface: "tsdoc",
4048
+ file: filePath,
4049
+ line: 1,
4050
+ column: 0
4051
+ };
3952
4052
  }
3953
4053
 
3954
4054
  // src/generators/class-schema.ts
3955
- import "typescript";
4055
+ import * as ts5 from "typescript";
3956
4056
 
3957
4057
  // src/metadata/collision-guards.ts
3958
4058
  function assertUniqueSerializedNames(entries, scope) {
@@ -5016,11 +5116,25 @@ function validateIR(ir, options) {
5016
5116
 
5017
5117
  // src/generators/class-schema.ts
5018
5118
  function generateClassSchemas(analysis, source, options) {
5019
- const errorDiagnostics = analysis.diagnostics?.filter(
5119
+ const result = generateClassSchemasDetailed(analysis, source, options);
5120
+ if (!result.ok || result.jsonSchema === void 0 || result.uiSchema === void 0) {
5121
+ throw new Error(formatValidationError(result.diagnostics));
5122
+ }
5123
+ return {
5124
+ jsonSchema: result.jsonSchema,
5125
+ uiSchema: result.uiSchema
5126
+ };
5127
+ }
5128
+ function generateClassSchemasDetailed(analysis, source, options) {
5129
+ const analysisDiagnostics = analysis.diagnostics ?? [];
5130
+ const errorDiagnostics = analysisDiagnostics.filter(
5020
5131
  (diagnostic) => diagnostic.severity === "error"
5021
5132
  );
5022
- if (errorDiagnostics !== void 0 && errorDiagnostics.length > 0) {
5023
- throw new Error(formatValidationError(errorDiagnostics));
5133
+ if (errorDiagnostics.length > 0) {
5134
+ return {
5135
+ ok: false,
5136
+ diagnostics: analysisDiagnostics
5137
+ };
5024
5138
  }
5025
5139
  const ir = canonicalizeTSDoc(
5026
5140
  analysis,
@@ -5034,9 +5148,14 @@ function generateClassSchemas(analysis, source, options) {
5034
5148
  ...options?.vendorPrefix !== void 0 && { vendorPrefix: options.vendorPrefix }
5035
5149
  });
5036
5150
  if (!validationResult.valid) {
5037
- throw new Error(formatValidationError(validationResult.diagnostics));
5151
+ return {
5152
+ ok: false,
5153
+ diagnostics: [...analysisDiagnostics, ...validationResult.diagnostics]
5154
+ };
5038
5155
  }
5039
5156
  return {
5157
+ ok: true,
5158
+ diagnostics: [...analysisDiagnostics, ...validationResult.diagnostics],
5040
5159
  jsonSchema: generateJsonSchemaFromIR(ir, options),
5041
5160
  uiSchema: generateUiSchemaFromIR(ir)
5042
5161
  };
@@ -5321,6 +5440,7 @@ export {
5321
5440
  analyzeClassToIR,
5322
5441
  analyzeInterfaceToIR,
5323
5442
  analyzeNamedTypeToIRFromProgramContext,
5443
+ analyzeNamedTypeToIRFromProgramContextDetailed,
5324
5444
  analyzeTypeAliasToIR,
5325
5445
  canonicalizeChainDSL,
5326
5446
  canonicalizeTSDoc,
@@ -5332,6 +5452,7 @@ export {
5332
5452
  findInterfaceByName,
5333
5453
  findTypeAliasByName,
5334
5454
  generateClassSchemas,
5455
+ generateClassSchemasDetailed,
5335
5456
  generateJsonSchemaFromIR,
5336
5457
  generateMethodSchemas,
5337
5458
  generateUiSchemaFromIR,