@formspec/build 0.1.0-alpha.38 → 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/index.cjs CHANGED
@@ -37,10 +37,14 @@ __export(index_exports, {
37
37
  createStaticBuildContextFromProgram: () => createStaticBuildContextFromProgram,
38
38
  generateJsonSchema: () => generateJsonSchema,
39
39
  generateSchemas: () => generateSchemas,
40
+ generateSchemasBatch: () => generateSchemasBatch,
41
+ generateSchemasBatchFromProgram: () => generateSchemasBatchFromProgram,
42
+ generateSchemasDetailed: () => generateSchemasDetailed,
40
43
  generateSchemasFromClass: () => generateSchemasFromClass,
41
44
  generateSchemasFromDeclaration: () => generateSchemasFromDeclaration,
42
45
  generateSchemasFromParameter: () => generateSchemasFromParameter,
43
46
  generateSchemasFromProgram: () => generateSchemasFromProgram,
47
+ generateSchemasFromProgramDetailed: () => generateSchemasFromProgramDetailed,
44
48
  generateSchemasFromReturnType: () => generateSchemasFromReturnType,
45
49
  generateSchemasFromType: () => generateSchemasFromType,
46
50
  generateUiSchema: () => generateUiSchema,
@@ -2019,7 +2023,7 @@ var jsonSchema7Schema = import_zod3.z.lazy(
2019
2023
  );
2020
2024
 
2021
2025
  // src/generators/class-schema.ts
2022
- var ts5 = require("typescript");
2026
+ var ts5 = __toESM(require("typescript"), 1);
2023
2027
 
2024
2028
  // src/analyzer/program.ts
2025
2029
  var ts4 = __toESM(require("typescript"), 1);
@@ -5162,29 +5166,35 @@ function analyzeNamedTypeToIR(filePath, typeName, extensionRegistry, metadataPol
5162
5166
  discriminatorOptions
5163
5167
  );
5164
5168
  }
5165
- function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensionRegistry, metadataPolicy, discriminatorOptions) {
5169
+ function analyzeNamedTypeToIRFromProgramContextDetailed(ctx, filePath, typeName, extensionRegistry, metadataPolicy, discriminatorOptions) {
5166
5170
  const analysisFilePath = path.resolve(filePath);
5167
5171
  const classDecl = findClassByName(ctx.sourceFile, typeName);
5168
5172
  if (classDecl !== null) {
5169
- return analyzeClassToIR(
5170
- classDecl,
5171
- ctx.checker,
5172
- analysisFilePath,
5173
- extensionRegistry,
5174
- metadataPolicy,
5175
- discriminatorOptions
5176
- );
5173
+ return {
5174
+ ok: true,
5175
+ analysis: analyzeClassToIR(
5176
+ classDecl,
5177
+ ctx.checker,
5178
+ analysisFilePath,
5179
+ extensionRegistry,
5180
+ metadataPolicy,
5181
+ discriminatorOptions
5182
+ )
5183
+ };
5177
5184
  }
5178
5185
  const interfaceDecl = findInterfaceByName(ctx.sourceFile, typeName);
5179
5186
  if (interfaceDecl !== null) {
5180
- return analyzeInterfaceToIR(
5181
- interfaceDecl,
5182
- ctx.checker,
5183
- analysisFilePath,
5184
- extensionRegistry,
5185
- metadataPolicy,
5186
- discriminatorOptions
5187
- );
5187
+ return {
5188
+ ok: true,
5189
+ analysis: analyzeInterfaceToIR(
5190
+ interfaceDecl,
5191
+ ctx.checker,
5192
+ analysisFilePath,
5193
+ extensionRegistry,
5194
+ metadataPolicy,
5195
+ discriminatorOptions
5196
+ )
5197
+ };
5188
5198
  }
5189
5199
  const typeAlias = findTypeAliasByName(ctx.sourceFile, typeName);
5190
5200
  if (typeAlias !== null) {
@@ -5197,11 +5207,20 @@ function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensi
5197
5207
  discriminatorOptions
5198
5208
  );
5199
5209
  if (result.ok) {
5200
- return result.analysis;
5210
+ return { ok: true, analysis: result.analysis };
5201
5211
  }
5202
5212
  const fallbackEligible = result.kind === "not-object-like" && isResolvableObjectLikeAliasTypeNode(typeAlias.type) && containsTypeReferenceInObjectLikeAlias(typeAlias.type);
5203
5213
  if (!fallbackEligible) {
5204
- throw new Error(result.error);
5214
+ return {
5215
+ ok: false,
5216
+ diagnostics: [
5217
+ makeProgramDiagnostic(
5218
+ result.kind === "duplicate-properties" ? "DUPLICATE_ROOT_PROPERTIES" : "UNSUPPORTED_ROOT_TYPE",
5219
+ result.error,
5220
+ makeNodeProvenance(typeAlias, analysisFilePath)
5221
+ )
5222
+ ]
5223
+ };
5205
5224
  }
5206
5225
  const duplicatePropertyNames = findFallbackAliasDuplicatePropertyNames(
5207
5226
  typeAlias.type,
@@ -5210,9 +5229,16 @@ function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensi
5210
5229
  if (duplicatePropertyNames.length > 0) {
5211
5230
  const sourceFile = typeAlias.getSourceFile();
5212
5231
  const { line } = sourceFile.getLineAndCharacterOfPosition(typeAlias.getStart());
5213
- throw new Error(
5214
- `Type alias "${typeAlias.name.text}" at line ${String(line + 1)} contains duplicate property names across object-like members: ${duplicatePropertyNames.join(", ")}`
5215
- );
5232
+ return {
5233
+ ok: false,
5234
+ diagnostics: [
5235
+ makeProgramDiagnostic(
5236
+ "DUPLICATE_ROOT_PROPERTIES",
5237
+ `Type alias "${typeAlias.name.text}" at line ${String(line + 1)} contains duplicate property names across object-like members: ${duplicatePropertyNames.join(", ")}`,
5238
+ makeNodeProvenance(typeAlias, analysisFilePath)
5239
+ )
5240
+ ]
5241
+ };
5216
5242
  }
5217
5243
  const rootInfo = analyzeDeclarationRootInfo(
5218
5244
  typeAlias,
@@ -5242,13 +5268,71 @@ function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensi
5242
5268
  diagnostics
5243
5269
  );
5244
5270
  if (fallbackAnalysis !== null) {
5245
- return fallbackAnalysis;
5271
+ return { ok: true, analysis: fallbackAnalysis };
5246
5272
  }
5247
- throw new Error(result.error);
5273
+ return {
5274
+ ok: false,
5275
+ diagnostics: [
5276
+ makeProgramDiagnostic(
5277
+ "UNSUPPORTED_ROOT_TYPE",
5278
+ result.error,
5279
+ makeNodeProvenance(typeAlias, analysisFilePath)
5280
+ )
5281
+ ]
5282
+ };
5248
5283
  }
5249
- throw new Error(
5250
- `Type "${typeName}" not found as a class, interface, or type alias in ${analysisFilePath}`
5284
+ return {
5285
+ ok: false,
5286
+ diagnostics: [
5287
+ makeProgramDiagnostic(
5288
+ "TYPE_NOT_FOUND",
5289
+ `Type "${typeName}" not found as a class, interface, or type alias in ${analysisFilePath}`,
5290
+ makeFileProvenance(analysisFilePath)
5291
+ )
5292
+ ]
5293
+ };
5294
+ }
5295
+ function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensionRegistry, metadataPolicy, discriminatorOptions) {
5296
+ const result = analyzeNamedTypeToIRFromProgramContextDetailed(
5297
+ ctx,
5298
+ filePath,
5299
+ typeName,
5300
+ extensionRegistry,
5301
+ metadataPolicy,
5302
+ discriminatorOptions
5251
5303
  );
5304
+ if (result.ok) {
5305
+ return result.analysis;
5306
+ }
5307
+ throw new Error(result.diagnostics.map((diagnostic) => diagnostic.message).join("\n"));
5308
+ }
5309
+ function makeProgramDiagnostic(code, message, primaryLocation) {
5310
+ return {
5311
+ code,
5312
+ message,
5313
+ severity: "error",
5314
+ primaryLocation,
5315
+ relatedLocations: []
5316
+ };
5317
+ }
5318
+ function makeNodeProvenance(node, filePath) {
5319
+ const sourceFile = node.getSourceFile();
5320
+ const position = sourceFile.getLineAndCharacterOfPosition(node.getStart());
5321
+ return {
5322
+ surface: "tsdoc",
5323
+ file: filePath,
5324
+ line: position.line + 1,
5325
+ column: position.character,
5326
+ length: node.getWidth()
5327
+ };
5328
+ }
5329
+ function makeFileProvenance(filePath) {
5330
+ return {
5331
+ surface: "tsdoc",
5332
+ file: filePath,
5333
+ line: 1,
5334
+ column: 0
5335
+ };
5252
5336
  }
5253
5337
 
5254
5338
  // src/validate/constraint-validator.ts
@@ -5326,11 +5410,25 @@ function validateIR(ir, options) {
5326
5410
 
5327
5411
  // src/generators/class-schema.ts
5328
5412
  function generateClassSchemas(analysis, source, options) {
5329
- const errorDiagnostics = analysis.diagnostics?.filter(
5413
+ const result = generateClassSchemasDetailed(analysis, source, options);
5414
+ if (!result.ok || result.jsonSchema === void 0 || result.uiSchema === void 0) {
5415
+ throw new Error(formatValidationError(result.diagnostics));
5416
+ }
5417
+ return {
5418
+ jsonSchema: result.jsonSchema,
5419
+ uiSchema: result.uiSchema
5420
+ };
5421
+ }
5422
+ function generateClassSchemasDetailed(analysis, source, options) {
5423
+ const analysisDiagnostics = analysis.diagnostics ?? [];
5424
+ const errorDiagnostics = analysisDiagnostics.filter(
5330
5425
  (diagnostic) => diagnostic.severity === "error"
5331
5426
  );
5332
- if (errorDiagnostics !== void 0 && errorDiagnostics.length > 0) {
5333
- throw new Error(formatValidationError(errorDiagnostics));
5427
+ if (errorDiagnostics.length > 0) {
5428
+ return {
5429
+ ok: false,
5430
+ diagnostics: analysisDiagnostics
5431
+ };
5334
5432
  }
5335
5433
  const ir = canonicalizeTSDoc(
5336
5434
  analysis,
@@ -5344,9 +5442,14 @@ function generateClassSchemas(analysis, source, options) {
5344
5442
  ...options?.vendorPrefix !== void 0 && { vendorPrefix: options.vendorPrefix }
5345
5443
  });
5346
5444
  if (!validationResult.valid) {
5347
- throw new Error(formatValidationError(validationResult.diagnostics));
5445
+ return {
5446
+ ok: false,
5447
+ diagnostics: [...analysisDiagnostics, ...validationResult.diagnostics]
5448
+ };
5348
5449
  }
5349
5450
  return {
5451
+ ok: true,
5452
+ diagnostics: [...analysisDiagnostics, ...validationResult.diagnostics],
5350
5453
  jsonSchema: generateJsonSchemaFromIR(ir, options),
5351
5454
  uiSchema: generateUiSchemaFromIR(ir)
5352
5455
  };
@@ -5388,25 +5491,127 @@ function generateSchemasFromClass(options) {
5388
5491
  );
5389
5492
  }
5390
5493
  function generateSchemas(options) {
5391
- const ctx = createProgramContext(options.filePath);
5494
+ const result = generateSchemasDetailedInternal(options);
5495
+ if (options.errorReporting === "diagnostics") {
5496
+ return result;
5497
+ }
5498
+ if (!result.ok || result.jsonSchema === void 0 || result.uiSchema === void 0) {
5499
+ throw new Error(formatValidationError(result.diagnostics));
5500
+ }
5501
+ return {
5502
+ jsonSchema: result.jsonSchema,
5503
+ uiSchema: result.uiSchema
5504
+ };
5505
+ }
5506
+ function generateSchemasFromProgram(options) {
5507
+ const result = generateSchemasFromProgramDetailedInternal(options);
5508
+ if (options.errorReporting === "diagnostics") {
5509
+ return result;
5510
+ }
5511
+ if (!result.ok || result.jsonSchema === void 0 || result.uiSchema === void 0) {
5512
+ throw new Error(formatValidationError(result.diagnostics));
5513
+ }
5514
+ return {
5515
+ jsonSchema: result.jsonSchema,
5516
+ uiSchema: result.uiSchema
5517
+ };
5518
+ }
5519
+ function generateSchemasDetailed(options) {
5520
+ return generateSchemas({
5521
+ ...options,
5522
+ errorReporting: "diagnostics"
5523
+ });
5524
+ }
5525
+ function generateSchemasDetailedInternal(options) {
5526
+ let ctx;
5527
+ try {
5528
+ ctx = createProgramContext(options.filePath);
5529
+ } catch (error) {
5530
+ return {
5531
+ ok: false,
5532
+ diagnostics: [createProgramContextFailureDiagnostic(options.filePath, error)]
5533
+ };
5534
+ }
5535
+ return generateSchemasFromDetailedProgramContext(ctx, options.filePath, options.typeName, options);
5536
+ }
5537
+ function generateSchemasFromProgramDetailed(options) {
5392
5538
  return generateSchemasFromProgram({
5393
5539
  ...options,
5394
- program: ctx.program
5540
+ errorReporting: "diagnostics"
5395
5541
  });
5396
5542
  }
5397
- function generateSchemasFromProgram(options) {
5398
- const ctx = createProgramContextFromProgram(options.program, options.filePath);
5399
- const analysis = analyzeNamedTypeToIRFromProgramContext(
5543
+ function generateSchemasFromProgramDetailedInternal(options) {
5544
+ let ctx;
5545
+ try {
5546
+ ctx = createProgramContextFromProgram(options.program, options.filePath);
5547
+ } catch (error) {
5548
+ return {
5549
+ ok: false,
5550
+ diagnostics: [createProgramContextFailureDiagnostic(options.filePath, error)]
5551
+ };
5552
+ }
5553
+ return generateSchemasFromDetailedProgramContext(ctx, options.filePath, options.typeName, options);
5554
+ }
5555
+ function generateSchemasBatch(options) {
5556
+ const contextCache = /* @__PURE__ */ new Map();
5557
+ return options.targets.map((target) => {
5558
+ let ctx;
5559
+ try {
5560
+ const cacheKey = ts5.sys.useCaseSensitiveFileNames ? target.filePath : target.filePath.toLowerCase();
5561
+ const cachedContext = contextCache.get(cacheKey);
5562
+ if (cachedContext === void 0) {
5563
+ ctx = createProgramContext(target.filePath);
5564
+ contextCache.set(cacheKey, ctx);
5565
+ } else {
5566
+ ctx = cachedContext;
5567
+ }
5568
+ } catch (error) {
5569
+ return withTarget(target, {
5570
+ ok: false,
5571
+ diagnostics: [createProgramContextFailureDiagnostic(target.filePath, error)]
5572
+ });
5573
+ }
5574
+ return withTarget(
5575
+ target,
5576
+ generateSchemasFromDetailedProgramContext(ctx, target.filePath, target.typeName, options)
5577
+ );
5578
+ });
5579
+ }
5580
+ function generateSchemasBatchFromProgram(options) {
5581
+ return options.targets.map((target) => {
5582
+ let ctx;
5583
+ try {
5584
+ ctx = createProgramContextFromProgram(options.program, target.filePath);
5585
+ } catch (error) {
5586
+ return withTarget(target, {
5587
+ ok: false,
5588
+ diagnostics: [createProgramContextFailureDiagnostic(target.filePath, error)]
5589
+ });
5590
+ }
5591
+ return withTarget(
5592
+ target,
5593
+ generateSchemasFromDetailedProgramContext(ctx, target.filePath, target.typeName, options)
5594
+ );
5595
+ });
5596
+ }
5597
+ function generateSchemasFromDetailedProgramContext(ctx, filePath, typeName, options) {
5598
+ const analysisResult = analyzeNamedTypeToIRFromProgramContextDetailed(
5400
5599
  ctx,
5401
- options.filePath,
5402
- options.typeName,
5600
+ filePath,
5601
+ typeName,
5403
5602
  options.extensionRegistry,
5404
5603
  options.metadata,
5405
5604
  options.discriminator
5406
5605
  );
5407
- return generateClassSchemas(
5408
- analysis,
5409
- { file: options.filePath },
5606
+ if (!analysisResult.ok) {
5607
+ return {
5608
+ ok: false,
5609
+ diagnostics: analysisResult.diagnostics
5610
+ };
5611
+ }
5612
+ return generateClassSchemasDetailed(
5613
+ analysisResult.analysis,
5614
+ { file: filePath },
5410
5615
  {
5411
5616
  extensionRegistry: options.extensionRegistry,
5412
5617
  metadata: options.metadata,
@@ -5414,6 +5619,27 @@ function generateSchemasFromProgram(options) {
5414
5619
  }
5415
5620
  );
5416
5621
  }
5622
+ function withTarget(target, result) {
5623
+ return {
5624
+ filePath: target.filePath,
5625
+ typeName: target.typeName,
5626
+ ...result
5627
+ };
5628
+ }
5629
+ function createProgramContextFailureDiagnostic(filePath, error) {
5630
+ return {
5631
+ code: "PROGRAM_CONTEXT_FAILURE",
5632
+ message: error instanceof Error ? error.message : String(error),
5633
+ severity: "error",
5634
+ primaryLocation: {
5635
+ surface: "tsdoc",
5636
+ file: filePath,
5637
+ line: 1,
5638
+ column: 0
5639
+ },
5640
+ relatedLocations: []
5641
+ };
5642
+ }
5417
5643
 
5418
5644
  // src/static-build.ts
5419
5645
  var ts6 = __toESM(require("typescript"), 1);
@@ -5451,8 +5677,11 @@ function resolveModuleExportDeclaration(context, exportName = "default") {
5451
5677
  // src/generators/discovered-schema.ts
5452
5678
  var ts7 = __toESM(require("typescript"), 1);
5453
5679
  var import_internals6 = require("@formspec/core/internals");
5454
- function toDiscoveredTypeSchemas(result) {
5455
- return result;
5680
+ function toDiscoveredTypeSchemas(result, resolvedMetadata) {
5681
+ return {
5682
+ ...result,
5683
+ ...resolvedMetadata !== void 0 && { resolvedMetadata }
5684
+ };
5456
5685
  }
5457
5686
  function isNamedTypeDeclaration(declaration) {
5458
5687
  return ts7.isClassDeclaration(declaration) || ts7.isInterfaceDeclaration(declaration) || ts7.isTypeAliasDeclaration(declaration);
@@ -5600,7 +5829,8 @@ function generateSchemasFromAnalysis(analysis, filePath, options) {
5600
5829
  metadata: options?.metadata,
5601
5830
  vendorPrefix: options?.vendorPrefix
5602
5831
  }
5603
- )
5832
+ ),
5833
+ analysis.metadata
5604
5834
  );
5605
5835
  }
5606
5836
  function generateSchemasFromResolvedType(options, skipNamedDeclaration = false, rootOverride) {
@@ -5658,7 +5888,8 @@ function generateSchemasFromResolvedType(options, skipNamedDeclaration = false,
5658
5888
  }
5659
5889
  return {
5660
5890
  jsonSchema: toStandaloneJsonSchema(root, typeRegistry, options),
5661
- uiSchema: null
5891
+ uiSchema: null,
5892
+ ...root.metadata !== void 0 && { resolvedMetadata: root.metadata }
5662
5893
  };
5663
5894
  }
5664
5895
  function generateSchemasFromDeclaration(options) {
@@ -5998,10 +6229,14 @@ function writeSchemas(form, options) {
5998
6229
  createStaticBuildContextFromProgram,
5999
6230
  generateJsonSchema,
6000
6231
  generateSchemas,
6232
+ generateSchemasBatch,
6233
+ generateSchemasBatchFromProgram,
6234
+ generateSchemasDetailed,
6001
6235
  generateSchemasFromClass,
6002
6236
  generateSchemasFromDeclaration,
6003
6237
  generateSchemasFromParameter,
6004
6238
  generateSchemasFromProgram,
6239
+ generateSchemasFromProgramDetailed,
6005
6240
  generateSchemasFromReturnType,
6006
6241
  generateSchemasFromType,
6007
6242
  generateUiSchema,