@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.
package/dist/cli.js CHANGED
@@ -2237,6 +2237,16 @@ function buildSupportingDeclarations(sourceFile, extensionTypeNames) {
2237
2237
  return true;
2238
2238
  }).map((statement) => statement.getText(sourceFile));
2239
2239
  }
2240
+ function pushUniqueCompilerDiagnostics(target, additions) {
2241
+ for (const diagnostic of additions) {
2242
+ if ((diagnostic.code === "UNSUPPORTED_CUSTOM_TYPE_OVERRIDE" || diagnostic.code === "SYNTHETIC_SETUP_FAILURE") && target.some(
2243
+ (existing) => existing.code === diagnostic.code && existing.message === diagnostic.message
2244
+ )) {
2245
+ continue;
2246
+ }
2247
+ target.push(diagnostic);
2248
+ }
2249
+ }
2240
2250
  function renderSyntheticArgumentExpression(valueKind, argumentText) {
2241
2251
  const trimmed = argumentText.trim();
2242
2252
  if (trimmed === "") {
@@ -2503,6 +2513,16 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
2503
2513
  if (result.diagnostics.length === 0) {
2504
2514
  return [];
2505
2515
  }
2516
+ const setupDiagnostic = result.diagnostics.find((diagnostic) => diagnostic.kind !== "typescript");
2517
+ if (setupDiagnostic !== void 0) {
2518
+ return [
2519
+ makeDiagnostic(
2520
+ setupDiagnostic.kind === "unsupported-custom-type-override" ? "UNSUPPORTED_CUSTOM_TYPE_OVERRIDE" : "SYNTHETIC_SETUP_FAILURE",
2521
+ setupDiagnostic.message,
2522
+ provenance
2523
+ )
2524
+ ];
2525
+ }
2506
2526
  const expectedLabel = definition.valueKind === null ? "compatible argument" : capabilityLabel(definition.valueKind);
2507
2527
  return [
2508
2528
  makeDiagnostic(
@@ -2666,7 +2686,7 @@ function parseTSDocTags(node, file = "", options) {
2666
2686
  options
2667
2687
  );
2668
2688
  if (compilerDiagnostics.length > 0) {
2669
- diagnostics.push(...compilerDiagnostics);
2689
+ pushUniqueCompilerDiagnostics(diagnostics, compilerDiagnostics);
2670
2690
  continue;
2671
2691
  }
2672
2692
  const constraintNode = parseConstraintTagValue(
@@ -2753,7 +2773,7 @@ function parseTSDocTags(node, file = "", options) {
2753
2773
  options
2754
2774
  );
2755
2775
  if (compilerDiagnostics.length > 0) {
2756
- diagnostics.push(...compilerDiagnostics);
2776
+ pushUniqueCompilerDiagnostics(diagnostics, compilerDiagnostics);
2757
2777
  continue;
2758
2778
  }
2759
2779
  const constraintNode = parseConstraintTagValue(
@@ -2787,7 +2807,7 @@ function parseTSDocTags(node, file = "", options) {
2787
2807
  options
2788
2808
  );
2789
2809
  if (compilerDiagnostics.length > 0) {
2790
- diagnostics.push(...compilerDiagnostics);
2810
+ pushUniqueCompilerDiagnostics(diagnostics, compilerDiagnostics);
2791
2811
  continue;
2792
2812
  }
2793
2813
  const constraintNode = parseConstraintTagValue(
@@ -5244,29 +5264,35 @@ function analyzeNamedTypeToIR(filePath, typeName, extensionRegistry, metadataPol
5244
5264
  discriminatorOptions
5245
5265
  );
5246
5266
  }
5247
- function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensionRegistry, metadataPolicy, discriminatorOptions) {
5267
+ function analyzeNamedTypeToIRFromProgramContextDetailed(ctx, filePath, typeName, extensionRegistry, metadataPolicy, discriminatorOptions) {
5248
5268
  const analysisFilePath = path.resolve(filePath);
5249
5269
  const classDecl = findClassByName(ctx.sourceFile, typeName);
5250
5270
  if (classDecl !== null) {
5251
- return analyzeClassToIR(
5252
- classDecl,
5253
- ctx.checker,
5254
- analysisFilePath,
5255
- extensionRegistry,
5256
- metadataPolicy,
5257
- discriminatorOptions
5258
- );
5271
+ return {
5272
+ ok: true,
5273
+ analysis: analyzeClassToIR(
5274
+ classDecl,
5275
+ ctx.checker,
5276
+ analysisFilePath,
5277
+ extensionRegistry,
5278
+ metadataPolicy,
5279
+ discriminatorOptions
5280
+ )
5281
+ };
5259
5282
  }
5260
5283
  const interfaceDecl = findInterfaceByName(ctx.sourceFile, typeName);
5261
5284
  if (interfaceDecl !== null) {
5262
- return analyzeInterfaceToIR(
5263
- interfaceDecl,
5264
- ctx.checker,
5265
- analysisFilePath,
5266
- extensionRegistry,
5267
- metadataPolicy,
5268
- discriminatorOptions
5269
- );
5285
+ return {
5286
+ ok: true,
5287
+ analysis: analyzeInterfaceToIR(
5288
+ interfaceDecl,
5289
+ ctx.checker,
5290
+ analysisFilePath,
5291
+ extensionRegistry,
5292
+ metadataPolicy,
5293
+ discriminatorOptions
5294
+ )
5295
+ };
5270
5296
  }
5271
5297
  const typeAlias = findTypeAliasByName(ctx.sourceFile, typeName);
5272
5298
  if (typeAlias !== null) {
@@ -5279,11 +5305,20 @@ function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensi
5279
5305
  discriminatorOptions
5280
5306
  );
5281
5307
  if (result.ok) {
5282
- return result.analysis;
5308
+ return { ok: true, analysis: result.analysis };
5283
5309
  }
5284
5310
  const fallbackEligible = result.kind === "not-object-like" && isResolvableObjectLikeAliasTypeNode(typeAlias.type) && containsTypeReferenceInObjectLikeAlias(typeAlias.type);
5285
5311
  if (!fallbackEligible) {
5286
- throw new Error(result.error);
5312
+ return {
5313
+ ok: false,
5314
+ diagnostics: [
5315
+ makeProgramDiagnostic(
5316
+ result.kind === "duplicate-properties" ? "DUPLICATE_ROOT_PROPERTIES" : "UNSUPPORTED_ROOT_TYPE",
5317
+ result.error,
5318
+ makeNodeProvenance(typeAlias, analysisFilePath)
5319
+ )
5320
+ ]
5321
+ };
5287
5322
  }
5288
5323
  const duplicatePropertyNames = findFallbackAliasDuplicatePropertyNames(
5289
5324
  typeAlias.type,
@@ -5292,9 +5327,16 @@ function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensi
5292
5327
  if (duplicatePropertyNames.length > 0) {
5293
5328
  const sourceFile = typeAlias.getSourceFile();
5294
5329
  const { line } = sourceFile.getLineAndCharacterOfPosition(typeAlias.getStart());
5295
- throw new Error(
5296
- `Type alias "${typeAlias.name.text}" at line ${String(line + 1)} contains duplicate property names across object-like members: ${duplicatePropertyNames.join(", ")}`
5297
- );
5330
+ return {
5331
+ ok: false,
5332
+ diagnostics: [
5333
+ makeProgramDiagnostic(
5334
+ "DUPLICATE_ROOT_PROPERTIES",
5335
+ `Type alias "${typeAlias.name.text}" at line ${String(line + 1)} contains duplicate property names across object-like members: ${duplicatePropertyNames.join(", ")}`,
5336
+ makeNodeProvenance(typeAlias, analysisFilePath)
5337
+ )
5338
+ ]
5339
+ };
5298
5340
  }
5299
5341
  const rootInfo = analyzeDeclarationRootInfo(
5300
5342
  typeAlias,
@@ -5324,13 +5366,71 @@ function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensi
5324
5366
  diagnostics
5325
5367
  );
5326
5368
  if (fallbackAnalysis !== null) {
5327
- return fallbackAnalysis;
5369
+ return { ok: true, analysis: fallbackAnalysis };
5328
5370
  }
5329
- throw new Error(result.error);
5371
+ return {
5372
+ ok: false,
5373
+ diagnostics: [
5374
+ makeProgramDiagnostic(
5375
+ "UNSUPPORTED_ROOT_TYPE",
5376
+ result.error,
5377
+ makeNodeProvenance(typeAlias, analysisFilePath)
5378
+ )
5379
+ ]
5380
+ };
5330
5381
  }
5331
- throw new Error(
5332
- `Type "${typeName}" not found as a class, interface, or type alias in ${analysisFilePath}`
5382
+ return {
5383
+ ok: false,
5384
+ diagnostics: [
5385
+ makeProgramDiagnostic(
5386
+ "TYPE_NOT_FOUND",
5387
+ `Type "${typeName}" not found as a class, interface, or type alias in ${analysisFilePath}`,
5388
+ makeFileProvenance(analysisFilePath)
5389
+ )
5390
+ ]
5391
+ };
5392
+ }
5393
+ function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensionRegistry, metadataPolicy, discriminatorOptions) {
5394
+ const result = analyzeNamedTypeToIRFromProgramContextDetailed(
5395
+ ctx,
5396
+ filePath,
5397
+ typeName,
5398
+ extensionRegistry,
5399
+ metadataPolicy,
5400
+ discriminatorOptions
5333
5401
  );
5402
+ if (result.ok) {
5403
+ return result.analysis;
5404
+ }
5405
+ throw new Error(result.diagnostics.map((diagnostic) => diagnostic.message).join("\n"));
5406
+ }
5407
+ function makeProgramDiagnostic(code, message, primaryLocation) {
5408
+ return {
5409
+ code,
5410
+ message,
5411
+ severity: "error",
5412
+ primaryLocation,
5413
+ relatedLocations: []
5414
+ };
5415
+ }
5416
+ function makeNodeProvenance(node, filePath) {
5417
+ const sourceFile = node.getSourceFile();
5418
+ const position = sourceFile.getLineAndCharacterOfPosition(node.getStart());
5419
+ return {
5420
+ surface: "tsdoc",
5421
+ file: filePath,
5422
+ line: position.line + 1,
5423
+ column: position.character,
5424
+ length: node.getWidth()
5425
+ };
5426
+ }
5427
+ function makeFileProvenance(filePath) {
5428
+ return {
5429
+ surface: "tsdoc",
5430
+ file: filePath,
5431
+ line: 1,
5432
+ column: 0
5433
+ };
5334
5434
  }
5335
5435
  var init_program = __esm({
5336
5436
  "src/analyzer/program.ts"() {
@@ -5428,13 +5528,27 @@ var init_validate = __esm({
5428
5528
  });
5429
5529
 
5430
5530
  // src/generators/class-schema.ts
5431
- import "typescript";
5531
+ import * as ts5 from "typescript";
5432
5532
  function generateClassSchemas(analysis, source, options) {
5433
- const errorDiagnostics = analysis.diagnostics?.filter(
5533
+ const result = generateClassSchemasDetailed(analysis, source, options);
5534
+ if (!result.ok || result.jsonSchema === void 0 || result.uiSchema === void 0) {
5535
+ throw new Error(formatValidationError(result.diagnostics));
5536
+ }
5537
+ return {
5538
+ jsonSchema: result.jsonSchema,
5539
+ uiSchema: result.uiSchema
5540
+ };
5541
+ }
5542
+ function generateClassSchemasDetailed(analysis, source, options) {
5543
+ const analysisDiagnostics = analysis.diagnostics ?? [];
5544
+ const errorDiagnostics = analysisDiagnostics.filter(
5434
5545
  (diagnostic) => diagnostic.severity === "error"
5435
5546
  );
5436
- if (errorDiagnostics !== void 0 && errorDiagnostics.length > 0) {
5437
- throw new Error(formatValidationError(errorDiagnostics));
5547
+ if (errorDiagnostics.length > 0) {
5548
+ return {
5549
+ ok: false,
5550
+ diagnostics: analysisDiagnostics
5551
+ };
5438
5552
  }
5439
5553
  const ir = canonicalizeTSDoc(
5440
5554
  analysis,
@@ -5448,9 +5562,14 @@ function generateClassSchemas(analysis, source, options) {
5448
5562
  ...options?.vendorPrefix !== void 0 && { vendorPrefix: options.vendorPrefix }
5449
5563
  });
5450
5564
  if (!validationResult.valid) {
5451
- throw new Error(formatValidationError(validationResult.diagnostics));
5565
+ return {
5566
+ ok: false,
5567
+ diagnostics: [...analysisDiagnostics, ...validationResult.diagnostics]
5568
+ };
5452
5569
  }
5453
5570
  return {
5571
+ ok: true,
5572
+ diagnostics: [...analysisDiagnostics, ...validationResult.diagnostics],
5454
5573
  jsonSchema: generateJsonSchemaFromIR(ir, options),
5455
5574
  uiSchema: generateUiSchemaFromIR(ir)
5456
5575
  };
@@ -5492,25 +5611,127 @@ function generateSchemasFromClass(options) {
5492
5611
  );
5493
5612
  }
5494
5613
  function generateSchemas(options) {
5495
- const ctx = createProgramContext(options.filePath);
5614
+ const result = generateSchemasDetailedInternal(options);
5615
+ if (options.errorReporting === "diagnostics") {
5616
+ return result;
5617
+ }
5618
+ if (!result.ok || result.jsonSchema === void 0 || result.uiSchema === void 0) {
5619
+ throw new Error(formatValidationError(result.diagnostics));
5620
+ }
5621
+ return {
5622
+ jsonSchema: result.jsonSchema,
5623
+ uiSchema: result.uiSchema
5624
+ };
5625
+ }
5626
+ function generateSchemasFromProgram(options) {
5627
+ const result = generateSchemasFromProgramDetailedInternal(options);
5628
+ if (options.errorReporting === "diagnostics") {
5629
+ return result;
5630
+ }
5631
+ if (!result.ok || result.jsonSchema === void 0 || result.uiSchema === void 0) {
5632
+ throw new Error(formatValidationError(result.diagnostics));
5633
+ }
5634
+ return {
5635
+ jsonSchema: result.jsonSchema,
5636
+ uiSchema: result.uiSchema
5637
+ };
5638
+ }
5639
+ function generateSchemasDetailed(options) {
5640
+ return generateSchemas({
5641
+ ...options,
5642
+ errorReporting: "diagnostics"
5643
+ });
5644
+ }
5645
+ function generateSchemasDetailedInternal(options) {
5646
+ let ctx;
5647
+ try {
5648
+ ctx = createProgramContext(options.filePath);
5649
+ } catch (error) {
5650
+ return {
5651
+ ok: false,
5652
+ diagnostics: [createProgramContextFailureDiagnostic(options.filePath, error)]
5653
+ };
5654
+ }
5655
+ return generateSchemasFromDetailedProgramContext(ctx, options.filePath, options.typeName, options);
5656
+ }
5657
+ function generateSchemasFromProgramDetailed(options) {
5496
5658
  return generateSchemasFromProgram({
5497
5659
  ...options,
5498
- program: ctx.program
5660
+ errorReporting: "diagnostics"
5499
5661
  });
5500
5662
  }
5501
- function generateSchemasFromProgram(options) {
5502
- const ctx = createProgramContextFromProgram(options.program, options.filePath);
5503
- const analysis = analyzeNamedTypeToIRFromProgramContext(
5663
+ function generateSchemasFromProgramDetailedInternal(options) {
5664
+ let ctx;
5665
+ try {
5666
+ ctx = createProgramContextFromProgram(options.program, options.filePath);
5667
+ } catch (error) {
5668
+ return {
5669
+ ok: false,
5670
+ diagnostics: [createProgramContextFailureDiagnostic(options.filePath, error)]
5671
+ };
5672
+ }
5673
+ return generateSchemasFromDetailedProgramContext(ctx, options.filePath, options.typeName, options);
5674
+ }
5675
+ function generateSchemasBatch(options) {
5676
+ const contextCache = /* @__PURE__ */ new Map();
5677
+ return options.targets.map((target) => {
5678
+ let ctx;
5679
+ try {
5680
+ const cacheKey = ts5.sys.useCaseSensitiveFileNames ? target.filePath : target.filePath.toLowerCase();
5681
+ const cachedContext = contextCache.get(cacheKey);
5682
+ if (cachedContext === void 0) {
5683
+ ctx = createProgramContext(target.filePath);
5684
+ contextCache.set(cacheKey, ctx);
5685
+ } else {
5686
+ ctx = cachedContext;
5687
+ }
5688
+ } catch (error) {
5689
+ return withTarget(target, {
5690
+ ok: false,
5691
+ diagnostics: [createProgramContextFailureDiagnostic(target.filePath, error)]
5692
+ });
5693
+ }
5694
+ return withTarget(
5695
+ target,
5696
+ generateSchemasFromDetailedProgramContext(ctx, target.filePath, target.typeName, options)
5697
+ );
5698
+ });
5699
+ }
5700
+ function generateSchemasBatchFromProgram(options) {
5701
+ return options.targets.map((target) => {
5702
+ let ctx;
5703
+ try {
5704
+ ctx = createProgramContextFromProgram(options.program, target.filePath);
5705
+ } catch (error) {
5706
+ return withTarget(target, {
5707
+ ok: false,
5708
+ diagnostics: [createProgramContextFailureDiagnostic(target.filePath, error)]
5709
+ });
5710
+ }
5711
+ return withTarget(
5712
+ target,
5713
+ generateSchemasFromDetailedProgramContext(ctx, target.filePath, target.typeName, options)
5714
+ );
5715
+ });
5716
+ }
5717
+ function generateSchemasFromDetailedProgramContext(ctx, filePath, typeName, options) {
5718
+ const analysisResult = analyzeNamedTypeToIRFromProgramContextDetailed(
5504
5719
  ctx,
5505
- options.filePath,
5506
- options.typeName,
5720
+ filePath,
5721
+ typeName,
5507
5722
  options.extensionRegistry,
5508
5723
  options.metadata,
5509
5724
  options.discriminator
5510
5725
  );
5511
- return generateClassSchemas(
5512
- analysis,
5513
- { file: options.filePath },
5726
+ if (!analysisResult.ok) {
5727
+ return {
5728
+ ok: false,
5729
+ diagnostics: analysisResult.diagnostics
5730
+ };
5731
+ }
5732
+ return generateClassSchemasDetailed(
5733
+ analysisResult.analysis,
5734
+ { file: filePath },
5514
5735
  {
5515
5736
  extensionRegistry: options.extensionRegistry,
5516
5737
  metadata: options.metadata,
@@ -5518,6 +5739,27 @@ function generateSchemasFromProgram(options) {
5518
5739
  }
5519
5740
  );
5520
5741
  }
5742
+ function withTarget(target, result) {
5743
+ return {
5744
+ filePath: target.filePath,
5745
+ typeName: target.typeName,
5746
+ ...result
5747
+ };
5748
+ }
5749
+ function createProgramContextFailureDiagnostic(filePath, error) {
5750
+ return {
5751
+ code: "PROGRAM_CONTEXT_FAILURE",
5752
+ message: error instanceof Error ? error.message : String(error),
5753
+ severity: "error",
5754
+ primaryLocation: {
5755
+ surface: "tsdoc",
5756
+ file: filePath,
5757
+ line: 1,
5758
+ column: 0
5759
+ },
5760
+ relatedLocations: []
5761
+ };
5762
+ }
5521
5763
  var init_class_schema = __esm({
5522
5764
  "src/generators/class-schema.ts"() {
5523
5765
  "use strict";
@@ -5572,8 +5814,11 @@ var init_static_build = __esm({
5572
5814
  // src/generators/discovered-schema.ts
5573
5815
  import * as ts7 from "typescript";
5574
5816
  import { IR_VERSION as IR_VERSION3 } from "@formspec/core/internals";
5575
- function toDiscoveredTypeSchemas(result) {
5576
- return result;
5817
+ function toDiscoveredTypeSchemas(result, resolvedMetadata) {
5818
+ return {
5819
+ ...result,
5820
+ ...resolvedMetadata !== void 0 && { resolvedMetadata }
5821
+ };
5577
5822
  }
5578
5823
  function isNamedTypeDeclaration(declaration) {
5579
5824
  return ts7.isClassDeclaration(declaration) || ts7.isInterfaceDeclaration(declaration) || ts7.isTypeAliasDeclaration(declaration);
@@ -5721,7 +5966,8 @@ function generateSchemasFromAnalysis(analysis, filePath, options) {
5721
5966
  metadata: options?.metadata,
5722
5967
  vendorPrefix: options?.vendorPrefix
5723
5968
  }
5724
- )
5969
+ ),
5970
+ analysis.metadata
5725
5971
  );
5726
5972
  }
5727
5973
  function generateSchemasFromResolvedType(options, skipNamedDeclaration = false, rootOverride) {
@@ -5779,7 +6025,8 @@ function generateSchemasFromResolvedType(options, skipNamedDeclaration = false,
5779
6025
  }
5780
6026
  return {
5781
6027
  jsonSchema: toStandaloneJsonSchema(root, typeRegistry, options),
5782
- uiSchema: null
6028
+ uiSchema: null,
6029
+ ...root.metadata !== void 0 && { resolvedMetadata: root.metadata }
5783
6030
  };
5784
6031
  }
5785
6032
  function generateSchemasFromDeclaration(options) {
@@ -6119,10 +6366,14 @@ __export(index_exports, {
6119
6366
  createStaticBuildContextFromProgram: () => createStaticBuildContextFromProgram,
6120
6367
  generateJsonSchema: () => generateJsonSchema,
6121
6368
  generateSchemas: () => generateSchemas,
6369
+ generateSchemasBatch: () => generateSchemasBatch,
6370
+ generateSchemasBatchFromProgram: () => generateSchemasBatchFromProgram,
6371
+ generateSchemasDetailed: () => generateSchemasDetailed,
6122
6372
  generateSchemasFromClass: () => generateSchemasFromClass,
6123
6373
  generateSchemasFromDeclaration: () => generateSchemasFromDeclaration,
6124
6374
  generateSchemasFromParameter: () => generateSchemasFromParameter,
6125
6375
  generateSchemasFromProgram: () => generateSchemasFromProgram,
6376
+ generateSchemasFromProgramDetailed: () => generateSchemasFromProgramDetailed,
6126
6377
  generateSchemasFromReturnType: () => generateSchemasFromReturnType,
6127
6378
  generateSchemasFromType: () => generateSchemasFromType,
6128
6379
  generateUiSchema: () => generateUiSchema,
@@ -6165,6 +6416,9 @@ var init_index = __esm({
6165
6416
  init_generator();
6166
6417
  init_generator2();
6167
6418
  init_class_schema();
6419
+ init_class_schema();
6420
+ init_class_schema();
6421
+ init_class_schema();
6168
6422
  init_static_build();
6169
6423
  init_discovered_schema();
6170
6424
  init_mixed_authoring();