@formspec/build 0.1.0-alpha.31 → 0.1.0-alpha.32

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
@@ -2992,6 +2992,27 @@ function resolveNodeMetadata(metadataPolicy, declarationKind, logicalName, node,
2992
2992
  makeMetadataContext("tsdoc", declarationKind, logicalName, buildContext)
2993
2993
  );
2994
2994
  }
2995
+ function analyzeDeclarationRootInfo(declaration, checker, file = "", extensionRegistry, metadataPolicy) {
2996
+ const normalizedMetadataPolicy = normalizeMetadataPolicy(metadataPolicy);
2997
+ const declarationType = checker.getTypeAtLocation(declaration);
2998
+ const logicalName = ts3.isClassDeclaration(declaration) ? declaration.name?.text ?? "AnonymousClass" : declaration.name.text;
2999
+ const docResult = extractJSDocParseResult(
3000
+ declaration,
3001
+ file,
3002
+ makeParseOptions(extensionRegistry, void 0, checker, declarationType, declarationType)
3003
+ );
3004
+ const metadata = resolveNodeMetadata(normalizedMetadataPolicy, "type", logicalName, declaration, {
3005
+ checker,
3006
+ declaration,
3007
+ subjectType: declarationType,
3008
+ hostType: declarationType
3009
+ });
3010
+ return {
3011
+ ...metadata !== void 0 && { metadata },
3012
+ annotations: docResult.annotations,
3013
+ diagnostics: docResult.diagnostics
3014
+ };
3015
+ }
2995
3016
  function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, metadataPolicy) {
2996
3017
  const normalizedMetadataPolicy = normalizeMetadataPolicy(metadataPolicy);
2997
3018
  const name = classDecl.name?.text ?? "AnonymousClass";
@@ -3406,10 +3427,7 @@ function resolveLiteralDiscriminatorPropertyValue(boundType, fieldName, checker,
3406
3427
  if (resolvedAnchorNode === null) {
3407
3428
  return void 0;
3408
3429
  }
3409
- const propertyType = checker.getTypeOfSymbolAtLocation(
3410
- propertySymbol,
3411
- resolvedAnchorNode
3412
- );
3430
+ const propertyType = checker.getTypeOfSymbolAtLocation(propertySymbol, resolvedAnchorNode);
3413
3431
  if (propertyType.isStringLiteral()) {
3414
3432
  return propertyType.value;
3415
3433
  }
@@ -4368,14 +4386,39 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
4368
4386
  collectedDiagnostics
4369
4387
  );
4370
4388
  const fieldNodeInfo = fieldInfoMap?.get(prop.name);
4389
+ const inlineFieldNodeInfo = fieldNodeInfo === void 0 ? ts3.isPropertySignature(declaration) ? analyzeInterfacePropertyToIR(
4390
+ declaration,
4391
+ checker,
4392
+ file,
4393
+ typeRegistry,
4394
+ visiting,
4395
+ collectedDiagnostics,
4396
+ type,
4397
+ metadataPolicy,
4398
+ extensionRegistry
4399
+ ) : ts3.isPropertyDeclaration(declaration) ? analyzeFieldToIR(
4400
+ declaration,
4401
+ checker,
4402
+ file,
4403
+ typeRegistry,
4404
+ visiting,
4405
+ collectedDiagnostics,
4406
+ type,
4407
+ metadataPolicy,
4408
+ extensionRegistry
4409
+ ) : null : null;
4410
+ const resolvedFieldNodeInfo = fieldNodeInfo ?? inlineFieldNodeInfo;
4411
+ const resolvedPropertyType = inlineFieldNodeInfo?.type ?? propTypeNode;
4371
4412
  properties.push({
4372
4413
  name: prop.name,
4373
- ...fieldNodeInfo?.metadata !== void 0 && { metadata: fieldNodeInfo.metadata },
4374
- type: propTypeNode,
4414
+ ...resolvedFieldNodeInfo?.metadata !== void 0 && {
4415
+ metadata: resolvedFieldNodeInfo.metadata
4416
+ },
4417
+ type: resolvedPropertyType,
4375
4418
  optional,
4376
- constraints: fieldNodeInfo?.constraints ?? [],
4377
- annotations: fieldNodeInfo?.annotations ?? [],
4378
- provenance: fieldNodeInfo?.provenance ?? provenanceForFile(file)
4419
+ constraints: resolvedFieldNodeInfo?.constraints ?? [],
4420
+ annotations: resolvedFieldNodeInfo?.annotations ?? [],
4421
+ provenance: resolvedFieldNodeInfo?.provenance ?? provenanceForFile(file)
4379
4422
  });
4380
4423
  }
4381
4424
  visiting.delete(type);
@@ -5020,6 +5063,360 @@ var init_class_schema = __esm({
5020
5063
  }
5021
5064
  });
5022
5065
 
5066
+ // src/static-build.ts
5067
+ import * as ts6 from "typescript";
5068
+ function toStaticBuildContext(context) {
5069
+ return context;
5070
+ }
5071
+ function createStaticBuildContext(filePath) {
5072
+ return toStaticBuildContext(createProgramContext(filePath));
5073
+ }
5074
+ function createStaticBuildContextFromProgram(program, filePath) {
5075
+ return toStaticBuildContext(createProgramContextFromProgram(program, filePath));
5076
+ }
5077
+ function getModuleSymbol(context) {
5078
+ const sourceFileWithSymbol = context.sourceFile;
5079
+ return context.checker.getSymbolAtLocation(context.sourceFile) ?? sourceFileWithSymbol.symbol;
5080
+ }
5081
+ function isSchemaSourceDeclaration(declaration) {
5082
+ return ts6.isClassDeclaration(declaration) || ts6.isInterfaceDeclaration(declaration) || ts6.isTypeAliasDeclaration(declaration);
5083
+ }
5084
+ function resolveModuleExport(context, exportName = "default") {
5085
+ const moduleSymbol = getModuleSymbol(context);
5086
+ if (moduleSymbol === void 0) {
5087
+ return null;
5088
+ }
5089
+ const exportSymbol = context.checker.getExportsOfModule(moduleSymbol).find((candidate) => candidate.name === exportName) ?? null;
5090
+ if (exportSymbol === null) {
5091
+ return null;
5092
+ }
5093
+ return exportSymbol.flags & ts6.SymbolFlags.Alias ? context.checker.getAliasedSymbol(exportSymbol) : exportSymbol;
5094
+ }
5095
+ function resolveModuleExportDeclaration(context, exportName = "default") {
5096
+ return resolveModuleExport(context, exportName)?.declarations?.find(isSchemaSourceDeclaration) ?? null;
5097
+ }
5098
+ var init_static_build = __esm({
5099
+ "src/static-build.ts"() {
5100
+ "use strict";
5101
+ init_program();
5102
+ }
5103
+ });
5104
+
5105
+ // src/generators/discovered-schema.ts
5106
+ import * as ts7 from "typescript";
5107
+ import { IR_VERSION as IR_VERSION3 } from "@formspec/core/internals";
5108
+ function toDiscoveredTypeSchemas(result) {
5109
+ return result;
5110
+ }
5111
+ function isNamedTypeDeclaration(declaration) {
5112
+ return ts7.isClassDeclaration(declaration) || ts7.isInterfaceDeclaration(declaration) || ts7.isTypeAliasDeclaration(declaration);
5113
+ }
5114
+ function hasConcreteTypeArguments(type, checker) {
5115
+ if ("aliasTypeArguments" in type && Array.isArray(type.aliasTypeArguments) && type.aliasTypeArguments.length > 0) {
5116
+ return true;
5117
+ }
5118
+ if ((type.flags & ts7.TypeFlags.Object) === 0) {
5119
+ return false;
5120
+ }
5121
+ const objectType = type;
5122
+ if ((objectType.objectFlags & ts7.ObjectFlags.Reference) === 0) {
5123
+ return false;
5124
+ }
5125
+ return checker.getTypeArguments(objectType).length > 0;
5126
+ }
5127
+ function getNamedTypeDeclaration2(type) {
5128
+ const symbol = type.getSymbol();
5129
+ if (symbol?.declarations !== void 0) {
5130
+ const declaration = symbol.declarations[0];
5131
+ if (declaration !== void 0 && isNamedTypeDeclaration(declaration)) {
5132
+ return declaration;
5133
+ }
5134
+ }
5135
+ const aliasDeclaration = type.aliasSymbol?.declarations?.find(ts7.isTypeAliasDeclaration);
5136
+ return aliasDeclaration;
5137
+ }
5138
+ function getFallbackName(sourceNode, fallback = "AnonymousType") {
5139
+ if (sourceNode !== void 0 && "name" in sourceNode) {
5140
+ const namedNode = sourceNode;
5141
+ if (namedNode.name !== void 0 && ts7.isIdentifier(namedNode.name)) {
5142
+ return namedNode.name.text;
5143
+ }
5144
+ }
5145
+ return fallback;
5146
+ }
5147
+ function createObjectRootAnalysis(name, properties, typeRegistry, metadata, annotations) {
5148
+ const fields = properties.map((property) => ({
5149
+ kind: "field",
5150
+ name: property.name,
5151
+ ...property.metadata !== void 0 && { metadata: property.metadata },
5152
+ type: property.type,
5153
+ required: !property.optional,
5154
+ constraints: property.constraints,
5155
+ annotations: property.annotations,
5156
+ provenance: property.provenance
5157
+ }));
5158
+ return {
5159
+ name,
5160
+ ...metadata !== void 0 && { metadata },
5161
+ fields,
5162
+ fieldLayouts: fields.map(() => ({})),
5163
+ typeRegistry,
5164
+ ...annotations !== void 0 && annotations.length > 0 && { annotations },
5165
+ instanceMethods: [],
5166
+ staticMethods: [],
5167
+ diagnostics: []
5168
+ };
5169
+ }
5170
+ function omitApiName(metadata) {
5171
+ if (metadata?.apiName === void 0) {
5172
+ return metadata;
5173
+ }
5174
+ const { apiName: _apiName, ...rest } = metadata;
5175
+ return Object.keys(rest).length > 0 ? rest : void 0;
5176
+ }
5177
+ function describeRootType(rootType, typeRegistry, fallbackName) {
5178
+ if (rootType.kind !== "reference") {
5179
+ return {
5180
+ name: fallbackName,
5181
+ type: rootType
5182
+ };
5183
+ }
5184
+ const definition = typeRegistry[rootType.name];
5185
+ if (definition === void 0) {
5186
+ return {
5187
+ name: rootType.name,
5188
+ type: rootType
5189
+ };
5190
+ }
5191
+ return {
5192
+ name: definition.name,
5193
+ ...definition.metadata !== void 0 && { metadata: definition.metadata },
5194
+ ...definition.annotations !== void 0 && definition.annotations.length > 0 && { annotations: definition.annotations },
5195
+ type: definition.type
5196
+ };
5197
+ }
5198
+ function toStandaloneJsonSchema(root, typeRegistry, options) {
5199
+ const syntheticFieldMetadata = omitApiName(root.metadata);
5200
+ const syntheticField = {
5201
+ kind: "field",
5202
+ name: "__result",
5203
+ ...syntheticFieldMetadata !== void 0 && { metadata: syntheticFieldMetadata },
5204
+ type: root.type,
5205
+ required: true,
5206
+ constraints: [],
5207
+ annotations: [...root.annotations ?? []],
5208
+ provenance: {
5209
+ surface: "tsdoc",
5210
+ file: "",
5211
+ line: 1,
5212
+ column: 0
5213
+ }
5214
+ };
5215
+ const schema = generateJsonSchemaFromIR(
5216
+ {
5217
+ kind: "form-ir",
5218
+ name: root.name,
5219
+ irVersion: IR_VERSION3,
5220
+ elements: [syntheticField],
5221
+ ...root.metadata !== void 0 && { metadata: root.metadata },
5222
+ ...root.annotations !== void 0 && root.annotations.length > 0 && { rootAnnotations: root.annotations },
5223
+ typeRegistry,
5224
+ provenance: syntheticField.provenance
5225
+ },
5226
+ {
5227
+ extensionRegistry: options?.extensionRegistry,
5228
+ vendorPrefix: options?.vendorPrefix
5229
+ }
5230
+ );
5231
+ const result = schema.properties?.["__result"];
5232
+ if (result === void 0) {
5233
+ throw new Error("FormSpec failed to extract the standalone schema root from the synthetic IR.");
5234
+ }
5235
+ if (schema.$defs === void 0 || Object.keys(schema.$defs).length === 0) {
5236
+ return {
5237
+ ...schema.$schema !== void 0 && { $schema: schema.$schema },
5238
+ ...result
5239
+ };
5240
+ }
5241
+ return {
5242
+ ...schema.$schema !== void 0 && { $schema: schema.$schema },
5243
+ ...result,
5244
+ $defs: schema.$defs
5245
+ };
5246
+ }
5247
+ function generateSchemasFromAnalysis(analysis, filePath, options) {
5248
+ return toDiscoveredTypeSchemas(
5249
+ generateClassSchemas(
5250
+ analysis,
5251
+ { file: filePath },
5252
+ {
5253
+ extensionRegistry: options?.extensionRegistry,
5254
+ metadata: options?.metadata,
5255
+ vendorPrefix: options?.vendorPrefix
5256
+ }
5257
+ )
5258
+ );
5259
+ }
5260
+ function generateSchemasFromResolvedType(options, skipNamedDeclaration = false, rootOverride) {
5261
+ const namedDeclaration = skipNamedDeclaration || hasConcreteTypeArguments(options.type, options.context.checker) ? void 0 : getNamedTypeDeclaration2(options.type);
5262
+ if (namedDeclaration !== void 0) {
5263
+ return generateSchemasFromDeclaration({
5264
+ ...options,
5265
+ declaration: namedDeclaration
5266
+ });
5267
+ }
5268
+ const filePath = options.sourceNode?.getSourceFile().fileName ?? options.context.sourceFile.fileName;
5269
+ const typeRegistry = {};
5270
+ const diagnostics = [];
5271
+ const rootType = resolveTypeNode(
5272
+ options.type,
5273
+ options.context.checker,
5274
+ filePath,
5275
+ typeRegistry,
5276
+ /* @__PURE__ */ new Set(),
5277
+ options.sourceNode,
5278
+ normalizeMetadataPolicy(options.metadata),
5279
+ options.extensionRegistry,
5280
+ diagnostics
5281
+ );
5282
+ if (diagnostics.length > 0) {
5283
+ const diagnosticDetails = diagnostics.map((diagnostic) => `${diagnostic.code}: ${diagnostic.message}`).join("; ");
5284
+ throw new Error(
5285
+ `FormSpec validation failed while generating discovered type schemas. ${diagnosticDetails}`
5286
+ );
5287
+ }
5288
+ const describedRoot = describeRootType(
5289
+ rootType,
5290
+ typeRegistry,
5291
+ options.name ?? getFallbackName(options.sourceNode)
5292
+ );
5293
+ const mergedMetadata = mergeResolvedMetadata(describedRoot.metadata, rootOverride?.metadata);
5294
+ const root = {
5295
+ ...describedRoot,
5296
+ ...rootOverride?.name !== void 0 && { name: rootOverride.name },
5297
+ ...mergedMetadata !== void 0 && { metadata: mergedMetadata },
5298
+ ...rootOverride?.annotations !== void 0 && { annotations: rootOverride.annotations }
5299
+ };
5300
+ if (root.type.kind === "object") {
5301
+ return generateSchemasFromAnalysis(
5302
+ createObjectRootAnalysis(
5303
+ options.name ?? root.name,
5304
+ root.type.properties,
5305
+ typeRegistry,
5306
+ root.metadata,
5307
+ root.annotations
5308
+ ),
5309
+ filePath,
5310
+ options
5311
+ );
5312
+ }
5313
+ return {
5314
+ jsonSchema: toStandaloneJsonSchema(root, typeRegistry, options),
5315
+ uiSchema: null
5316
+ };
5317
+ }
5318
+ function generateSchemasFromDeclaration(options) {
5319
+ const filePath = options.declaration.getSourceFile().fileName;
5320
+ if (ts7.isClassDeclaration(options.declaration)) {
5321
+ return generateSchemasFromAnalysis(
5322
+ analyzeClassToIR(
5323
+ options.declaration,
5324
+ options.context.checker,
5325
+ filePath,
5326
+ options.extensionRegistry,
5327
+ options.metadata
5328
+ ),
5329
+ filePath,
5330
+ options
5331
+ );
5332
+ }
5333
+ if (ts7.isInterfaceDeclaration(options.declaration)) {
5334
+ return generateSchemasFromAnalysis(
5335
+ analyzeInterfaceToIR(
5336
+ options.declaration,
5337
+ options.context.checker,
5338
+ filePath,
5339
+ options.extensionRegistry,
5340
+ options.metadata
5341
+ ),
5342
+ filePath,
5343
+ options
5344
+ );
5345
+ }
5346
+ if (ts7.isTypeAliasDeclaration(options.declaration)) {
5347
+ const analyzedAlias = analyzeTypeAliasToIR(
5348
+ options.declaration,
5349
+ options.context.checker,
5350
+ filePath,
5351
+ options.extensionRegistry,
5352
+ options.metadata
5353
+ );
5354
+ if (analyzedAlias.ok) {
5355
+ return generateSchemasFromAnalysis(analyzedAlias.analysis, filePath, options);
5356
+ }
5357
+ const aliasRootInfo = analyzeDeclarationRootInfo(
5358
+ options.declaration,
5359
+ options.context.checker,
5360
+ filePath,
5361
+ options.extensionRegistry,
5362
+ options.metadata
5363
+ );
5364
+ if (aliasRootInfo.diagnostics.length > 0) {
5365
+ const diagnosticDetails = aliasRootInfo.diagnostics.map((diagnostic) => `${diagnostic.code}: ${diagnostic.message}`).join("; ");
5366
+ throw new Error(
5367
+ `FormSpec validation failed while generating discovered type schemas. ${diagnosticDetails}`
5368
+ );
5369
+ }
5370
+ return generateSchemasFromResolvedType(
5371
+ {
5372
+ ...options,
5373
+ type: options.context.checker.getTypeAtLocation(options.declaration),
5374
+ sourceNode: options.declaration,
5375
+ name: options.declaration.name.text
5376
+ },
5377
+ true,
5378
+ {
5379
+ name: options.declaration.name.text,
5380
+ ...aliasRootInfo.metadata !== void 0 && { metadata: aliasRootInfo.metadata },
5381
+ ...aliasRootInfo.annotations.length > 0 && { annotations: aliasRootInfo.annotations }
5382
+ }
5383
+ );
5384
+ }
5385
+ const _exhaustive = options.declaration;
5386
+ return _exhaustive;
5387
+ }
5388
+ function generateSchemasFromType(options) {
5389
+ return generateSchemasFromResolvedType(options);
5390
+ }
5391
+ function generateSchemasFromParameter(options) {
5392
+ return generateSchemasFromResolvedType({
5393
+ ...options,
5394
+ type: options.context.checker.getTypeAtLocation(options.parameter),
5395
+ sourceNode: options.parameter,
5396
+ name: getFallbackName(options.parameter, "Parameter")
5397
+ });
5398
+ }
5399
+ function generateSchemasFromReturnType(options) {
5400
+ const signature = options.context.checker.getSignatureFromDeclaration(options.declaration);
5401
+ const type = signature !== void 0 ? options.context.checker.getReturnTypeOfSignature(signature) : options.context.checker.getTypeAtLocation(options.declaration);
5402
+ const fallbackName = options.declaration.name !== void 0 && ts7.isIdentifier(options.declaration.name) ? `${options.declaration.name.text}ReturnType` : "ReturnType";
5403
+ return generateSchemasFromResolvedType({
5404
+ ...options,
5405
+ type,
5406
+ sourceNode: options.declaration.type ?? options.declaration,
5407
+ name: fallbackName
5408
+ });
5409
+ }
5410
+ var init_discovered_schema = __esm({
5411
+ "src/generators/discovered-schema.ts"() {
5412
+ "use strict";
5413
+ init_class_analyzer();
5414
+ init_class_schema();
5415
+ init_ir_generator();
5416
+ init_metadata();
5417
+ }
5418
+ });
5419
+
5023
5420
  // src/generators/mixed-authoring.ts
5024
5421
  function buildMixedAuthoringSchemas(options) {
5025
5422
  const { filePath, typeName, overlays, ...schemaOptions } = options;
@@ -5226,12 +5623,20 @@ __export(index_exports, {
5226
5623
  buildFormSchemas: () => buildFormSchemas,
5227
5624
  buildMixedAuthoringSchemas: () => buildMixedAuthoringSchemas,
5228
5625
  createExtensionRegistry: () => createExtensionRegistry,
5626
+ createStaticBuildContext: () => createStaticBuildContext,
5627
+ createStaticBuildContextFromProgram: () => createStaticBuildContextFromProgram,
5229
5628
  generateJsonSchema: () => generateJsonSchema,
5230
5629
  generateSchemas: () => generateSchemas,
5231
5630
  generateSchemasFromClass: () => generateSchemasFromClass,
5631
+ generateSchemasFromDeclaration: () => generateSchemasFromDeclaration,
5632
+ generateSchemasFromParameter: () => generateSchemasFromParameter,
5232
5633
  generateSchemasFromProgram: () => generateSchemasFromProgram,
5634
+ generateSchemasFromReturnType: () => generateSchemasFromReturnType,
5635
+ generateSchemasFromType: () => generateSchemasFromType,
5233
5636
  generateUiSchema: () => generateUiSchema,
5234
5637
  jsonSchema7Schema: () => jsonSchema7Schema,
5638
+ resolveModuleExport: () => resolveModuleExport,
5639
+ resolveModuleExportDeclaration: () => resolveModuleExportDeclaration,
5235
5640
  uiSchemaSchema: () => uiSchema,
5236
5641
  writeSchemas: () => writeSchemas
5237
5642
  });
@@ -5268,6 +5673,8 @@ var init_index = __esm({
5268
5673
  init_generator();
5269
5674
  init_generator2();
5270
5675
  init_class_schema();
5676
+ init_static_build();
5677
+ init_discovered_schema();
5271
5678
  init_mixed_authoring();
5272
5679
  }
5273
5680
  });