@alagoni97/cli 0.72.3 → 0.72.5
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/codegen/generators/typescript/channels/openapi.js +10 -5
- package/dist/codegen/generators/typescript/channels/protocols/http/client.d.ts +1 -1
- package/dist/codegen/generators/typescript/channels/protocols/http/client.js +40 -30
- package/dist/codegen/generators/typescript/channels/protocols/http/common-types.js +30 -52
- package/dist/codegen/generators/typescript/channels/protocols/http/index.d.ts +1 -1
- package/dist/codegen/generators/typescript/channels/protocols/http/index.js +1 -2
- package/dist/codegen/generators/typescript/channels/protocols/http/security.d.ts +9 -5
- package/dist/codegen/generators/typescript/channels/protocols/http/security.js +50 -23
- package/dist/codegen/generators/typescript/channels/types.d.ts +7 -0
- package/dist/codegen/inputs/openapi/generators/payloads.js +11 -7
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
|
@@ -35,8 +35,12 @@ async function generateTypeScriptChannelsForOpenAPI(context, parameters, payload
|
|
|
35
35
|
const deps = protocolDependencies['http_client'];
|
|
36
36
|
const importExtension = (0, utils_4.resolveImportExtension)(context.generator, context.config);
|
|
37
37
|
(0, utils_1.collectProtocolDependencies)(payloads, parameters, headers, context, deps, importExtension);
|
|
38
|
+
// OAuth2 request handling is only generated when the spec defines an OAuth2
|
|
39
|
+
// scheme; otherwise the narrowed AuthConfig union would make that code fail to
|
|
40
|
+
// type-check.
|
|
41
|
+
const oauth2Enabled = (0, http_1.analyzeSecuritySchemes)(securitySchemes).oauth2;
|
|
38
42
|
// Process all operations and collect renders
|
|
39
|
-
const renders = processOpenAPIOperations(openapiDocument, payloads, parameters);
|
|
43
|
+
const renders = processOpenAPIOperations(openapiDocument, payloads, parameters, oauth2Enabled);
|
|
40
44
|
// Generate common types once (stateless check)
|
|
41
45
|
// Pass security schemes to generate only relevant auth types
|
|
42
46
|
if (protocolCodeFunctions['http_client'].length === 0 && renders.length > 0) {
|
|
@@ -60,14 +64,14 @@ exports.generateTypeScriptChannelsForOpenAPI = generateTypeScriptChannelsForOpen
|
|
|
60
64
|
/**
|
|
61
65
|
* Process all OpenAPI operations and generate HTTP client functions.
|
|
62
66
|
*/
|
|
63
|
-
function processOpenAPIOperations(openapiDocument, payloads, parameters) {
|
|
67
|
+
function processOpenAPIOperations(openapiDocument, payloads, parameters, oauth2Enabled) {
|
|
64
68
|
const renders = [];
|
|
65
69
|
for (const [path, pathItem] of Object.entries(openapiDocument.paths ?? {})) {
|
|
66
70
|
if (!pathItem) {
|
|
67
71
|
continue;
|
|
68
72
|
}
|
|
69
73
|
for (const method of HTTP_METHODS) {
|
|
70
|
-
const render = processOperation(pathItem, method, path, payloads, parameters);
|
|
74
|
+
const render = processOperation(pathItem, method, path, payloads, parameters, oauth2Enabled);
|
|
71
75
|
if (render) {
|
|
72
76
|
renders.push(render);
|
|
73
77
|
}
|
|
@@ -78,7 +82,7 @@ function processOpenAPIOperations(openapiDocument, payloads, parameters) {
|
|
|
78
82
|
/**
|
|
79
83
|
* Process a single OpenAPI operation and generate an HTTP client function.
|
|
80
84
|
*/
|
|
81
|
-
function processOperation(pathItem, method, path, payloads, parameters) {
|
|
85
|
+
function processOperation(pathItem, method, path, payloads, parameters, oauth2Enabled) {
|
|
82
86
|
// eslint-disable-next-line security/detect-object-injection
|
|
83
87
|
const operation = pathItem[method];
|
|
84
88
|
if (!operation) {
|
|
@@ -140,7 +144,8 @@ function processOperation(pathItem, method, path, payloads, parameters) {
|
|
|
140
144
|
channelParameters: parameterModel?.model,
|
|
141
145
|
includesStatusCodes: replyIncludesStatusCodes,
|
|
142
146
|
description,
|
|
143
|
-
deprecated
|
|
147
|
+
deprecated,
|
|
148
|
+
oauth2Enabled
|
|
144
149
|
});
|
|
145
150
|
}
|
|
146
151
|
/**
|
|
@@ -7,4 +7,4 @@ import { RenderHttpParameters } from '../../types';
|
|
|
7
7
|
/**
|
|
8
8
|
* Renders an HTTP fetch client function for a specific API operation.
|
|
9
9
|
*/
|
|
10
|
-
export declare function renderHttpFetchClient({ requestTopic, requestMessageType, requestMessageModule, replyMessageType, replyMessageModule, channelParameters, method, servers, subName, functionName, includesStatusCodes, description, deprecated }: RenderHttpParameters): HttpRenderType;
|
|
10
|
+
export declare function renderHttpFetchClient({ requestTopic, requestMessageType, requestMessageModule, replyMessageType, replyMessageModule, channelParameters, method, servers, subName, functionName, includesStatusCodes, description, deprecated, oauth2Enabled }: RenderHttpParameters): HttpRenderType;
|
|
@@ -7,7 +7,7 @@ const utils_2 = require("../../utils");
|
|
|
7
7
|
/**
|
|
8
8
|
* Renders an HTTP fetch client function for a specific API operation.
|
|
9
9
|
*/
|
|
10
|
-
function renderHttpFetchClient({ requestTopic, requestMessageType, requestMessageModule, replyMessageType, replyMessageModule, channelParameters, method, servers = [], subName = (0, utils_1.pascalCase)(requestTopic), functionName = `${method.toLowerCase()}${subName}`, includesStatusCodes = false, description, deprecated }) {
|
|
10
|
+
function renderHttpFetchClient({ requestTopic, requestMessageType, requestMessageModule, replyMessageType, replyMessageModule, channelParameters, method, servers = [], subName = (0, utils_1.pascalCase)(requestTopic), functionName = `${method.toLowerCase()}${subName}`, includesStatusCodes = false, description, deprecated, oauth2Enabled = true }) {
|
|
11
11
|
const messageType = requestMessageModule
|
|
12
12
|
? `${requestMessageModule}.${requestMessageType}`
|
|
13
13
|
: requestMessageType;
|
|
@@ -39,7 +39,8 @@ function renderHttpFetchClient({ requestTopic, requestMessageType, requestMessag
|
|
|
39
39
|
method,
|
|
40
40
|
servers,
|
|
41
41
|
includesStatusCodes,
|
|
42
|
-
jsDoc
|
|
42
|
+
jsDoc,
|
|
43
|
+
oauth2Enabled
|
|
43
44
|
});
|
|
44
45
|
const code = `${contextInterface}
|
|
45
46
|
|
|
@@ -80,7 +81,7 @@ function generateContextInterface(interfaceName, messageType, hasParameters, met
|
|
|
80
81
|
* Generate the function implementation
|
|
81
82
|
*/
|
|
82
83
|
function generateFunctionImplementation(params) {
|
|
83
|
-
const { functionName, contextInterfaceName, replyType, replyMessageModule, replyMessageType, messageType, requestTopic, hasParameters, method, servers, includesStatusCodes, jsDoc } = params;
|
|
84
|
+
const { functionName, contextInterfaceName, replyType, replyMessageModule, replyMessageType, messageType, requestTopic, hasParameters, method, servers, includesStatusCodes, jsDoc, oauth2Enabled } = params;
|
|
84
85
|
const defaultServer = servers[0] ?? "'localhost:3000'";
|
|
85
86
|
const hasBody = messageType && ['POST', 'PUT', 'PATCH'].includes(method.toUpperCase());
|
|
86
87
|
// Generate URL building code
|
|
@@ -108,6 +109,40 @@ function generateFunctionImplementation(params) {
|
|
|
108
109
|
}
|
|
109
110
|
// Generate default context for optional context parameter
|
|
110
111
|
const contextDefault = !hasBody && !hasParameters ? ' = {}' : '';
|
|
112
|
+
// OAuth2 request handling is only emitted when the API actually defines an
|
|
113
|
+
// OAuth2 scheme; otherwise these branches reference fields/functions that the
|
|
114
|
+
// narrowed AuthConfig union no longer carries and would fail to type-check.
|
|
115
|
+
const oauth2ValidateBlock = oauth2Enabled
|
|
116
|
+
? ` // Validate OAuth2 config if present
|
|
117
|
+
if (config.auth?.type === 'oauth2' && AUTH_FEATURES.oauth2) {
|
|
118
|
+
validateOAuth2Config(config.auth);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
`
|
|
122
|
+
: '';
|
|
123
|
+
const oauth2TokenBlock = oauth2Enabled
|
|
124
|
+
? `
|
|
125
|
+
// Handle OAuth2 token flows that require getting a token first
|
|
126
|
+
if (config.auth?.type === 'oauth2' && !config.auth.accessToken && AUTH_FEATURES.oauth2) {
|
|
127
|
+
const tokenFlowResponse = await handleOAuth2TokenFlow(config.auth, requestParams, makeRequest, config.retry);
|
|
128
|
+
if (tokenFlowResponse) {
|
|
129
|
+
response = tokenFlowResponse;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Handle 401 with token refresh
|
|
134
|
+
if (response.status === 401 && config.auth?.type === 'oauth2' && AUTH_FEATURES.oauth2) {
|
|
135
|
+
try {
|
|
136
|
+
const refreshResponse = await handleTokenRefresh(config.auth, requestParams, makeRequest, config.retry);
|
|
137
|
+
if (refreshResponse) {
|
|
138
|
+
response = refreshResponse;
|
|
139
|
+
}
|
|
140
|
+
} catch {
|
|
141
|
+
throw new Error('Unauthorized');
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
`
|
|
145
|
+
: '';
|
|
111
146
|
return `${jsDoc}
|
|
112
147
|
async function ${functionName}(context: ${contextInterfaceName}${contextDefault}): Promise<HttpClientResponse<${replyType}>> {
|
|
113
148
|
// Apply defaults
|
|
@@ -117,12 +152,7 @@ async function ${functionName}(context: ${contextInterfaceName}${contextDefault}
|
|
|
117
152
|
...context,
|
|
118
153
|
};
|
|
119
154
|
|
|
120
|
-
//
|
|
121
|
-
if (config.auth?.type === 'oauth2' && AUTH_FEATURES.oauth2) {
|
|
122
|
-
validateOAuth2Config(config.auth);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Build headers
|
|
155
|
+
${oauth2ValidateBlock} // Build headers
|
|
126
156
|
${headersInit}
|
|
127
157
|
|
|
128
158
|
// Build URL
|
|
@@ -166,27 +196,7 @@ async function ${functionName}(context: ${contextInterfaceName}${contextDefault}
|
|
|
166
196
|
if (config.hooks?.afterResponse) {
|
|
167
197
|
response = await config.hooks.afterResponse(response, requestParams);
|
|
168
198
|
}
|
|
169
|
-
|
|
170
|
-
// Handle OAuth2 token flows that require getting a token first
|
|
171
|
-
if (config.auth?.type === 'oauth2' && !config.auth.accessToken && AUTH_FEATURES.oauth2) {
|
|
172
|
-
const tokenFlowResponse = await handleOAuth2TokenFlow(config.auth, requestParams, makeRequest, config.retry);
|
|
173
|
-
if (tokenFlowResponse) {
|
|
174
|
-
response = tokenFlowResponse;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// Handle 401 with token refresh
|
|
179
|
-
if (response.status === 401 && config.auth?.type === 'oauth2' && AUTH_FEATURES.oauth2) {
|
|
180
|
-
try {
|
|
181
|
-
const refreshResponse = await handleTokenRefresh(config.auth, requestParams, makeRequest, config.retry);
|
|
182
|
-
if (refreshResponse) {
|
|
183
|
-
response = refreshResponse;
|
|
184
|
-
}
|
|
185
|
-
} catch {
|
|
186
|
-
throw new Error('Unauthorized');
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
199
|
+
${oauth2TokenBlock}
|
|
190
200
|
// Handle error responses
|
|
191
201
|
if (!response.ok) {
|
|
192
202
|
handleHttpError(response.status, response.statusText);
|
|
@@ -13,6 +13,33 @@ const security_1 = require("./security");
|
|
|
13
13
|
function renderHttpCommonTypes(securitySchemes) {
|
|
14
14
|
const requirements = (0, security_1.analyzeSecuritySchemes)(securitySchemes);
|
|
15
15
|
const securityTypes = (0, security_1.renderSecurityTypes)(securitySchemes, requirements);
|
|
16
|
+
const applyAuthCases = (0, security_1.renderApplyAuthCases)(requirements);
|
|
17
|
+
// Only emit the AUTH_FEATURES flag when OAuth2 code is generated, and the
|
|
18
|
+
// API_KEY_DEFAULTS const when an apiKey case is generated - otherwise they
|
|
19
|
+
// become unused declarations in the output.
|
|
20
|
+
const authFeaturesBlock = requirements.oauth2
|
|
21
|
+
? `
|
|
22
|
+
/**
|
|
23
|
+
* Feature flags indicating which auth types are available.
|
|
24
|
+
* Used internally to conditionally call auth-specific helpers.
|
|
25
|
+
*/
|
|
26
|
+
const AUTH_FEATURES = {
|
|
27
|
+
oauth2: ${requirements.oauth2}
|
|
28
|
+
} as const;
|
|
29
|
+
`
|
|
30
|
+
: '';
|
|
31
|
+
const apiKeyDefaultsBlock = requirements.apiKey
|
|
32
|
+
? `
|
|
33
|
+
/**
|
|
34
|
+
* Default values for API key authentication derived from the spec.
|
|
35
|
+
* These match the defaults documented in the ApiKeyAuth interface.
|
|
36
|
+
*/
|
|
37
|
+
const API_KEY_DEFAULTS = {
|
|
38
|
+
name: '${(0, security_1.escapeStringForCodeGen)((0, security_1.getApiKeyDefaults)(requirements.apiKeySchemes).name)}',
|
|
39
|
+
in: '${(0, security_1.escapeStringForCodeGen)((0, security_1.getApiKeyDefaults)(requirements.apiKeySchemes).in)}' as 'header' | 'query' | 'cookie'
|
|
40
|
+
} as const;
|
|
41
|
+
`
|
|
42
|
+
: '';
|
|
16
43
|
return `// ============================================================================
|
|
17
44
|
// Common Types - Shared across all HTTP client functions
|
|
18
45
|
// ============================================================================
|
|
@@ -95,24 +122,7 @@ export interface TokenResponse {
|
|
|
95
122
|
}
|
|
96
123
|
|
|
97
124
|
${securityTypes}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Feature flags indicating which auth types are available.
|
|
101
|
-
* Used internally to conditionally call auth-specific helpers.
|
|
102
|
-
*/
|
|
103
|
-
const AUTH_FEATURES = {
|
|
104
|
-
oauth2: ${requirements.oauth2}
|
|
105
|
-
} as const;
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Default values for API key authentication derived from the spec.
|
|
109
|
-
* These match the defaults documented in the ApiKeyAuth interface.
|
|
110
|
-
*/
|
|
111
|
-
const API_KEY_DEFAULTS = {
|
|
112
|
-
name: '${(0, security_1.escapeStringForCodeGen)((0, security_1.getApiKeyDefaults)(requirements.apiKeySchemes).name)}',
|
|
113
|
-
in: '${(0, security_1.escapeStringForCodeGen)((0, security_1.getApiKeyDefaults)(requirements.apiKeySchemes).in)}' as 'header' | 'query' | 'cookie'
|
|
114
|
-
} as const;
|
|
115
|
-
|
|
125
|
+
${authFeaturesBlock}${apiKeyDefaultsBlock}
|
|
116
126
|
// ============================================================================
|
|
117
127
|
// Pagination Types
|
|
118
128
|
// ============================================================================
|
|
@@ -294,39 +304,7 @@ function applyAuth(
|
|
|
294
304
|
if (!auth) return { headers, url };
|
|
295
305
|
|
|
296
306
|
switch (auth.type) {
|
|
297
|
-
|
|
298
|
-
headers['Authorization'] = \`Bearer \${auth.token}\`;
|
|
299
|
-
break;
|
|
300
|
-
|
|
301
|
-
case 'basic': {
|
|
302
|
-
const credentials = Buffer.from(\`\${auth.username}:\${auth.password}\`).toString('base64');
|
|
303
|
-
headers['Authorization'] = \`Basic \${credentials}\`;
|
|
304
|
-
break;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
case 'apiKey': {
|
|
308
|
-
const keyName = auth.name ?? API_KEY_DEFAULTS.name;
|
|
309
|
-
const keyIn = auth.in ?? API_KEY_DEFAULTS.in;
|
|
310
|
-
|
|
311
|
-
if (keyIn === 'header') {
|
|
312
|
-
headers[keyName] = auth.key;
|
|
313
|
-
} else if (keyIn === 'query') {
|
|
314
|
-
const separator = url.includes('?') ? '&' : '?';
|
|
315
|
-
url = \`\${url}\${separator}\${keyName}=\${encodeURIComponent(auth.key)}\`;
|
|
316
|
-
} else if (keyIn === 'cookie') {
|
|
317
|
-
headers['Cookie'] = \`\${keyName}=\${auth.key}\`;
|
|
318
|
-
}
|
|
319
|
-
break;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
case 'oauth2': {
|
|
323
|
-
// If we have an access token, use it directly
|
|
324
|
-
// Token flows (client_credentials, password) are handled separately
|
|
325
|
-
if (auth.accessToken) {
|
|
326
|
-
headers['Authorization'] = \`Bearer \${auth.accessToken}\`;
|
|
327
|
-
}
|
|
328
|
-
break;
|
|
329
|
-
}
|
|
307
|
+
${applyAuthCases}
|
|
330
308
|
}
|
|
331
309
|
|
|
332
310
|
return { headers, url };
|
|
@@ -792,7 +770,7 @@ function applyTypedHeaders(
|
|
|
792
770
|
|
|
793
771
|
return headers;
|
|
794
772
|
}
|
|
795
|
-
${requirements.oauth2 ? (0, security_1.renderOAuth2Helpers)() :
|
|
773
|
+
${requirements.oauth2 ? (0, security_1.renderOAuth2Helpers)() : ''}
|
|
796
774
|
// ============================================================================
|
|
797
775
|
// Generated HTTP Client Functions
|
|
798
776
|
// ============================================================================`;
|
|
@@ -3,6 +3,6 @@ import { ChannelInterface } from '@asyncapi/parser';
|
|
|
3
3
|
import { renderHttpCommonTypes } from './common-types';
|
|
4
4
|
import { renderHttpFetchClient } from './client';
|
|
5
5
|
export { renderHttpCommonTypes, renderHttpFetchClient };
|
|
6
|
-
export { analyzeSecuritySchemes, escapeStringForCodeGen, getApiKeyDefaults, renderOAuth2Helpers,
|
|
6
|
+
export { analyzeSecuritySchemes, escapeStringForCodeGen, getApiKeyDefaults, renderOAuth2Helpers, renderSecurityTypes, type AuthTypeRequirements } from './security';
|
|
7
7
|
export type { SecuritySchemeOptions } from '../../types';
|
|
8
8
|
export declare function generatehttpChannels(context: TypeScriptChannelsGeneratorContext, channel: ChannelInterface, protocolCodeFunctions: Record<string, string[]>, externalProtocolFunctionInformation: Record<string, TypeScriptChannelRenderedFunctionType[]>, dependencies: string[]): Promise<void>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generatehttpChannels = exports.renderSecurityTypes = exports.
|
|
3
|
+
exports.generatehttpChannels = exports.renderSecurityTypes = exports.renderOAuth2Helpers = exports.getApiKeyDefaults = exports.escapeStringForCodeGen = exports.analyzeSecuritySchemes = exports.renderHttpFetchClient = exports.renderHttpCommonTypes = void 0;
|
|
4
4
|
/* eslint-disable security/detect-object-injection */
|
|
5
5
|
const types_1 = require("../../types");
|
|
6
6
|
const utils_1 = require("../../../../../utils");
|
|
@@ -16,7 +16,6 @@ Object.defineProperty(exports, "analyzeSecuritySchemes", { enumerable: true, get
|
|
|
16
16
|
Object.defineProperty(exports, "escapeStringForCodeGen", { enumerable: true, get: function () { return security_1.escapeStringForCodeGen; } });
|
|
17
17
|
Object.defineProperty(exports, "getApiKeyDefaults", { enumerable: true, get: function () { return security_1.getApiKeyDefaults; } });
|
|
18
18
|
Object.defineProperty(exports, "renderOAuth2Helpers", { enumerable: true, get: function () { return security_1.renderOAuth2Helpers; } });
|
|
19
|
-
Object.defineProperty(exports, "renderOAuth2Stubs", { enumerable: true, get: function () { return security_1.renderOAuth2Stubs; } });
|
|
20
19
|
Object.defineProperty(exports, "renderSecurityTypes", { enumerable: true, get: function () { return security_1.renderSecurityTypes; } });
|
|
21
20
|
async function generatehttpChannels(context, channel, protocolCodeFunctions, externalProtocolFunctionInformation, dependencies) {
|
|
22
21
|
const { generator, parameter, topic } = context;
|
|
@@ -36,11 +36,15 @@ export declare function getApiKeyDefaults(apiKeySchemes: SecuritySchemeOptions[]
|
|
|
36
36
|
*/
|
|
37
37
|
export declare function renderSecurityTypes(schemes: SecuritySchemeOptions[] | undefined, requirements?: AuthTypeRequirements): string;
|
|
38
38
|
/**
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
* Renders the `switch (auth.type)` case blocks for the generated `applyAuth`
|
|
40
|
+
* helper, emitting only the branches whose auth interfaces were generated.
|
|
41
|
+
*
|
|
42
|
+
* A case for an auth type absent from the (possibly narrowed) AuthConfig union
|
|
43
|
+
* would not type-check: the discriminant comparison has no overlap and the
|
|
44
|
+
* type-specific fields (`token`, `username`, `key`, `accessToken`, ...) don't
|
|
45
|
+
* exist on the union members that remain.
|
|
46
|
+
*/
|
|
47
|
+
export declare function renderApplyAuthCases(requirements: AuthTypeRequirements): string;
|
|
44
48
|
/**
|
|
45
49
|
* Generates OAuth2-specific helper functions.
|
|
46
50
|
* Only included when OAuth2 auth is needed.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.renderOAuth2Helpers = exports.
|
|
3
|
+
exports.renderOAuth2Helpers = exports.renderApplyAuthCases = exports.renderSecurityTypes = exports.getApiKeyDefaults = exports.analyzeSecuritySchemes = exports.escapeStringForCodeGen = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Escapes special characters in strings that will be interpolated into generated code.
|
|
6
6
|
* Prevents syntax errors when OpenAPI spec values contain quotes, backticks, or template expressions.
|
|
@@ -310,30 +310,57 @@ ${bearerSection}${basicSection}${apiKeySection}${oauth2Section}${renderAuthConfi
|
|
|
310
310
|
}
|
|
311
311
|
exports.renderSecurityTypes = renderSecurityTypes;
|
|
312
312
|
/**
|
|
313
|
-
*
|
|
314
|
-
*
|
|
315
|
-
*
|
|
313
|
+
* Renders the `switch (auth.type)` case blocks for the generated `applyAuth`
|
|
314
|
+
* helper, emitting only the branches whose auth interfaces were generated.
|
|
315
|
+
*
|
|
316
|
+
* A case for an auth type absent from the (possibly narrowed) AuthConfig union
|
|
317
|
+
* would not type-check: the discriminant comparison has no overlap and the
|
|
318
|
+
* type-specific fields (`token`, `username`, `key`, `accessToken`, ...) don't
|
|
319
|
+
* exist on the union members that remain.
|
|
316
320
|
*/
|
|
317
|
-
function
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
321
|
+
function renderApplyAuthCases(requirements) {
|
|
322
|
+
const cases = [];
|
|
323
|
+
if (requirements.bearer) {
|
|
324
|
+
cases.push(` case 'bearer':
|
|
325
|
+
headers['Authorization'] = \`Bearer \${auth.token}\`;
|
|
326
|
+
break;`);
|
|
327
|
+
}
|
|
328
|
+
if (requirements.basic) {
|
|
329
|
+
cases.push(` case 'basic': {
|
|
330
|
+
const credentials = Buffer.from(\`\${auth.username}:\${auth.password}\`).toString('base64');
|
|
331
|
+
headers['Authorization'] = \`Basic \${credentials}\`;
|
|
332
|
+
break;
|
|
333
|
+
}`);
|
|
334
|
+
}
|
|
335
|
+
if (requirements.apiKey) {
|
|
336
|
+
cases.push(` case 'apiKey': {
|
|
337
|
+
const keyName = auth.name ?? API_KEY_DEFAULTS.name;
|
|
338
|
+
const keyIn = auth.in ?? API_KEY_DEFAULTS.in;
|
|
339
|
+
|
|
340
|
+
if (keyIn === 'header') {
|
|
341
|
+
headers[keyName] = auth.key;
|
|
342
|
+
} else if (keyIn === 'query') {
|
|
343
|
+
const separator = url.includes('?') ? '&' : '?';
|
|
344
|
+
url = \`\${url}\${separator}\${keyName}=\${encodeURIComponent(auth.key)}\`;
|
|
345
|
+
} else if (keyIn === 'cookie') {
|
|
346
|
+
headers['Cookie'] = \`\${keyName}=\${auth.key}\`;
|
|
347
|
+
}
|
|
348
|
+
break;
|
|
349
|
+
}`);
|
|
350
|
+
}
|
|
351
|
+
if (requirements.oauth2) {
|
|
352
|
+
cases.push(` case 'oauth2': {
|
|
353
|
+
// If we have an access token, use it directly
|
|
354
|
+
// Token flows (client_credentials, password) are handled separately
|
|
355
|
+
if (auth.accessToken) {
|
|
356
|
+
headers['Authorization'] = \`Bearer \${auth.accessToken}\`;
|
|
357
|
+
}
|
|
358
|
+
break;
|
|
359
|
+
}`);
|
|
360
|
+
}
|
|
361
|
+
return cases.join('\n\n');
|
|
335
362
|
}
|
|
336
|
-
exports.
|
|
363
|
+
exports.renderApplyAuthCases = renderApplyAuthCases;
|
|
337
364
|
/**
|
|
338
365
|
* Generates OAuth2-specific helper functions.
|
|
339
366
|
* Only included when OAuth2 auth is needed.
|
|
@@ -177,5 +177,12 @@ export interface RenderHttpParameters {
|
|
|
177
177
|
description?: string;
|
|
178
178
|
/** Whether the operation is marked as deprecated in the API specification */
|
|
179
179
|
deprecated?: boolean;
|
|
180
|
+
/**
|
|
181
|
+
* Whether OAuth2 auth is available for this API. When false, OAuth2-specific
|
|
182
|
+
* request handling is omitted so the generated function type-checks against an
|
|
183
|
+
* AuthConfig union that was narrowed to exclude OAuth2. Defaults to true to keep
|
|
184
|
+
* the AsyncAPI path (which generates all auth types) unchanged.
|
|
185
|
+
*/
|
|
186
|
+
oauth2Enabled?: boolean;
|
|
180
187
|
}
|
|
181
188
|
export type SupportedProtocols = 'nats' | 'kafka' | 'mqtt' | 'amqp' | 'event_source' | 'http_client' | 'websocket';
|
|
@@ -104,17 +104,21 @@ function extractPayloadsFromOperations(paths) {
|
|
|
104
104
|
method,
|
|
105
105
|
path: pathKey
|
|
106
106
|
});
|
|
107
|
-
// Extract request payload schema
|
|
107
|
+
// Extract request payload schema.
|
|
108
|
+
// Prefer the 3.x `requestBody`: 3.x operations also carry a `parameters`
|
|
109
|
+
// array (path/query/header), so presence of `parameters` cannot be used
|
|
110
|
+
// to detect 2.0 - doing so would drop the body on any 3.x operation that
|
|
111
|
+
// declares parameters. The 2.0 body lives in a `parameters` entry with
|
|
112
|
+
// `in: 'body'`, so fall back to that only when there is no `requestBody`.
|
|
108
113
|
let requestSchema = null;
|
|
109
|
-
|
|
110
|
-
if ('parameters' in operationObj && operationObj.parameters) {
|
|
111
|
-
// OpenAPI 2.0 style
|
|
112
|
-
requestSchema = extractOpenAPI2RequestSchema(operationObj.parameters);
|
|
113
|
-
}
|
|
114
|
-
else if ('requestBody' in operationObj && operationObj.requestBody) {
|
|
114
|
+
if ('requestBody' in operationObj && operationObj.requestBody) {
|
|
115
115
|
// OpenAPI 3.x style
|
|
116
116
|
requestSchema = extractOpenAPI3RequestSchema(operationObj.requestBody);
|
|
117
117
|
}
|
|
118
|
+
else if ('parameters' in operationObj && operationObj.parameters) {
|
|
119
|
+
// OpenAPI 2.0 style (body carried as a `in: 'body'` parameter)
|
|
120
|
+
requestSchema = extractOpenAPI2RequestSchema(operationObj.parameters);
|
|
121
|
+
}
|
|
118
122
|
if (requestSchema) {
|
|
119
123
|
const requestSchemaId = (0, utils_1.pascalCase)(`${operationId}_Request`);
|
|
120
124
|
requestPayloads[operationId] = {
|
package/oclif.manifest.json
CHANGED