@typespec/openapi3 0.54.0-dev.0 → 0.54.0-dev.10

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.
@@ -1,11 +1,12 @@
1
- import { compilerAssert, emitFile, getAllTags, getAnyExtensionFromPath, getDoc, getEncode, getFormat, getKnownValues, getMaxItems, getMaxLength, getMaxValue, getMaxValueExclusive, getMinItems, getMinLength, getMinValue, getMinValueExclusive, getNamespaceFullName, getPattern, getService, getSummary, ignoreDiagnostics, interpolatePath, isArrayModelType, isDeprecated, isGlobalNamespace, isNeverType, isNullType, isSecret, isVoidType, listServices, navigateTypesInNamespace, projectProgram, resolvePath, } from "@typespec/compiler";
2
- import { createMetadataInfo, getAuthentication, getHttpService, getServers, getStatusCodeDescription, isContentTypeHeader, isOverloadSameEndpoint, reportIfNoRoutes, resolveRequestVisibility, Visibility, } from "@typespec/http";
3
- import { getExtensions, getExternalDocs, getInfo, getOpenAPITypeName, getParameterKey, isDefaultResponse, isReadonlyProperty, resolveOperationId, shouldInline, } from "@typespec/openapi";
1
+ import { compilerAssert, createDiagnosticCollector, emitFile, getAllTags, getAnyExtensionFromPath, getDoc, getEncode, getFormat, getKnownValues, getMaxItems, getMaxLength, getMaxValue, getMaxValueExclusive, getMinItems, getMinLength, getMinValue, getMinValueExclusive, getNamespaceFullName, getPattern, getService, getSummary, ignoreDiagnostics, interpolatePath, isDeprecated, isGlobalNamespace, isNeverType, isSecret, isVoidType, listServices, navigateTypesInNamespace, projectProgram, resolvePath, } from "@typespec/compiler";
2
+ import { createAssetEmitter } from "@typespec/compiler/emitter-framework";
3
+ import { createMetadataInfo, getHttpService, getServers, getStatusCodeDescription, isContentTypeHeader, isOverloadSameEndpoint, reportIfNoRoutes, resolveAuthentication, resolveRequestVisibility, Visibility, } from "@typespec/http";
4
+ import { getExtensions, getExternalDocs, getOpenAPITypeName, getParameterKey, isDefaultResponse, isReadonlyProperty, resolveInfo, resolveOperationId, shouldInline, } from "@typespec/openapi";
4
5
  import { buildVersionProjections } from "@typespec/versioning";
5
6
  import { stringify } from "yaml";
6
7
  import { getRef } from "./decorators.js";
7
- import { reportDiagnostic } from "./lib.js";
8
- import { OpenAPI3SchemaEmitter } from "./schema-emitter.js";
8
+ import { createDiagnostic } from "./lib.js";
9
+ import { getDefaultValue, OpenAPI3SchemaEmitter } from "./schema-emitter.js";
9
10
  import { deepEquals } from "./util.js";
10
11
  import { resolveVisibilityUsage } from "./visibility-usage.js";
11
12
  const defaultFileType = "yaml";
@@ -13,12 +14,35 @@ const defaultOptions = {
13
14
  "new-line": "lf",
14
15
  "omit-unreachable-types": false,
15
16
  "include-x-typespec-name": "never",
17
+ "safeint-strategy": "int64",
16
18
  };
17
19
  export async function $onEmit(context) {
18
20
  const options = resolveOptions(context);
19
21
  const emitter = createOAPIEmitter(context, options);
20
22
  await emitter.emitOpenAPI();
21
23
  }
24
+ /**
25
+ * Get the OpenAPI 3 document records from the given program. The documents are
26
+ * returned as a JS object.
27
+ *
28
+ * @param program The program to emit to OpenAPI 3
29
+ * @param options OpenAPI 3 emit options
30
+ * @returns An array of OpenAPI 3 document records.
31
+ */
32
+ export async function getOpenAPI3(program, options = {}) {
33
+ const context = {
34
+ program,
35
+ // this value doesn't matter for getting the OpenAPI3 objects
36
+ emitterOutputDir: "tsp-output",
37
+ options: options,
38
+ getAssetEmitter(TypeEmitterClass) {
39
+ return createAssetEmitter(program, TypeEmitterClass, this);
40
+ },
41
+ };
42
+ const resolvedOptions = resolveOptions(context);
43
+ const emitter = createOAPIEmitter(context, resolvedOptions);
44
+ return emitter.getOpenAPI();
45
+ }
22
46
  function findFileTypeFromFilename(filename) {
23
47
  if (filename === undefined) {
24
48
  return defaultFileType;
@@ -43,6 +67,7 @@ export function resolveOptions(context) {
43
67
  newLine: resolvedOptions["new-line"],
44
68
  omitUnreachableTypes: resolvedOptions["omit-unreachable-types"],
45
69
  includeXTypeSpecName: resolvedOptions["include-x-typespec-name"],
70
+ safeintStrategy: resolvedOptions["safeint-strategy"],
46
71
  outputFile: resolvePath(context.emitterOutputDir, outputFile),
47
72
  };
48
73
  }
@@ -50,6 +75,7 @@ function createOAPIEmitter(context, options) {
50
75
  let program = context.program;
51
76
  let schemaEmitter;
52
77
  let root;
78
+ let diagnostics;
53
79
  let currentService;
54
80
  // Get the service namespace string for use in name shortening
55
81
  let serviceNamespaceName;
@@ -73,9 +99,45 @@ function createOAPIEmitter(context, options) {
73
99
  return name !== serviceNamespaceName;
74
100
  },
75
101
  };
76
- return { emitOpenAPI };
77
- function initializeEmitter(service, version) {
78
- var _a, _b, _c;
102
+ return { emitOpenAPI, getOpenAPI };
103
+ async function emitOpenAPI() {
104
+ const services = await getOpenAPI();
105
+ // first, emit diagnostics
106
+ for (const serviceRecord of services) {
107
+ if (serviceRecord.versioned) {
108
+ for (const documentRecord of serviceRecord.versions) {
109
+ program.reportDiagnostics(documentRecord.diagnostics);
110
+ }
111
+ }
112
+ else {
113
+ program.reportDiagnostics(serviceRecord.diagnostics);
114
+ }
115
+ }
116
+ if (program.compilerOptions.noEmit || program.hasError()) {
117
+ return;
118
+ }
119
+ const multipleService = services.length > 1;
120
+ for (const serviceRecord of services) {
121
+ if (serviceRecord.versioned) {
122
+ for (const documentRecord of serviceRecord.versions) {
123
+ await emitFile(program, {
124
+ path: resolveOutputFile(serviceRecord.service, multipleService, documentRecord.version),
125
+ content: serializeDocument(documentRecord.document, options.fileType),
126
+ newLine: options.newLine,
127
+ });
128
+ }
129
+ }
130
+ else {
131
+ await emitFile(program, {
132
+ path: resolveOutputFile(serviceRecord.service, multipleService),
133
+ content: serializeDocument(serviceRecord.document, options.fileType),
134
+ newLine: options.newLine,
135
+ });
136
+ }
137
+ }
138
+ }
139
+ function initializeEmitter(service, allHttpAuthentications, defaultAuth, version) {
140
+ var _a;
79
141
  currentService = service;
80
142
  metadataInfo = createMetadataInfo(program, {
81
143
  canonicalVisibility: Visibility.Read,
@@ -87,28 +149,30 @@ function createOAPIEmitter(context, options) {
87
149
  super(emitter, metadataInfo, visibilityUsage, options);
88
150
  }
89
151
  });
90
- const auth = processAuth(service.type);
152
+ const securitySchemes = getOpenAPISecuritySchemes(allHttpAuthentications);
153
+ const security = getOpenAPISecurity(defaultAuth);
154
+ const info = resolveInfo(program, service.type);
91
155
  root = {
92
156
  openapi: "3.0.0",
93
157
  info: {
94
- title: (_a = service.title) !== null && _a !== void 0 ? _a : "(title)",
95
- version: (_b = version !== null && version !== void 0 ? version : service.version) !== null && _b !== void 0 ? _b : "0000-00-00",
96
- description: getDoc(program, service.type),
97
- ...getInfo(program, service.type),
158
+ title: "(title)",
159
+ ...info,
160
+ version: (_a = version !== null && version !== void 0 ? version : info === null || info === void 0 ? void 0 : info.version) !== null && _a !== void 0 ? _a : "0.0.0",
98
161
  },
99
162
  externalDocs: getExternalDocs(program, service.type),
100
163
  tags: [],
101
164
  paths: {},
102
- security: auth === null || auth === void 0 ? void 0 : auth.security,
165
+ security: security.length > 0 ? security : undefined,
103
166
  components: {
104
167
  parameters: {},
105
168
  requestBodies: {},
106
169
  responses: {},
107
170
  schemas: {},
108
171
  examples: {},
109
- securitySchemes: (_c = auth === null || auth === void 0 ? void 0 : auth.securitySchemes) !== null && _c !== void 0 ? _c : {},
172
+ securitySchemes: securitySchemes,
110
173
  },
111
174
  };
175
+ diagnostics = createDiagnosticCollector();
112
176
  const servers = getServers(program, service.type);
113
177
  if (servers) {
114
178
  root.servers = resolveServers(servers);
@@ -140,11 +204,11 @@ function createOAPIEmitter(context, options) {
140
204
  function validateValidServerVariable(program, prop) {
141
205
  const isValid = isValidServerVariableType(program, prop.type);
142
206
  if (!isValid) {
143
- reportDiagnostic(program, {
207
+ diagnostics.add(createDiagnostic({
144
208
  code: "invalid-server-variable",
145
209
  format: { propName: prop.name },
146
210
  target: prop,
147
- });
211
+ }));
148
212
  }
149
213
  return isValid;
150
214
  }
@@ -156,7 +220,7 @@ function createOAPIEmitter(context, options) {
156
220
  continue;
157
221
  }
158
222
  const variable = {
159
- default: prop.default ? getDefaultValue(prop.type, prop.default) : "",
223
+ default: prop.default ? getDefaultValue(program, prop.type, prop.default) : "",
160
224
  description: getDoc(program, prop),
161
225
  };
162
226
  if (prop.type.kind === "Enum") {
@@ -180,12 +244,53 @@ function createOAPIEmitter(context, options) {
180
244
  };
181
245
  });
182
246
  }
183
- async function emitOpenAPI() {
247
+ async function getOpenAPI() {
248
+ const serviceRecords = [];
184
249
  const services = listServices(program);
185
250
  if (services.length === 0) {
186
251
  services.push({ type: program.getGlobalNamespaceType() });
187
252
  }
188
253
  for (const service of services) {
254
+ const versions = buildVersionProjections(program, service.type);
255
+ if (versions.length === 1 && versions[0].version === undefined) {
256
+ // non-versioned spec
257
+ const document = await getProjectedOpenAPIDocument(service, versions[0]);
258
+ if (document === undefined) {
259
+ // an error occurred producing this document, so don't return it
260
+ return serviceRecords;
261
+ }
262
+ serviceRecords.push({
263
+ service,
264
+ versioned: false,
265
+ document: document[0],
266
+ diagnostics: document[1],
267
+ });
268
+ }
269
+ else {
270
+ // versioned spec
271
+ const serviceRecord = {
272
+ service,
273
+ versioned: true,
274
+ versions: [],
275
+ };
276
+ serviceRecords.push(serviceRecord);
277
+ for (const record of versions) {
278
+ const document = await getProjectedOpenAPIDocument(service, record);
279
+ if (document === undefined) {
280
+ // an error occurred producing this document
281
+ continue;
282
+ }
283
+ serviceRecord.versions.push({
284
+ service,
285
+ version: record.version,
286
+ document: document[0],
287
+ diagnostics: document[1],
288
+ });
289
+ }
290
+ }
291
+ }
292
+ return serviceRecords;
293
+ async function getProjectedOpenAPIDocument(service, record) {
189
294
  const commonProjections = [
190
295
  {
191
296
  projectionName: "target",
@@ -193,17 +298,15 @@ function createOAPIEmitter(context, options) {
193
298
  },
194
299
  ];
195
300
  const originalProgram = program;
196
- const versions = buildVersionProjections(program, service.type);
197
- for (const record of versions) {
198
- const projectedProgram = (program = projectProgram(originalProgram, [
199
- ...commonProjections,
200
- ...record.projections,
201
- ]));
202
- const projectedServiceNs = projectedProgram.projector.projectedTypes.get(service.type);
203
- await emitOpenAPIFromVersion(projectedServiceNs === projectedProgram.getGlobalNamespaceType()
204
- ? { type: projectedProgram.getGlobalNamespaceType() }
205
- : getService(program, projectedServiceNs), services.length > 1, record.version);
206
- }
301
+ const projectedProgram = (program = projectProgram(originalProgram, [
302
+ ...commonProjections,
303
+ ...record.projections,
304
+ ]));
305
+ const projectedServiceNs = projectedProgram.projector.projectedTypes.get(service.type);
306
+ const document = await getOpenApiFromVersion(projectedServiceNs === projectedProgram.getGlobalNamespaceType()
307
+ ? { type: projectedProgram.getGlobalNamespaceType() }
308
+ : getService(program, projectedServiceNs), record.version);
309
+ return document;
207
310
  }
208
311
  }
209
312
  function resolveOutputFile(service, multipleService, version) {
@@ -297,11 +400,11 @@ function createOAPIEmitter(context, options) {
297
400
  }
298
401
  }
299
402
  function rangeToOpenAPI(range, diagnosticTarget) {
300
- const reportInvalid = () => reportDiagnostic(program, {
403
+ const reportInvalid = () => diagnostics.add(createDiagnostic({
301
404
  code: "unsupported-status-code-range",
302
405
  format: { start: String(range.start), end: String(range.end) },
303
406
  target: diagnosticTarget,
304
- });
407
+ }));
305
408
  const codes = [];
306
409
  let start = range.start;
307
410
  let end = range.end;
@@ -372,6 +475,7 @@ function createOAPIEmitter(context, options) {
372
475
  parameters: [],
373
476
  },
374
477
  bodies: undefined,
478
+ authentication: operations[0].authentication,
375
479
  responses: new Map(),
376
480
  };
377
481
  for (const [paramName, ops] of paramMap) {
@@ -413,17 +517,20 @@ function createOAPIEmitter(context, options) {
413
517
  }
414
518
  return result;
415
519
  }
416
- async function emitOpenAPIFromVersion(service, multipleService, version) {
417
- initializeEmitter(service, version);
520
+ async function getOpenApiFromVersion(service, version) {
418
521
  try {
419
522
  const httpService = ignoreDiagnostics(getHttpService(program, service.type));
523
+ const auth = resolveAuthentication(httpService);
524
+ initializeEmitter(service, auth.schemes, auth.defaultAuth, version);
420
525
  reportIfNoRoutes(program, httpService.operations);
421
526
  for (const op of resolveOperations(httpService.operations)) {
422
527
  if (op.kind === "shared") {
423
- emitSharedOperation(op);
528
+ const opAuth = auth.operationsAuth.get(op.operations[0]);
529
+ emitSharedOperation(op, opAuth);
424
530
  }
425
531
  else {
426
- emitOperation(op);
532
+ const opAuth = auth.operationsAuth.get(op.operation);
533
+ emitOperation(op, opAuth);
427
534
  }
428
535
  }
429
536
  emitParameters();
@@ -437,14 +544,7 @@ function createOAPIEmitter(context, options) {
437
544
  }
438
545
  }
439
546
  }
440
- if (!program.compilerOptions.noEmit && !program.hasError()) {
441
- // Write out the OpenAPI document to the output path
442
- await emitFile(program, {
443
- path: resolveOutputFile(service, multipleService, version),
444
- content: serializeDocument(root, options.fileType),
445
- newLine: options.newLine,
446
- });
447
- }
547
+ return [root, diagnostics.diagnostics];
448
548
  }
449
549
  catch (err) {
450
550
  if (err instanceof ErrorTypeFoundError) {
@@ -468,7 +568,7 @@ function createOAPIEmitter(context, options) {
468
568
  return undefined;
469
569
  }
470
570
  }
471
- function emitSharedOperation(shared) {
571
+ function emitSharedOperation(shared, authReference) {
472
572
  const { path: fullPath, verb: verb, operations: ops } = shared;
473
573
  if (!root.paths[fullPath]) {
474
574
  root.paths[fullPath] = {};
@@ -510,10 +610,10 @@ function createOAPIEmitter(context, options) {
510
610
  return resolveRequestVisibility(program, op, verb);
511
611
  });
512
612
  if (visibilities.some((v) => v !== visibilities[0])) {
513
- reportDiagnostic(program, {
613
+ diagnostics.add(createDiagnostic({
514
614
  code: "inconsistent-shared-route-request-visibility",
515
615
  target: ops[0],
516
- });
616
+ }));
517
617
  }
518
618
  const visibility = resolveRequestVisibility(program, shared.operations[0], verb);
519
619
  emitEndpointParameters(shared.parameters.parameters, visibility);
@@ -532,12 +632,15 @@ function createOAPIEmitter(context, options) {
532
632
  }
533
633
  attachExtensions(program, op, currentEndpoint);
534
634
  }
635
+ if (authReference) {
636
+ emitSecurity(authReference);
637
+ }
535
638
  }
536
- function emitOperation(operation) {
639
+ function emitOperation(operation, authReference) {
537
640
  const { path: fullPath, operation: op, verb, parameters } = operation;
538
641
  // If path contains a query string, issue msg and don't emit this endpoint
539
642
  if (fullPath.indexOf("?") > 0) {
540
- reportDiagnostic(program, { code: "path-query", target: op });
643
+ diagnostics.add(createDiagnostic({ code: "path-query", target: op }));
541
644
  return;
542
645
  }
543
646
  if (!root.paths[fullPath]) {
@@ -567,6 +670,9 @@ function createOAPIEmitter(context, options) {
567
670
  emitEndpointParameters(parameters.parameters, visibility);
568
671
  emitRequestBody(parameters.body, visibility);
569
672
  emitResponses(operation.responses);
673
+ if (authReference) {
674
+ emitSecurity(authReference);
675
+ }
570
676
  if (isDeprecated(program, op)) {
571
677
  currentEndpoint.deprecated = true;
572
678
  }
@@ -636,11 +742,11 @@ function createOAPIEmitter(context, options) {
636
742
  const existing = obj.headers[key];
637
743
  if (existing) {
638
744
  if (!deepEquals(existing, headerVal)) {
639
- reportDiagnostic(program, {
745
+ diagnostics.add(createDiagnostic({
640
746
  code: "duplicate-header",
641
747
  format: { header: key },
642
748
  target: target,
643
- });
749
+ }));
644
750
  }
645
751
  continue;
646
752
  }
@@ -699,11 +805,11 @@ function createOAPIEmitter(context, options) {
699
805
  case "declaration":
700
806
  return { $ref: `#/components/schemas/${result.name}` };
701
807
  case "circular":
702
- reportDiagnostic(program, {
808
+ diagnostics.add(createDiagnostic({
703
809
  code: "inline-cycle",
704
810
  format: { type: getOpenAPITypeName(program, type, typeNameOptions) },
705
811
  target: type,
706
- });
812
+ }));
707
813
  return {};
708
814
  case "none":
709
815
  return {};
@@ -716,11 +822,11 @@ function createOAPIEmitter(context, options) {
716
822
  case "declaration":
717
823
  return result.value;
718
824
  case "circular":
719
- reportDiagnostic(program, {
825
+ diagnostics.add(createDiagnostic({
720
826
  code: "inline-cycle",
721
827
  format: { type: getOpenAPITypeName(program, type, typeNameOptions) },
722
828
  target: type,
723
- });
829
+ }));
724
830
  return {};
725
831
  case "none":
726
832
  return {};
@@ -869,7 +975,7 @@ function createOAPIEmitter(context, options) {
869
975
  }
870
976
  const schema = applyEncoding(param, applyIntrinsicDecorators(param, typeSchema));
871
977
  if (param.default) {
872
- schema.default = getDefaultValue(param.type, param.default);
978
+ schema.default = getDefaultValue(program, param.type, param.default);
873
979
  }
874
980
  // Description is already provided in the parameter itself.
875
981
  delete schema.description;
@@ -929,14 +1035,14 @@ function createOAPIEmitter(context, options) {
929
1035
  case "simple":
930
1036
  return { style: "simple" };
931
1037
  default:
932
- reportDiagnostic(program, {
1038
+ diagnostics.add(createDiagnostic({
933
1039
  code: "invalid-format",
934
1040
  format: {
935
1041
  paramType: "header",
936
1042
  value: parameter.format,
937
1043
  },
938
1044
  target: parameter.param,
939
- });
1045
+ }));
940
1046
  return undefined;
941
1047
  }
942
1048
  }
@@ -955,14 +1061,14 @@ function createOAPIEmitter(context, options) {
955
1061
  case "pipes":
956
1062
  return { style: "pipeDelimited", explode: false };
957
1063
  default:
958
- reportDiagnostic(program, {
1064
+ diagnostics.add(createDiagnostic({
959
1065
  code: "invalid-format",
960
1066
  format: {
961
1067
  paramType: "query",
962
1068
  value: parameter.format,
963
1069
  },
964
1070
  target: parameter.param,
965
- });
1071
+ }));
966
1072
  return undefined;
967
1073
  }
968
1074
  }
@@ -1014,41 +1120,6 @@ function createOAPIEmitter(context, options) {
1014
1120
  function getSchemaForType(type, visibility) {
1015
1121
  return callSchemaEmitter(type, visibility);
1016
1122
  }
1017
- function getDefaultValue(type, defaultType) {
1018
- var _a;
1019
- switch (defaultType.kind) {
1020
- case "String":
1021
- return defaultType.value;
1022
- case "Number":
1023
- return defaultType.value;
1024
- case "Boolean":
1025
- return defaultType.value;
1026
- case "Tuple":
1027
- compilerAssert(type.kind === "Tuple" || (type.kind === "Model" && isArrayModelType(program, type)), "setting tuple default to non-tuple value");
1028
- if (type.kind === "Tuple") {
1029
- return defaultType.values.map((defaultTupleValue, index) => getDefaultValue(type.values[index], defaultTupleValue));
1030
- }
1031
- else {
1032
- return defaultType.values.map((defaultTuplevalue) => getDefaultValue(type.indexer.value, defaultTuplevalue));
1033
- }
1034
- case "Intrinsic":
1035
- return isNullType(defaultType)
1036
- ? null
1037
- : reportDiagnostic(program, {
1038
- code: "invalid-default",
1039
- format: { type: defaultType.kind },
1040
- target: defaultType,
1041
- });
1042
- case "EnumMember":
1043
- return (_a = defaultType.value) !== null && _a !== void 0 ? _a : defaultType.name;
1044
- default:
1045
- reportDiagnostic(program, {
1046
- code: "invalid-default",
1047
- format: { type: defaultType.kind },
1048
- target: defaultType,
1049
- });
1050
- }
1051
- }
1052
1123
  function attachExtensions(program, type, emitObject) {
1053
1124
  // Attach any OpenAPI extensions
1054
1125
  const extensions = getExtensions(program, type);
@@ -1166,41 +1237,47 @@ function createOAPIEmitter(context, options) {
1166
1237
  target.externalDocs = externalDocs;
1167
1238
  }
1168
1239
  }
1169
- function processAuth(serviceNamespace) {
1170
- const authentication = getAuthentication(program, serviceNamespace);
1171
- if (authentication) {
1172
- return processServiceAuthentication(authentication);
1240
+ function getOpenAPISecuritySchemes(httpAuthentications) {
1241
+ const schemes = {};
1242
+ for (const httpAuth of httpAuthentications) {
1243
+ const scheme = getOpenAPI3Scheme(httpAuth);
1244
+ if (scheme) {
1245
+ schemes[httpAuth.id] = scheme;
1246
+ }
1173
1247
  }
1174
- return undefined;
1248
+ return schemes;
1175
1249
  }
1176
- function processServiceAuthentication(authentication) {
1177
- const oaiSchemes = {};
1178
- const security = [];
1179
- for (const option of authentication.options) {
1180
- const oai3SecurityOption = {};
1181
- for (const scheme of option.schemes) {
1182
- const result = getOpenAPI3Scheme(scheme);
1183
- if (result) {
1184
- oaiSchemes[scheme.id] = result.scheme;
1185
- oai3SecurityOption[scheme.id] = result.scopes;
1250
+ function getOpenAPISecurity(authReference) {
1251
+ const security = authReference.options.map((authOption) => {
1252
+ const securityOption = {};
1253
+ for (const httpAuthRef of authOption.all) {
1254
+ switch (httpAuthRef.kind) {
1255
+ case "noAuth":
1256
+ // should emit "{}" as a security option https://github.com/OAI/OpenAPI-Specification/issues/14#issuecomment-297457320
1257
+ continue;
1258
+ case "oauth2":
1259
+ securityOption[httpAuthRef.auth.id] = httpAuthRef.scopes;
1260
+ continue;
1261
+ default:
1262
+ securityOption[httpAuthRef.auth.id] = [];
1186
1263
  }
1187
1264
  }
1188
- security.push(oai3SecurityOption);
1265
+ return securityOption;
1266
+ });
1267
+ return security;
1268
+ }
1269
+ function emitSecurity(authReference) {
1270
+ const security = getOpenAPISecurity(authReference);
1271
+ if (security.length > 0) {
1272
+ currentEndpoint.security = security;
1189
1273
  }
1190
- return { securitySchemes: oaiSchemes, security };
1191
1274
  }
1192
1275
  function getOpenAPI3Scheme(auth) {
1193
1276
  switch (auth.type) {
1194
1277
  case "http":
1195
- return {
1196
- scheme: { type: "http", scheme: auth.scheme, description: auth.description },
1197
- scopes: [],
1198
- };
1278
+ return { type: "http", scheme: auth.scheme, description: auth.description };
1199
1279
  case "apiKey":
1200
- return {
1201
- scheme: { type: "apiKey", in: auth.in, name: auth.name, description: auth.description },
1202
- scopes: [],
1203
- };
1280
+ return { type: "apiKey", in: auth.in, name: auth.name, description: auth.description };
1204
1281
  case "oauth2":
1205
1282
  const flows = {};
1206
1283
  const scopes = [];
@@ -1213,22 +1290,21 @@ function createOAPIEmitter(context, options) {
1213
1290
  scopes: Object.fromEntries(flow.scopes.map((x) => { var _a; return [x.value, (_a = x.description) !== null && _a !== void 0 ? _a : ""]; })),
1214
1291
  };
1215
1292
  }
1216
- return { scheme: { type: "oauth2", flows, description: auth.description }, scopes };
1293
+ return { type: "oauth2", flows, description: auth.description };
1217
1294
  case "openIdConnect":
1218
1295
  return {
1219
- scheme: {
1220
- type: "openIdConnect",
1221
- openIdConnectUrl: auth.openIdConnectUrl,
1222
- description: auth.description,
1223
- },
1224
- scopes: [],
1296
+ type: "openIdConnect",
1297
+ openIdConnectUrl: auth.openIdConnectUrl,
1298
+ description: auth.description,
1225
1299
  };
1300
+ case "noAuth":
1301
+ return undefined;
1226
1302
  default:
1227
- reportDiagnostic(program, {
1303
+ diagnostics.add(createDiagnostic({
1228
1304
  code: "unsupported-auth",
1229
1305
  format: { authType: auth.type },
1230
1306
  target: currentService.type,
1231
- });
1307
+ }));
1232
1308
  return undefined;
1233
1309
  }
1234
1310
  }