@typespec/openapi3 0.64.0-dev.1 → 0.64.0-dev.4

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.
Files changed (57) hide show
  1. package/README.md +4 -0
  2. package/dist/src/attach-extensions.d.ts +3 -0
  3. package/dist/src/attach-extensions.d.ts.map +1 -0
  4. package/dist/src/attach-extensions.js +11 -0
  5. package/dist/src/attach-extensions.js.map +1 -0
  6. package/dist/src/encoding.d.ts +2 -2
  7. package/dist/src/encoding.d.ts.map +1 -1
  8. package/dist/src/encoding.js +3 -2
  9. package/dist/src/encoding.js.map +1 -1
  10. package/dist/src/json-schema.d.ts +3 -0
  11. package/dist/src/json-schema.d.ts.map +1 -0
  12. package/dist/src/json-schema.js +9 -0
  13. package/dist/src/json-schema.js.map +1 -0
  14. package/dist/src/lib.d.ts +1 -0
  15. package/dist/src/lib.d.ts.map +1 -1
  16. package/dist/src/lib.js +12 -0
  17. package/dist/src/lib.js.map +1 -1
  18. package/dist/src/openapi-helpers-3-0.d.ts +6 -0
  19. package/dist/src/openapi-helpers-3-0.d.ts.map +1 -0
  20. package/dist/src/openapi-helpers-3-0.js +15 -0
  21. package/dist/src/openapi-helpers-3-0.js.map +1 -0
  22. package/dist/src/openapi-helpers-3-1.d.ts +6 -0
  23. package/dist/src/openapi-helpers-3-1.d.ts.map +1 -0
  24. package/dist/src/openapi-helpers-3-1.js +23 -0
  25. package/dist/src/openapi-helpers-3-1.js.map +1 -0
  26. package/dist/src/openapi-spec-mappings.d.ts +33 -0
  27. package/dist/src/openapi-spec-mappings.d.ts.map +1 -0
  28. package/dist/src/openapi-spec-mappings.js +53 -0
  29. package/dist/src/openapi-spec-mappings.js.map +1 -0
  30. package/dist/src/openapi.d.ts +2 -1
  31. package/dist/src/openapi.d.ts.map +1 -1
  32. package/dist/src/openapi.js +42 -44
  33. package/dist/src/openapi.js.map +1 -1
  34. package/dist/src/schema-emitter-3-0.d.ts +19 -0
  35. package/dist/src/schema-emitter-3-0.d.ts.map +1 -0
  36. package/dist/src/schema-emitter-3-0.js +199 -0
  37. package/dist/src/schema-emitter-3-0.js.map +1 -0
  38. package/dist/src/schema-emitter-3-1.d.ts +24 -0
  39. package/dist/src/schema-emitter-3-1.d.ts.map +1 -0
  40. package/dist/src/schema-emitter-3-1.js +226 -0
  41. package/dist/src/schema-emitter-3-1.js.map +1 -0
  42. package/dist/src/schema-emitter.d.ts +33 -10
  43. package/dist/src/schema-emitter.d.ts.map +1 -1
  44. package/dist/src/schema-emitter.js +104 -280
  45. package/dist/src/schema-emitter.js.map +1 -1
  46. package/dist/src/std-scalar-schemas.d.ts +2 -2
  47. package/dist/src/std-scalar-schemas.d.ts.map +1 -1
  48. package/dist/src/types.d.ts +352 -2
  49. package/dist/src/types.d.ts.map +1 -1
  50. package/dist/src/util.d.ts +10 -0
  51. package/dist/src/util.d.ts.map +1 -1
  52. package/dist/src/util.js +42 -0
  53. package/dist/src/util.js.map +1 -1
  54. package/dist/src/xml-module.d.ts +3 -3
  55. package/dist/src/xml-module.d.ts.map +1 -1
  56. package/dist/src/xml-module.js.map +1 -1
  57. package/package.json +6 -1
@@ -1,25 +1,28 @@
1
- import { compilerAssert, explainStringTemplateNotSerializable, getDeprecated, getDiscriminatedUnion, getDiscriminator, getDoc, getEncode, getExamples, getFormat, getKnownValues, getMaxItems, getMaxLength, getMaxValue, getMaxValueExclusive, getMinItems, getMinLength, getMinValue, getMinValueExclusive, getNamespaceFullName, getPattern, getSummary, getTypeName, ignoreDiagnostics, isArrayModelType, isNeverType, isNullType, isSecret, isTemplateDeclaration, resolveEncodedName, serializeValueAsJson, } from "@typespec/compiler";
1
+ import { compilerAssert, explainStringTemplateNotSerializable, getDeprecated, getDiscriminatedUnion, getDiscriminator, getDoc, getEncode, getFormat, getKnownValues, getMaxItems, getMaxLength, getMaxValue, getMinItems, getMinLength, getMinValue, getNamespaceFullName, getPattern, getSummary, getTypeName, ignoreDiagnostics, isArrayModelType, isNeverType, isSecret, resolveEncodedName, } from "@typespec/compiler";
2
2
  import { ArrayBuilder, ObjectBuilder, Placeholder, TypeEmitter, } from "@typespec/compiler/emitter-framework";
3
3
  import { Visibility, getVisibilitySuffix } from "@typespec/http";
4
- import { checkDuplicateTypeName, getExtensions, getExternalDocs, getOpenAPITypeName, isReadonlyProperty, shouldInline, } from "@typespec/openapi";
4
+ import { checkDuplicateTypeName, getExternalDocs, getOpenAPITypeName, isReadonlyProperty, shouldInline, } from "@typespec/openapi";
5
+ import { attachExtensions } from "./attach-extensions.js";
5
6
  import { getOneOf, getRef } from "./decorators.js";
6
- import { applyEncoding } from "./encoding.js";
7
7
  import { reportDiagnostic } from "./lib.js";
8
8
  import { getSchemaForStdScalars } from "./std-scalar-schemas.js";
9
+ import { getDefaultValue, includeDerivedModel, isBytesKeptRaw, isStdType } from "./util.js";
9
10
  /**
10
- * OpenAPI3 schema emitter. Deals with emitting content of `components/schemas` section.
11
+ * Base OpenAPI3 schema emitter. Deals with emitting content of `components/schemas` section.
11
12
  */
12
- export class OpenAPI3SchemaEmitter extends TypeEmitter {
13
- #metadataInfo;
14
- #visibilityUsage;
15
- #options;
16
- #xmlModule;
17
- constructor(emitter, metadataInfo, visibilityUsage, options, xmlModule) {
13
+ export class OpenAPI3SchemaEmitterBase extends TypeEmitter {
14
+ _metadataInfo;
15
+ _visibilityUsage;
16
+ _options;
17
+ _jsonSchemaModule;
18
+ _xmlModule;
19
+ constructor(emitter, metadataInfo, visibilityUsage, options, optionalDependencies) {
18
20
  super(emitter);
19
- this.#metadataInfo = metadataInfo;
20
- this.#visibilityUsage = visibilityUsage;
21
- this.#options = options;
22
- this.#xmlModule = xmlModule;
21
+ this._metadataInfo = metadataInfo;
22
+ this._visibilityUsage = visibilityUsage;
23
+ this._options = options;
24
+ this._jsonSchemaModule = optionalDependencies.jsonSchemaModule;
25
+ this._xmlModule = optionalDependencies.xmlModule;
23
26
  }
24
27
  modelDeclarationReferenceContext(model, name) {
25
28
  return this.reduceContext(model);
@@ -39,15 +42,28 @@ export class OpenAPI3SchemaEmitter extends TypeEmitter {
39
42
  reduceContext(type) {
40
43
  const visibility = this.#getVisibilityContext();
41
44
  const patch = {};
42
- if (visibility !== Visibility.Read && !this.#metadataInfo.isTransformed(type, visibility)) {
45
+ if (visibility !== Visibility.Read && !this._metadataInfo.isTransformed(type, visibility)) {
43
46
  patch.visibility = Visibility.Read;
44
47
  }
45
- const contentType = this.#getContentType();
48
+ const contentType = this.getContentType();
46
49
  if (contentType === "application/json") {
47
50
  patch.contentType = undefined;
48
51
  }
49
52
  return patch;
50
53
  }
54
+ applyDiscriminator(type, schema) {
55
+ const program = this.emitter.getProgram();
56
+ const discriminator = getDiscriminator(program, type);
57
+ if (discriminator) {
58
+ // the decorator validates that all the variants will be a model type
59
+ // with the discriminator field present.
60
+ schema.discriminator = { ...discriminator };
61
+ const discriminatedUnion = ignoreDiagnostics(getDiscriminatedUnion(type, discriminator));
62
+ if (discriminatedUnion.variants.size > 0) {
63
+ schema.discriminator.mapping = this.getDiscriminatorMapping(discriminatedUnion);
64
+ }
65
+ }
66
+ }
51
67
  modelDeclaration(model, _) {
52
68
  const program = this.emitter.getProgram();
53
69
  const visibility = this.#getVisibilityContext();
@@ -64,23 +80,15 @@ export class OpenAPI3SchemaEmitter extends TypeEmitter {
64
80
  for (const child of derivedModels) {
65
81
  this.emitter.emitTypeReference(child);
66
82
  }
67
- const discriminator = getDiscriminator(program, model);
68
- if (discriminator) {
69
- const [union] = getDiscriminatedUnion(model, discriminator);
70
- const openApiDiscriminator = { ...discriminator };
71
- if (union.variants.size > 0) {
72
- openApiDiscriminator.mapping = this.#getDiscriminatorMapping(union);
73
- }
74
- schema.discriminator = openApiDiscriminator;
75
- }
83
+ this.applyDiscriminator(model, schema);
76
84
  this.#applyExternalDocs(model, schema);
77
85
  if (model.baseModel) {
78
- schema.set("allOf", B.array([this.emitter.emitTypeReference(model.baseModel)]));
86
+ schema.set("allOf", Builders.array([this.emitter.emitTypeReference(model.baseModel)]));
79
87
  }
80
88
  const baseName = getOpenAPITypeName(program, model, this.#typeNameOptions());
81
- const isMultipart = this.#getContentType().startsWith("multipart/");
89
+ const isMultipart = this.getContentType().startsWith("multipart/");
82
90
  const name = isMultipart ? baseName + "MultiPart" : baseName;
83
- return this.#createDeclaration(model, name, this.#applyConstraints(model, schema));
91
+ return this.#createDeclaration(model, name, this.applyConstraints(model, schema));
84
92
  }
85
93
  #applyExternalDocs(typespecType, target) {
86
94
  const externalDocs = getExternalDocs(this.emitter.getProgram(), typespecType);
@@ -104,7 +112,7 @@ export class OpenAPI3SchemaEmitter extends TypeEmitter {
104
112
  #ignoreMetadataAnnotations() {
105
113
  return this.emitter.getContext().ignoreMetadataAnnotations;
106
114
  }
107
- #getContentType() {
115
+ getContentType() {
108
116
  return this.emitter.getContext().contentType ?? "application/json";
109
117
  }
110
118
  modelLiteral(model) {
@@ -130,7 +138,7 @@ export class OpenAPI3SchemaEmitter extends TypeEmitter {
130
138
  type: "array",
131
139
  items: this.emitter.emitTypeReference(elementType),
132
140
  });
133
- return this.#createDeclaration(array, name, this.#applyConstraints(array, schema));
141
+ return this.#createDeclaration(array, name, this.applyConstraints(array, schema));
134
142
  }
135
143
  arrayDeclarationReferenceContext(array, name, elementType) {
136
144
  return {
@@ -155,11 +163,11 @@ export class OpenAPI3SchemaEmitter extends TypeEmitter {
155
163
  // If the property has a type of 'never', don't include it in the schema
156
164
  continue;
157
165
  }
158
- if (!this.#metadataInfo.isPayloadProperty(prop, visibility, this.#ignoreMetadataAnnotations())) {
166
+ if (!this._metadataInfo.isPayloadProperty(prop, visibility, this.#ignoreMetadataAnnotations())) {
159
167
  continue;
160
168
  }
161
- if (!this.#metadataInfo.isOptional(prop, visibility)) {
162
- const encodedName = resolveEncodedName(this.emitter.getProgram(), prop, this.#getContentType());
169
+ if (!this._metadataInfo.isOptional(prop, visibility)) {
170
+ const encodedName = resolveEncodedName(this.emitter.getProgram(), prop, this.getContentType());
163
171
  requiredProps.push(encodedName);
164
172
  }
165
173
  }
@@ -175,13 +183,13 @@ export class OpenAPI3SchemaEmitter extends TypeEmitter {
175
183
  const program = this.emitter.getProgram();
176
184
  const props = new ObjectBuilder();
177
185
  const visibility = this.emitter.getContext().visibility;
178
- const contentType = this.#getContentType();
186
+ const contentType = this.getContentType();
179
187
  for (const prop of model.properties.values()) {
180
188
  if (isNeverType(prop.type)) {
181
189
  // If the property has a type of 'never', don't include it in the schema
182
190
  continue;
183
191
  }
184
- if (!this.#metadataInfo.isPayloadProperty(prop, visibility, this.#ignoreMetadataAnnotations())) {
192
+ if (!this._metadataInfo.isPayloadProperty(prop, visibility, this.#ignoreMetadataAnnotations())) {
185
193
  continue;
186
194
  }
187
195
  const result = this.emitter.emitModelProperty(prop);
@@ -200,17 +208,20 @@ export class OpenAPI3SchemaEmitter extends TypeEmitter {
200
208
  }
201
209
  return props;
202
210
  }
211
+ getRawBinarySchema() {
212
+ throw new Error("Method not implemented.");
213
+ }
203
214
  modelPropertyLiteral(prop) {
204
215
  const program = this.emitter.getProgram();
205
- const isMultipart = this.#getContentType().startsWith("multipart/");
216
+ const isMultipart = this.getContentType().startsWith("multipart/");
206
217
  if (isMultipart) {
207
218
  if (isBytesKeptRaw(program, prop.type) && getEncode(program, prop) === undefined) {
208
- return { type: "string", format: "binary" };
219
+ return this.getRawBinarySchema();
209
220
  }
210
221
  if (prop.type.kind === "Model" &&
211
222
  isArrayModelType(program, prop.type) &&
212
223
  isBytesKeptRaw(program, prop.type.indexer.value)) {
213
- return { type: "array", items: { type: "string", format: "binary" } };
224
+ return { type: "array", items: this.getRawBinarySchema() };
214
225
  }
215
226
  }
216
227
  const refSchema = this.emitter.emitTypeReference(prop.type, {
@@ -231,9 +242,9 @@ export class OpenAPI3SchemaEmitter extends TypeEmitter {
231
242
  return {};
232
243
  }
233
244
  const isRef = refSchema.value instanceof Placeholder || "$ref" in refSchema.value;
234
- const schema = this.#applyEncoding(prop, refSchema.value);
245
+ const schema = this.applyEncoding(prop, refSchema.value);
235
246
  // Apply decorators on the property to the type's schema
236
- const additionalProps = this.#applyConstraints(prop, {}, schema);
247
+ const additionalProps = this.applyConstraints(prop, {}, schema);
237
248
  if (prop.defaultValue) {
238
249
  additionalProps.default = getDefaultValue(program, prop.defaultValue, prop);
239
250
  }
@@ -241,7 +252,7 @@ export class OpenAPI3SchemaEmitter extends TypeEmitter {
241
252
  additionalProps.readOnly = true;
242
253
  }
243
254
  // Attach any additional OpenAPI extensions
244
- this.#attachExtensions(program, prop, additionalProps);
255
+ attachExtensions(program, prop, additionalProps);
245
256
  if (schema && isRef && !(prop.type.kind === "Model" && isArrayModelType(program, prop.type))) {
246
257
  if (Object.keys(additionalProps).length === 0) {
247
258
  return schema;
@@ -291,28 +302,11 @@ export class OpenAPI3SchemaEmitter extends TypeEmitter {
291
302
  }
292
303
  enumDeclaration(en, name) {
293
304
  const baseName = getOpenAPITypeName(this.emitter.getProgram(), en, this.#typeNameOptions());
294
- return this.#createDeclaration(en, baseName, new ObjectBuilder(this.#enumSchema(en)));
305
+ return this.#createDeclaration(en, baseName, new ObjectBuilder(this.enumSchema(en)));
295
306
  }
296
- #enumSchema(en) {
297
- const program = this.emitter.getProgram();
298
- if (en.members.size === 0) {
299
- reportDiagnostic(program, { code: "empty-enum", target: en });
300
- return {};
301
- }
302
- const enumTypes = new Set();
303
- const enumValues = new Set();
304
- for (const member of en.members.values()) {
305
- enumTypes.add(typeof member.value === "number" ? "number" : "string");
306
- enumValues.add(member.value ?? member.name);
307
- }
308
- if (enumTypes.size > 1) {
309
- reportDiagnostic(program, { code: "enum-unique-type", target: en });
310
- }
311
- const schema = {
312
- type: enumTypes.values().next().value,
313
- enum: [...enumValues],
314
- };
315
- return this.#applyConstraints(en, schema);
307
+ enumSchema(en) {
308
+ // Enums are handled differently between 3.x versions due to the differences in `type`
309
+ throw new Error("Method not implemented.");
316
310
  }
317
311
  enumMember(member) {
318
312
  return this.enumMemberReference(member);
@@ -329,134 +323,16 @@ export class OpenAPI3SchemaEmitter extends TypeEmitter {
329
323
  }
330
324
  }
331
325
  unionDeclaration(union, name) {
332
- const schema = this.#unionSchema(union);
326
+ const schema = this.unionSchema(union);
333
327
  const baseName = getOpenAPITypeName(this.emitter.getProgram(), union, this.#typeNameOptions());
334
328
  return this.#createDeclaration(union, baseName, schema);
335
329
  }
336
- #unionSchema(union) {
337
- const program = this.emitter.getProgram();
338
- if (union.variants.size === 0) {
339
- reportDiagnostic(program, { code: "empty-union", target: union });
340
- return new ObjectBuilder({});
341
- }
342
- const variants = Array.from(union.variants.values());
343
- const literalVariantEnumByType = {};
344
- const ofType = getOneOf(program, union) ? "oneOf" : "anyOf";
345
- const schemaMembers = [];
346
- let nullable = false;
347
- const discriminator = getDiscriminator(program, union);
348
- const isMultipart = this.#getContentType().startsWith("multipart/");
349
- for (const variant of variants) {
350
- if (isNullType(variant.type)) {
351
- nullable = true;
352
- continue;
353
- }
354
- if (isMultipart && isBytesKeptRaw(program, variant.type)) {
355
- schemaMembers.push({ schema: { type: "string", format: "binary" }, type: variant.type });
356
- continue;
357
- }
358
- if (isLiteralType(variant.type)) {
359
- if (!literalVariantEnumByType[variant.type.kind]) {
360
- const enumValue = [variant.type.value];
361
- literalVariantEnumByType[variant.type.kind] = enumValue;
362
- schemaMembers.push({
363
- schema: { type: literalType(variant.type), enum: enumValue },
364
- type: null,
365
- });
366
- }
367
- else {
368
- literalVariantEnumByType[variant.type.kind].push(variant.type.value);
369
- }
370
- }
371
- else {
372
- const enumSchema = this.emitter.emitTypeReference(variant.type, {
373
- referenceContext: isMultipart ? { contentType: "application/json" } : {},
374
- });
375
- compilerAssert(enumSchema.kind === "code", "Unexpected enum schema. Should be kind: code");
376
- schemaMembers.push({ schema: enumSchema.value, type: variant.type });
377
- }
378
- }
379
- const wrapWithObjectBuilder = (schemaMember, { mergeUnionWideConstraints }) => {
380
- // we can just return the single schema member after applying nullable
381
- const schema = schemaMember.schema;
382
- const type = schemaMember.type;
383
- const additionalProps = mergeUnionWideConstraints
384
- ? this.#applyConstraints(union, {})
385
- : {};
386
- if (mergeUnionWideConstraints && nullable) {
387
- additionalProps.nullable = true;
388
- }
389
- if (Object.keys(additionalProps).length === 0) {
390
- return new ObjectBuilder(schema);
391
- }
392
- else {
393
- if ((schema instanceof Placeholder || "$ref" in schema) &&
394
- !(type && shouldInline(program, type))) {
395
- if (type && (type.kind === "Model" || type.kind === "Scalar")) {
396
- return new ObjectBuilder({
397
- type: "object",
398
- allOf: B.array([schema]),
399
- ...additionalProps,
400
- });
401
- }
402
- else {
403
- return new ObjectBuilder({ allOf: B.array([schema]), ...additionalProps });
404
- }
405
- }
406
- else {
407
- const merged = new ObjectBuilder(schema);
408
- for (const [key, value] of Object.entries(additionalProps)) {
409
- merged.set(key, value);
410
- }
411
- return merged;
412
- }
413
- }
414
- };
415
- const checkMerge = (schemaMembers) => {
416
- if (nullable) {
417
- for (const m of schemaMembers) {
418
- if (m.schema instanceof Placeholder || "$ref" in m.schema) {
419
- return true;
420
- }
421
- }
422
- }
423
- return false;
424
- };
425
- if (schemaMembers.length === 0) {
426
- if (nullable) {
427
- // This union is equivalent to just `null` but OA3 has no way to specify
428
- // null as a value, so we throw an error.
429
- reportDiagnostic(program, { code: "union-null", target: union });
430
- return new ObjectBuilder({});
431
- }
432
- else {
433
- // completely empty union can maybe only happen with bugs?
434
- compilerAssert(false, "Attempting to emit an empty union");
435
- }
436
- }
437
- if (schemaMembers.length === 1) {
438
- return wrapWithObjectBuilder(schemaMembers[0], { mergeUnionWideConstraints: true });
439
- }
440
- const isMerge = checkMerge(schemaMembers);
441
- const schema = {
442
- [ofType]: schemaMembers.map((m) => wrapWithObjectBuilder(m, { mergeUnionWideConstraints: isMerge })),
443
- };
444
- if (!isMerge && nullable) {
445
- schema.nullable = true;
446
- }
447
- if (discriminator) {
448
- // the decorator validates that all the variants will be a model type
449
- // with the discriminator field present.
450
- schema.discriminator = { ...discriminator };
451
- // Diagnostic already reported in compiler for unions
452
- const discriminatedUnion = ignoreDiagnostics(getDiscriminatedUnion(union, discriminator));
453
- if (discriminatedUnion.variants.size > 0) {
454
- schema.discriminator.mapping = this.#getDiscriminatorMapping(discriminatedUnion);
455
- }
456
- }
457
- return this.#applyConstraints(union, schema);
330
+ unionSchema(union) {
331
+ // Unions are handled differently between 3.x versions
332
+ // mostly due to how nullable properties are handled.
333
+ throw new Error("Method not implemented.");
458
334
  }
459
- #getDiscriminatorMapping(union) {
335
+ getDiscriminatorMapping(union) {
460
336
  const mapping = {};
461
337
  for (const [key, model] of union.variants.entries()) {
462
338
  const ref = this.emitter.emitTypeReference(model);
@@ -466,7 +342,7 @@ export class OpenAPI3SchemaEmitter extends TypeEmitter {
466
342
  return mapping;
467
343
  }
468
344
  unionLiteral(union) {
469
- return this.#unionSchema(union);
345
+ return this.unionSchema(union);
470
346
  }
471
347
  unionVariants(union) {
472
348
  const variants = new ArrayBuilder();
@@ -481,15 +357,6 @@ export class OpenAPI3SchemaEmitter extends TypeEmitter {
481
357
  modelPropertyReference(prop) {
482
358
  return this.modelPropertyLiteral(prop);
483
359
  }
484
- #attachExtensions(program, type, emitObject) {
485
- // Attach any OpenAPI extensions
486
- const extensions = getExtensions(program, type);
487
- if (extensions) {
488
- for (const key of extensions.keys()) {
489
- emitObject[key] = extensions.get(key);
490
- }
491
- }
492
- }
493
360
  reference(targetDeclaration, pathUp, pathDown, commonScope) {
494
361
  if (targetDeclaration.value instanceof Placeholder) {
495
362
  // I don't think this is possible, confirm.
@@ -517,11 +384,13 @@ export class OpenAPI3SchemaEmitter extends TypeEmitter {
517
384
  return super.circularReference(target, scope, cycle);
518
385
  }
519
386
  scalarDeclaration(scalar, name) {
520
- const isStd = this.#isStdType(scalar);
387
+ const isStd = isStdType(this.emitter.getProgram(), scalar);
521
388
  const schema = this.#getSchemaForScalar(scalar);
522
389
  const baseName = getOpenAPITypeName(this.emitter.getProgram(), scalar, this.#typeNameOptions());
523
390
  // Don't create a declaration for std types
524
- return isStd ? schema : this.#createDeclaration(scalar, baseName, new ObjectBuilder(schema));
391
+ return isStd
392
+ ? schema
393
+ : this.#createDeclaration(scalar, baseName, new ObjectBuilder(schema));
525
394
  }
526
395
  scalarInstantiation(scalar, name) {
527
396
  return this.#getSchemaForScalar(scalar);
@@ -531,31 +400,26 @@ export class OpenAPI3SchemaEmitter extends TypeEmitter {
531
400
  }
532
401
  #getSchemaForScalar(scalar) {
533
402
  let result = {};
534
- const isStd = this.#isStdType(scalar);
403
+ const isStd = isStdType(this.emitter.getProgram(), scalar);
535
404
  if (isStd) {
536
- result = this.#getSchemaForStdScalars(scalar);
405
+ result = this.getSchemaForStdScalars(scalar);
537
406
  }
538
407
  else if (scalar.baseScalar) {
539
408
  result = this.#getSchemaForScalar(scalar.baseScalar);
540
409
  }
541
- const withDecorators = this.#applyEncoding(scalar, this.#applyConstraints(scalar, result));
410
+ const withDecorators = this.applyEncoding(scalar, this.applyConstraints(scalar, result));
542
411
  if (isStd) {
543
412
  // Standard types are going to be inlined in the spec and we don't want the description of the scalar to show up
544
413
  delete withDecorators.description;
545
414
  }
546
415
  return withDecorators;
547
416
  }
548
- #getSchemaForStdScalars(scalar) {
549
- return getSchemaForStdScalars(scalar, this.#options);
417
+ getSchemaForStdScalars(scalar) {
418
+ return getSchemaForStdScalars(scalar, this._options);
550
419
  }
551
- #applySchemaExamples(type, target) {
552
- const program = this.emitter.getProgram();
553
- const examples = getExamples(program, type);
554
- if (examples.length > 0) {
555
- target.set("example", serializeValueAsJson(program, examples[0].value, type));
556
- }
557
- }
558
- #applyConstraints(type, original, refSchema) {
420
+ applyCustomConstraints(type, target, refSchema) { }
421
+ applyConstraints(type, original, refSchema) {
422
+ // Apply common constraints
559
423
  const schema = new ObjectBuilder(original);
560
424
  const program = this.emitter.getProgram();
561
425
  const applyConstraint = (fn, key) => {
@@ -564,7 +428,6 @@ export class OpenAPI3SchemaEmitter extends TypeEmitter {
564
428
  schema[key] = value;
565
429
  }
566
430
  };
567
- this.#applySchemaExamples(type, schema);
568
431
  applyConstraint(getMinLength, "minLength");
569
432
  applyConstraint(getMaxLength, "maxLength");
570
433
  applyConstraint(getMinValue, "minimum");
@@ -572,49 +435,52 @@ export class OpenAPI3SchemaEmitter extends TypeEmitter {
572
435
  applyConstraint(getPattern, "pattern");
573
436
  applyConstraint(getMinItems, "minItems");
574
437
  applyConstraint(getMaxItems, "maxItems");
575
- const minValueExclusive = getMinValueExclusive(program, type);
576
- if (minValueExclusive !== undefined) {
577
- schema.minimum = minValueExclusive;
578
- schema.exclusiveMinimum = true;
579
- }
580
- const maxValueExclusive = getMaxValueExclusive(program, type);
581
- if (maxValueExclusive !== undefined) {
582
- schema.maximum = maxValueExclusive;
583
- schema.exclusiveMaximum = true;
438
+ // apply json schema decorators
439
+ const jsonSchemaModule = this._jsonSchemaModule;
440
+ if (jsonSchemaModule) {
441
+ applyConstraint(jsonSchemaModule.getMultipleOf, "multipleOf");
442
+ applyConstraint(jsonSchemaModule.getUniqueItems, "uniqueItems");
443
+ applyConstraint(jsonSchemaModule.getMinProperties, "minProperties");
444
+ applyConstraint(jsonSchemaModule.getMaxProperties, "maxProperties");
584
445
  }
585
446
  if (isSecret(program, type)) {
586
447
  schema.format = "password";
587
448
  }
588
449
  // the stdlib applies a format of "url" but json schema wants "uri",
589
450
  // so ignore this format if it's the built-in type.
590
- if (!this.#isStdType(type) || type.name !== "url") {
451
+ if (!isStdType(program, type) || type.name !== "url") {
591
452
  applyConstraint(getFormat, "format");
592
453
  }
593
454
  applyConstraint(getDoc, "description");
594
455
  applyConstraint(getSummary, "title");
595
456
  applyConstraint((p, t) => (getDeprecated(p, t) !== undefined ? true : undefined), "deprecated");
596
- if (this.#xmlModule) {
457
+ this.applyCustomConstraints(type, schema, refSchema);
458
+ this.applyXml(type, schema, refSchema);
459
+ attachExtensions(program, type, schema);
460
+ const values = getKnownValues(program, type);
461
+ if (values) {
462
+ return new ObjectBuilder({
463
+ oneOf: [schema, this.enumSchema(values)],
464
+ });
465
+ }
466
+ return new ObjectBuilder(schema);
467
+ }
468
+ applyXml(type, schema, refSchema) {
469
+ const program = this.emitter.getProgram();
470
+ if (this._xmlModule) {
597
471
  switch (type.kind) {
598
472
  case "Scalar":
599
473
  case "Model":
600
- this.#xmlModule.attachXmlObjectForScalarOrModel(program, type, schema);
474
+ this._xmlModule.attachXmlObjectForScalarOrModel(program, type, schema);
601
475
  break;
602
476
  case "ModelProperty":
603
- this.#xmlModule.attachXmlObjectForModelProperty(program, this.#options, type, schema, refSchema);
477
+ this._xmlModule.attachXmlObjectForModelProperty(program, this._options, type, schema, refSchema);
604
478
  break;
605
479
  }
606
480
  }
607
- this.#attachExtensions(program, type, schema);
608
- const values = getKnownValues(program, type);
609
- if (values) {
610
- return new ObjectBuilder({
611
- oneOf: [schema, this.#enumSchema(values)],
612
- });
613
- }
614
- return new ObjectBuilder(schema);
615
481
  }
616
482
  #inlineType(type, schema) {
617
- if (this.#options.includeXTypeSpecName !== "never") {
483
+ if (this._options.includeXTypeSpecName !== "never") {
618
484
  schema.set("x-typespec-name", getTypeName(type, this.#typeNameOptions()));
619
485
  }
620
486
  return schema;
@@ -633,7 +499,7 @@ export class OpenAPI3SchemaEmitter extends TypeEmitter {
633
499
  if (title) {
634
500
  schema.set("title", title);
635
501
  }
636
- const usage = this.#visibilityUsage.getUsage(type);
502
+ const usage = this._visibilityUsage.getUsage(type);
637
503
  const shouldAddSuffix = usage !== undefined && usage.size > 1;
638
504
  const visibility = this.#getVisibilityContext();
639
505
  const fullName = name + (shouldAddSuffix ? getVisibilitySuffix(visibility, Visibility.Read) : "");
@@ -641,51 +507,15 @@ export class OpenAPI3SchemaEmitter extends TypeEmitter {
641
507
  checkDuplicateTypeName(this.emitter.getProgram(), type, fullName, Object.fromEntries(decl.scope.declarations.map((x) => [x.name, true])));
642
508
  return decl;
643
509
  }
644
- #isStdType(type) {
645
- return this.emitter.getProgram().checker.isStdType(type);
646
- }
647
- #applyEncoding(typespecType, target) {
648
- return applyEncoding(this.emitter.getProgram(), typespecType, target, this.#options);
649
- }
650
- intrinsic(intrinsic, name) {
651
- switch (name) {
652
- case "unknown":
653
- return {};
654
- case "null":
655
- return { nullable: true };
656
- }
657
- reportDiagnostic(this.emitter.getProgram(), {
658
- code: "invalid-schema",
659
- format: { type: name },
660
- target: intrinsic,
661
- });
662
- return {};
510
+ applyEncoding(typespecType, target) {
511
+ throw new Error("Method not implemented.");
663
512
  }
664
513
  programContext(program) {
665
514
  const sourceFile = this.emitter.createSourceFile("openapi");
666
515
  return { scope: sourceFile.globalScope };
667
516
  }
668
517
  }
669
- function isLiteralType(type) {
670
- return type.kind === "Boolean" || type.kind === "String" || type.kind === "Number";
671
- }
672
- function literalType(type) {
673
- switch (type.kind) {
674
- case "String":
675
- return "string";
676
- case "Number":
677
- return "number";
678
- case "Boolean":
679
- return "boolean";
680
- }
681
- }
682
- function includeDerivedModel(model) {
683
- return (!isTemplateDeclaration(model) &&
684
- (model.templateMapper?.args === undefined ||
685
- model.templateMapper.args?.length === 0 ||
686
- model.derivedModels.length > 0));
687
- }
688
- const B = {
518
+ export const Builders = {
689
519
  array: (items) => {
690
520
  const builder = new ArrayBuilder();
691
521
  for (const item of items) {
@@ -701,10 +531,4 @@ const B = {
701
531
  return builder;
702
532
  },
703
533
  };
704
- export function getDefaultValue(program, defaultType, modelProperty) {
705
- return serializeValueAsJson(program, defaultType, modelProperty);
706
- }
707
- export function isBytesKeptRaw(program, type) {
708
- return type.kind === "Scalar" && type.name === "bytes" && getEncode(program, type) === undefined;
709
- }
710
534
  //# sourceMappingURL=schema-emitter.js.map