oapiex 0.2.2 → 0.3.1
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/bin/cli.mjs +62 -9
- package/dist/index.cjs +286 -21
- package/dist/index.d.ts +62 -1
- package/dist/index.mjs +286 -21
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -1142,11 +1142,18 @@ var TypeScriptModuleRenderer = class {
|
|
|
1142
1142
|
"export interface OpenApiMediaTypeDefinition<TExample = unknown> {\n schema?: OpenApiSchemaDefinition\n example?: TExample\n}",
|
|
1143
1143
|
"export interface OpenApiResponseDefinition<_TResponse = unknown, TExample = unknown> {\n description: string\n content?: Record<string, OpenApiMediaTypeDefinition<TExample>>\n}",
|
|
1144
1144
|
"export interface OpenApiRequestBodyDefinition<TInput = unknown> {\n description?: string\n required: boolean\n content: Record<string, OpenApiMediaTypeDefinition<TInput>>\n}",
|
|
1145
|
-
"export interface
|
|
1145
|
+
"export interface OpenApiOauthFlowDefinition {\n authorizationUrl?: string\n tokenUrl?: string\n refreshUrl?: string\n scopes?: Record<string, string>\n}",
|
|
1146
|
+
"export type OpenApiSecurityRequirementDefinition = Record<string, string[]>",
|
|
1147
|
+
"export type OpenApiSecuritySchemeDefinition =\n | {\n type: 'http'\n description?: string\n scheme: string\n bearerFormat?: string\n }\n | {\n type: 'apiKey'\n description?: string\n name: string\n in: 'query' | 'header' | 'cookie'\n }\n | {\n type: 'oauth2'\n description?: string\n flows?: Record<string, OpenApiOauthFlowDefinition>\n }\n | {\n type: 'openIdConnect'\n description?: string\n openIdConnectUrl: string\n }",
|
|
1148
|
+
"export interface OpenApiComponentsDefinition {\n securitySchemes?: Record<string, OpenApiSecuritySchemeDefinition>\n}",
|
|
1149
|
+
"export interface OpenApiOperationDefinition<_TResponse = unknown, TResponseExample = unknown, TInput = Record<string, never>, _TQuery = Record<string, never>, _THeader = Record<string, never>, _TParams = Record<string, never>> {\n summary?: string\n description?: string\n operationId?: string\n security?: OpenApiSecurityRequirementDefinition[]\n parameters?: OpenApiParameterDefinition[]\n requestBody?: OpenApiRequestBodyDefinition<TInput>\n responses: Record<string, OpenApiResponseDefinition<_TResponse, TResponseExample>>\n}",
|
|
1146
1150
|
"export interface OpenApiSdkParameterManifest {\n name: string\n accessor: string\n in: 'query' | 'header' | 'path'\n required: boolean\n description?: string\n}",
|
|
1147
|
-
"export interface
|
|
1151
|
+
"export interface OpenApiSdkSecurityRequirementSchemeManifest {\n name: string\n scopes: string[]\n}",
|
|
1152
|
+
"export interface OpenApiSdkSecurityRequirementManifest {\n schemes: OpenApiSdkSecurityRequirementSchemeManifest[]\n}",
|
|
1153
|
+
"export interface OpenApiSdkSecuritySchemeManifest {\n name: string\n helperName: string\n description?: string\n type: 'http' | 'apiKey' | 'oauth2' | 'openIdConnect'\n authType: 'bearer' | 'basic' | 'apiKey' | 'oauth2'\n scheme?: string\n bearerFormat?: string\n in?: 'header' | 'query' | 'cookie'\n parameterName?: string\n openIdConnectUrl?: string\n scopes?: string[]\n}",
|
|
1154
|
+
"export interface OpenApiSdkOperationManifest {\n path: string\n method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'\n methodName: string\n summary?: string\n description?: string\n operationId?: string\n requestBodyDescription?: string\n responseDescription?: string\n responseType: string\n inputType: string\n queryType: string\n headerType: string\n paramsType: string\n hasBody: boolean\n bodyRequired: boolean\n pathParams: OpenApiSdkParameterManifest[]\n queryParams: OpenApiSdkParameterManifest[]\n headerParams: OpenApiSdkParameterManifest[]\n security?: OpenApiSdkSecurityRequirementManifest[]\n}",
|
|
1148
1155
|
"export interface OpenApiSdkGroupManifest {\n className: string\n propertyName: string\n operations: OpenApiSdkOperationManifest[]\n}",
|
|
1149
|
-
"export interface OpenApiSdkManifest {\n groups: OpenApiSdkGroupManifest[]\n}",
|
|
1156
|
+
"export interface OpenApiSdkManifest {\n groups: OpenApiSdkGroupManifest[]\n securitySchemes: OpenApiSdkSecuritySchemeManifest[]\n security?: OpenApiSdkSecurityRequirementManifest[]\n}",
|
|
1150
1157
|
"export interface OpenApiRuntimeBundle<TApi = unknown> {\n document: unknown\n manifest: OpenApiSdkManifest\n __api?: TApi\n}",
|
|
1151
1158
|
Object.entries(document.paths).map(([path, operations]) => {
|
|
1152
1159
|
const pathTypeName = this.derivePathTypeName(path);
|
|
@@ -1164,7 +1171,7 @@ var TypeScriptModuleRenderer = class {
|
|
|
1164
1171
|
}).join("\n\n"), `export interface ${pathTypeName} {\n${Object.keys(operations).map((method) => ` ${method}: ${this.deriveOperationInterfaceName(path, method)}`).join("\n")}\n}`].join("\n\n");
|
|
1165
1172
|
}).join("\n\n"),
|
|
1166
1173
|
`export interface Paths {\n${Object.keys(document.paths).map((path) => ` ${this.formatPropertyKey(path)}: ${this.derivePathTypeName(path)}`).join("\n")}\n}`,
|
|
1167
|
-
`export interface ${rootTypeName} {\n openapi: '3.1.0'\n info: OpenApiInfo\n paths: Paths\n}`
|
|
1174
|
+
`export interface ${rootTypeName} {\n openapi: '3.1.0'\n info: OpenApiInfo\n components?: OpenApiComponentsDefinition\n security?: OpenApiSecurityRequirementDefinition[]\n paths: Paths\n}`
|
|
1168
1175
|
].join("\n\n");
|
|
1169
1176
|
}
|
|
1170
1177
|
renderSdkApiInterface(rootTypeName, manifest) {
|
|
@@ -1259,7 +1266,7 @@ var TypeScriptModuleRenderer = class {
|
|
|
1259
1266
|
if (value.length === 0) return "[]";
|
|
1260
1267
|
const nextIndent = this.indent(indentLevel + 1);
|
|
1261
1268
|
const currentIndent = this.indent(indentLevel);
|
|
1262
|
-
return `[\n${value.map((entry) => `${nextIndent}${this.renderLiteral(entry, indentLevel + 1)}`).join(",\n")}\n${currentIndent}]
|
|
1269
|
+
return `\n[`.startsWith("\n[") ? `[\n${value.map((entry) => `${nextIndent}${this.renderLiteral(entry, indentLevel + 1)}`).join(",\n")}\n${currentIndent}]` : "[]";
|
|
1263
1270
|
}
|
|
1264
1271
|
if (typeof value === "object") {
|
|
1265
1272
|
const entries = Object.entries(value);
|
|
@@ -2042,9 +2049,22 @@ var TypeScriptShapeBuilder = class {
|
|
|
2042
2049
|
var TypeScriptTypeBuilder = class {
|
|
2043
2050
|
naming = new TypeScriptNamingSupport();
|
|
2044
2051
|
shapes = new TypeScriptShapeBuilder(this.naming);
|
|
2052
|
+
/**
|
|
2053
|
+
* Creates a new generator context, which holds the state of the type generation process.
|
|
2054
|
+
*
|
|
2055
|
+
* @returns
|
|
2056
|
+
*/
|
|
2045
2057
|
createContext() {
|
|
2046
2058
|
return this.shapes.createContext();
|
|
2047
2059
|
}
|
|
2060
|
+
/**
|
|
2061
|
+
* Collects semantic models from the given OpenAPI document, which represent the various
|
|
2062
|
+
* shapes and types that need to be generated for the SDK, along with their associated
|
|
2063
|
+
* metadata such as paths, methods, and roles.
|
|
2064
|
+
*
|
|
2065
|
+
* @param document The OpenAPI document to extract semantic models from.
|
|
2066
|
+
* @returns An array of semantic models representing the shapes and types for the SDK.
|
|
2067
|
+
*/
|
|
2048
2068
|
collectSemanticModels(document) {
|
|
2049
2069
|
const models = [];
|
|
2050
2070
|
for (const [path, operations] of Object.entries(document.paths)) {
|
|
@@ -2107,9 +2127,20 @@ var TypeScriptTypeBuilder = class {
|
|
|
2107
2127
|
}
|
|
2108
2128
|
return models;
|
|
2109
2129
|
}
|
|
2130
|
+
/**
|
|
2131
|
+
* Builds the SDK manifest from the given OpenAPI document, using the provided operation
|
|
2132
|
+
* type references and naming strategy options.
|
|
2133
|
+
*
|
|
2134
|
+
* @param document The OpenAPI document to build the SDK manifest from.
|
|
2135
|
+
* @param operationTypeRefs A map of operation type references.
|
|
2136
|
+
* @param options Naming strategy options for the SDK manifest.
|
|
2137
|
+
* @returns The generated SDK manifest.
|
|
2138
|
+
*/
|
|
2110
2139
|
buildSdkManifest(document, operationTypeRefs, options = {}) {
|
|
2111
2140
|
const sdkGroupNamesBySignature = this.naming.deriveSdkGroupNamesBySignature(document, options.namespaceStrategy ?? "smart");
|
|
2112
2141
|
const groups = /* @__PURE__ */ new Map();
|
|
2142
|
+
const securitySchemes = this.buildSecuritySchemes(document);
|
|
2143
|
+
const globalSecurity = this.buildSecurityRequirements(document.security);
|
|
2113
2144
|
for (const [path, operations] of Object.entries(document.paths)) {
|
|
2114
2145
|
const staticSignature = this.naming.getStaticPathSegments(path).join("/");
|
|
2115
2146
|
const className = sdkGroupNamesBySignature.get(staticSignature) ?? "Resource";
|
|
@@ -2146,34 +2177,96 @@ var TypeScriptTypeBuilder = class {
|
|
|
2146
2177
|
bodyRequired: operation.requestBody?.required ?? false,
|
|
2147
2178
|
pathParams: this.naming.createSdkParameterManifest(operation.parameters, "path", path),
|
|
2148
2179
|
queryParams: this.naming.createSdkParameterManifest(operation.parameters, "query", path),
|
|
2149
|
-
headerParams: this.naming.createSdkParameterManifest(operation.parameters, "header", path)
|
|
2180
|
+
headerParams: this.naming.createSdkParameterManifest(operation.parameters, "header", path),
|
|
2181
|
+
security: this.buildSecurityRequirements(operation.security)
|
|
2150
2182
|
});
|
|
2151
2183
|
}
|
|
2152
2184
|
groups.set(propertyName, group);
|
|
2153
2185
|
}
|
|
2154
|
-
return {
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2186
|
+
return {
|
|
2187
|
+
groups: Array.from(groups.values()).map((group) => ({
|
|
2188
|
+
...group,
|
|
2189
|
+
operations: this.naming.ensureUniqueSdkMethodNames(group.operations)
|
|
2190
|
+
})).sort((left, right) => left.propertyName.localeCompare(right.propertyName)),
|
|
2191
|
+
securitySchemes,
|
|
2192
|
+
security: globalSecurity
|
|
2193
|
+
};
|
|
2158
2194
|
}
|
|
2195
|
+
/**
|
|
2196
|
+
* Infers a shape node from a given example value, using the provided name hint for
|
|
2197
|
+
* type naming purposes.
|
|
2198
|
+
*
|
|
2199
|
+
* @param value The example value to infer the shape from.
|
|
2200
|
+
* @param nameHint A hint for naming the inferred type.
|
|
2201
|
+
* @returns The inferred shape node.
|
|
2202
|
+
*/
|
|
2159
2203
|
inferShapeFromExample(value, nameHint) {
|
|
2160
2204
|
return this.shapes.inferShapeFromExample(value, nameHint);
|
|
2161
2205
|
}
|
|
2206
|
+
/**
|
|
2207
|
+
* Sanitizes a given string to be used as a type name in TypeScript.
|
|
2208
|
+
*
|
|
2209
|
+
* @param value The string to sanitize.
|
|
2210
|
+
* @returns The sanitized type name.
|
|
2211
|
+
*/
|
|
2162
2212
|
sanitizeTypeName(value) {
|
|
2163
2213
|
return this.naming.sanitizeTypeName(value);
|
|
2164
2214
|
}
|
|
2215
|
+
/**
|
|
2216
|
+
* Registers a shape with a preferred name and returns the assigned type name, ensuring
|
|
2217
|
+
* that it is unique within the given context.
|
|
2218
|
+
*
|
|
2219
|
+
* @param shape The shape node to register.
|
|
2220
|
+
* @param preferredName The preferred name for the type.
|
|
2221
|
+
* @param context The generator context.
|
|
2222
|
+
* @param collisionSuffix The suffix to use in case of name collisions.
|
|
2223
|
+
* @returns The assigned type name.
|
|
2224
|
+
*/
|
|
2165
2225
|
registerNamedShape(shape, preferredName, context, collisionSuffix) {
|
|
2166
2226
|
return this.shapes.registerNamedShape(shape, preferredName, context, collisionSuffix);
|
|
2167
2227
|
}
|
|
2228
|
+
/**
|
|
2229
|
+
* Determines the top-level shape for a given shape and its semantic role, which can
|
|
2230
|
+
* be used for namespace grouping in the generated SDK.
|
|
2231
|
+
*
|
|
2232
|
+
* @param shape The shape node to evaluate.
|
|
2233
|
+
* @param role The semantic role of the shape.
|
|
2234
|
+
* @returns The top-level shape node for the given shape and role.
|
|
2235
|
+
*/
|
|
2168
2236
|
namespaceTopLevelShape(shape, role) {
|
|
2169
2237
|
return this.shapes.namespaceTopLevelShape(shape, role);
|
|
2170
2238
|
}
|
|
2239
|
+
/**
|
|
2240
|
+
* Registers the given object shape and returns the assigned type name.
|
|
2241
|
+
*
|
|
2242
|
+
* @param shape The object shape to register.
|
|
2243
|
+
* @param preferredName The preferred name for the type.
|
|
2244
|
+
* @param context The generator context.
|
|
2245
|
+
* @param collisionSuffix The suffix to use in case of name collisions.
|
|
2246
|
+
* @param emitAlias Whether to emit a type alias.
|
|
2247
|
+
* @returns The assigned type name.
|
|
2248
|
+
*/
|
|
2171
2249
|
registerObjectShape(shape, preferredName, context, collisionSuffix, emitAlias = false) {
|
|
2172
2250
|
return this.shapes.registerObjectShape(shape, preferredName, context, collisionSuffix, emitAlias);
|
|
2173
2251
|
}
|
|
2252
|
+
/**
|
|
2253
|
+
* Determines the priority of an operation based on its characteristics, such as the
|
|
2254
|
+
* presence of a request body, which can be used for sorting operations when generating the SDK.
|
|
2255
|
+
*
|
|
2256
|
+
* @param operation The operation object to evaluate.
|
|
2257
|
+
* @returns The priority of the operation.
|
|
2258
|
+
*/
|
|
2174
2259
|
getOperationPriority(operation) {
|
|
2175
2260
|
return Number(Boolean(operation.requestBody)) * 10;
|
|
2176
2261
|
}
|
|
2262
|
+
/**
|
|
2263
|
+
* Resolves the description for a successful response from the given responses
|
|
2264
|
+
* object, preferring common success status codes and falling back to any available
|
|
2265
|
+
* description if necessary.
|
|
2266
|
+
*
|
|
2267
|
+
* @param responses The responses object to evaluate.
|
|
2268
|
+
* @returns The description of the successful response, or undefined if none is found.
|
|
2269
|
+
*/
|
|
2177
2270
|
resolveSuccessResponseDescription(responses) {
|
|
2178
2271
|
for (const statusCode of [
|
|
2179
2272
|
"200",
|
|
@@ -2189,6 +2282,85 @@ var TypeScriptTypeBuilder = class {
|
|
|
2189
2282
|
if (description) return description;
|
|
2190
2283
|
}
|
|
2191
2284
|
}
|
|
2285
|
+
/**
|
|
2286
|
+
* Builds the security schemes for the entire API, based on the provided OpenAPI document.
|
|
2287
|
+
*
|
|
2288
|
+
* @param document The OpenAPI document to build the security schemes from.
|
|
2289
|
+
* @returns The security scheme manifest objects.
|
|
2290
|
+
*/
|
|
2291
|
+
buildSecuritySchemes(document) {
|
|
2292
|
+
return Object.entries(document.components?.securitySchemes ?? {}).map(([name, scheme]) => this.createSecuritySchemeManifest(name, scheme)).filter((entry) => entry !== null).sort((left, right) => left.name.localeCompare(right.name));
|
|
2293
|
+
}
|
|
2294
|
+
/**
|
|
2295
|
+
* Builds the security requirements for an operation or the entire API, based on the
|
|
2296
|
+
* provided OpenAPI security requirement objects.
|
|
2297
|
+
*
|
|
2298
|
+
* @param name The name of the security requirement (used for logging or error messages).
|
|
2299
|
+
* @param scheme The OpenAPI security scheme object to create the manifest from.
|
|
2300
|
+
* @returns The security scheme manifest object, or null if the scheme type is not supported.
|
|
2301
|
+
*/
|
|
2302
|
+
createSecuritySchemeManifest(name, scheme) {
|
|
2303
|
+
const helperName = this.createSecurityHelperName(name);
|
|
2304
|
+
if (scheme.type === "apiKey") return {
|
|
2305
|
+
name,
|
|
2306
|
+
helperName,
|
|
2307
|
+
description: scheme.description,
|
|
2308
|
+
type: "apiKey",
|
|
2309
|
+
authType: "apiKey",
|
|
2310
|
+
in: scheme.in,
|
|
2311
|
+
parameterName: scheme.name
|
|
2312
|
+
};
|
|
2313
|
+
if (scheme.type === "oauth2") return {
|
|
2314
|
+
name,
|
|
2315
|
+
helperName,
|
|
2316
|
+
description: scheme.description,
|
|
2317
|
+
type: "oauth2",
|
|
2318
|
+
authType: "oauth2",
|
|
2319
|
+
scopes: this.collectSecurityScopes(scheme)
|
|
2320
|
+
};
|
|
2321
|
+
if (scheme.type === "openIdConnect") return {
|
|
2322
|
+
name,
|
|
2323
|
+
helperName,
|
|
2324
|
+
description: scheme.description,
|
|
2325
|
+
type: "openIdConnect",
|
|
2326
|
+
authType: "oauth2",
|
|
2327
|
+
openIdConnectUrl: scheme.openIdConnectUrl
|
|
2328
|
+
};
|
|
2329
|
+
const normalizedScheme = scheme.scheme.toLowerCase();
|
|
2330
|
+
return {
|
|
2331
|
+
name,
|
|
2332
|
+
helperName,
|
|
2333
|
+
description: scheme.description,
|
|
2334
|
+
type: "http",
|
|
2335
|
+
authType: normalizedScheme === "basic" ? "basic" : "bearer",
|
|
2336
|
+
scheme: scheme.scheme,
|
|
2337
|
+
bearerFormat: scheme.bearerFormat
|
|
2338
|
+
};
|
|
2339
|
+
}
|
|
2340
|
+
/**
|
|
2341
|
+
* Builds the security requirements for an operation or the entire API, based on the
|
|
2342
|
+
* provided OpenAPI security requirement objects.
|
|
2343
|
+
*
|
|
2344
|
+
* @param requirements The OpenAPI security requirement objects to build the manifest from.
|
|
2345
|
+
* @returns The security requirement manifest objects, or undefined if none are provided.
|
|
2346
|
+
*/
|
|
2347
|
+
buildSecurityRequirements(requirements) {
|
|
2348
|
+
if (!requirements || requirements.length === 0) return;
|
|
2349
|
+
const normalized = requirements.map((requirement) => ({ schemes: Object.entries(requirement).map(([name, scopes]) => ({
|
|
2350
|
+
name,
|
|
2351
|
+
scopes: [...scopes].sort()
|
|
2352
|
+
})).sort((left, right) => left.name.localeCompare(right.name)) })).filter((requirement) => requirement.schemes.length > 0);
|
|
2353
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
2354
|
+
}
|
|
2355
|
+
collectSecurityScopes(scheme) {
|
|
2356
|
+
const scopes = /* @__PURE__ */ new Set();
|
|
2357
|
+
for (const flow of Object.values(scheme.flows ?? {})) for (const scope of Object.keys(flow.scopes ?? {})) scopes.add(scope);
|
|
2358
|
+
return scopes.size > 0 ? Array.from(scopes).sort() : void 0;
|
|
2359
|
+
}
|
|
2360
|
+
createSecurityHelperName(name) {
|
|
2361
|
+
const sanitized = this.naming.sanitizeTypeName(name);
|
|
2362
|
+
return sanitized.endsWith("Auth") ? `create${sanitized}` : `create${sanitized}Auth`;
|
|
2363
|
+
}
|
|
2192
2364
|
};
|
|
2193
2365
|
|
|
2194
2366
|
//#endregion
|
|
@@ -2375,7 +2547,7 @@ var SdkPackageGenerator = class {
|
|
|
2375
2547
|
"package.json": this.renderPackageJson(options),
|
|
2376
2548
|
"README.md": this.renderReadme(manifest, options, outputMode, signatureStyle),
|
|
2377
2549
|
"src/Schema.ts": schemaModule,
|
|
2378
|
-
"src/index.ts": this.renderIndexFile(classNames, outputMode, rootTypeName),
|
|
2550
|
+
"src/index.ts": this.renderIndexFile(classNames, outputMode, rootTypeName, manifest),
|
|
2379
2551
|
"tsconfig.json": this.renderTsconfig(),
|
|
2380
2552
|
"tsdown.config.ts": this.renderTsdownConfig(),
|
|
2381
2553
|
"vitest.config.ts": this.renderVitestConfig(),
|
|
@@ -2625,7 +2797,7 @@ var SdkPackageGenerator = class {
|
|
|
2625
2797
|
const title = `# ${packageName}`;
|
|
2626
2798
|
const description = this.renderReadmeDescription(outputMode);
|
|
2627
2799
|
const usage = this.renderReadmeUsage(manifest, packageName, outputMode, signatureStyle);
|
|
2628
|
-
const exports = this.renderReadmeExports(outputMode);
|
|
2800
|
+
const exports = this.renderReadmeExports(outputMode, manifest);
|
|
2629
2801
|
return [
|
|
2630
2802
|
title,
|
|
2631
2803
|
"",
|
|
@@ -2667,8 +2839,13 @@ var SdkPackageGenerator = class {
|
|
|
2667
2839
|
const classSnippet = this.renderReadmeClientSnippet(packageName, "classes", signatureStyle, exampleOperation);
|
|
2668
2840
|
if (outputMode === "classes") return classSnippet;
|
|
2669
2841
|
const typeImports = exampleOperation ? this.collectReadmeTypeImports(exampleOperation.operation) : [];
|
|
2842
|
+
const valueImports = [
|
|
2843
|
+
"Core",
|
|
2844
|
+
"createClient",
|
|
2845
|
+
...exampleOperation ? this.collectReadmeAuthHelperImports(exampleOperation) : []
|
|
2846
|
+
];
|
|
2670
2847
|
return [
|
|
2671
|
-
typeImports.length > 0 ? `import {
|
|
2848
|
+
typeImports.length > 0 ? `import { ${valueImports.join(", ")}, type ${typeImports.join(", type ")} } from '${packageName}'` : `import { ${valueImports.join(", ")} } from '${packageName}'`,
|
|
2672
2849
|
"",
|
|
2673
2850
|
...this.renderReadmeClientBody("sdk", "classes", signatureStyle, exampleOperation),
|
|
2674
2851
|
"",
|
|
@@ -2680,7 +2857,9 @@ var SdkPackageGenerator = class {
|
|
|
2680
2857
|
renderReadmeClientSnippet(packageName, mode, signatureStyle, exampleOperation) {
|
|
2681
2858
|
const importNames = mode === "runtime" ? ["createClient"] : ["Core"];
|
|
2682
2859
|
const typeImports = exampleOperation ? this.collectReadmeTypeImports(exampleOperation.operation) : [];
|
|
2683
|
-
const
|
|
2860
|
+
const helperImports = exampleOperation ? this.collectReadmeAuthHelperImports(exampleOperation) : [];
|
|
2861
|
+
const valueImports = [...importNames, ...helperImports];
|
|
2862
|
+
const importLine = typeImports.length > 0 ? `import { ${valueImports.join(", ")}, type ${typeImports.join(", type ")} } from '${packageName}'` : `import { ${valueImports.join(", ")} } from '${packageName}'`;
|
|
2684
2863
|
const sdkVariable = mode === "runtime" ? "runtimeSdk" : "sdk";
|
|
2685
2864
|
return [
|
|
2686
2865
|
importLine,
|
|
@@ -2696,16 +2875,27 @@ var SdkPackageGenerator = class {
|
|
|
2696
2875
|
" clientId: process.env.CLIENT_ID!,",
|
|
2697
2876
|
" clientSecret: process.env.CLIENT_SECRET!,",
|
|
2698
2877
|
" environment: 'sandbox',",
|
|
2878
|
+
...exampleOperation ? this.renderReadmeAuthLines(exampleOperation.operation.security ?? exampleOperation.groupSecurity ?? exampleOperation.globalSecurity) : [],
|
|
2699
2879
|
"})",
|
|
2700
2880
|
...callLines.length > 0 ? ["", ...callLines] : []
|
|
2701
2881
|
];
|
|
2702
2882
|
}
|
|
2703
|
-
renderReadmeExports(outputMode) {
|
|
2704
|
-
|
|
2705
|
-
if (outputMode === "
|
|
2883
|
+
renderReadmeExports(outputMode, manifest) {
|
|
2884
|
+
const authLine = manifest.securitySchemes.length > 0 ? ["generated auth helpers derived from OpenAPI security schemes"] : [];
|
|
2885
|
+
if (outputMode === "runtime") return [
|
|
2886
|
+
"`createClient()` for a typed runtime SDK instance",
|
|
2887
|
+
...authLine,
|
|
2888
|
+
"`Schema` exports for request, response, params, query, and header types"
|
|
2889
|
+
];
|
|
2890
|
+
if (outputMode === "classes") return [
|
|
2891
|
+
"`Core` as the class-based SDK entrypoint",
|
|
2892
|
+
...authLine,
|
|
2893
|
+
"generated API classes plus `Schema` type exports"
|
|
2894
|
+
];
|
|
2706
2895
|
return [
|
|
2707
2896
|
"`Core` for class-based usage",
|
|
2708
2897
|
"`createClient()` for runtime-first usage",
|
|
2898
|
+
...authLine,
|
|
2709
2899
|
"`Schema` exports for generated request, response, params, query, and header types"
|
|
2710
2900
|
];
|
|
2711
2901
|
}
|
|
@@ -2715,9 +2905,33 @@ var SdkPackageGenerator = class {
|
|
|
2715
2905
|
if (!group || !operation) return null;
|
|
2716
2906
|
return {
|
|
2717
2907
|
group,
|
|
2718
|
-
operation
|
|
2908
|
+
operation,
|
|
2909
|
+
groupSecurity: void 0,
|
|
2910
|
+
globalSecurity: manifest.security
|
|
2719
2911
|
};
|
|
2720
2912
|
}
|
|
2913
|
+
renderReadmeAuthLines(security) {
|
|
2914
|
+
if (!security || security.length === 0) return [];
|
|
2915
|
+
const selectedRequirement = security[0];
|
|
2916
|
+
if (!selectedRequirement || selectedRequirement.schemes.length === 0) return [];
|
|
2917
|
+
const value = selectedRequirement.schemes.length === 1 ? this.renderReadmeAuthFactoryCall(selectedRequirement.schemes[0].name) : `[
|
|
2918
|
+
${selectedRequirement.schemes.map((scheme) => this.renderReadmeAuthFactoryCall(scheme.name)).join(",\n ")}
|
|
2919
|
+
]`;
|
|
2920
|
+
const lines = security.length > 1 ? [" // Choose a generated auth helper that matches your API access setup."] : [];
|
|
2921
|
+
lines.push(` auth: ${value},`);
|
|
2922
|
+
return lines;
|
|
2923
|
+
}
|
|
2924
|
+
renderReadmeAuthFactoryCall(schemeName) {
|
|
2925
|
+
const helperName = this.createSecurityHelperName(schemeName);
|
|
2926
|
+
const envName = this.toConstantCase(schemeName);
|
|
2927
|
+
if (/basic/i.test(schemeName)) return `${helperName}(process.env.${envName}_USERNAME!, process.env.${envName}_PASSWORD!)`;
|
|
2928
|
+
return `${helperName}(process.env.${envName}_VALUE!)`;
|
|
2929
|
+
}
|
|
2930
|
+
collectReadmeAuthHelperImports(exampleOperation) {
|
|
2931
|
+
const selectedRequirement = (exampleOperation.operation.security ?? exampleOperation.groupSecurity ?? exampleOperation.globalSecurity)?.[0];
|
|
2932
|
+
if (!selectedRequirement) return [];
|
|
2933
|
+
return selectedRequirement.schemes.map((scheme) => this.createSecurityHelperName(scheme.name));
|
|
2934
|
+
}
|
|
2721
2935
|
collectReadmeTypeImports(operation) {
|
|
2722
2936
|
const types = /* @__PURE__ */ new Set();
|
|
2723
2937
|
if (operation.pathParams.length > 0) types.add(operation.paramsType);
|
|
@@ -2824,13 +3038,13 @@ var SdkPackageGenerator = class {
|
|
|
2824
3038
|
"})"
|
|
2825
3039
|
].join("\n");
|
|
2826
3040
|
}
|
|
2827
|
-
renderIndexFile(classNames, outputMode, rootTypeName) {
|
|
3041
|
+
renderIndexFile(classNames, outputMode, rootTypeName, manifest) {
|
|
2828
3042
|
const rootExportName = `${rootTypeName.charAt(0).toLowerCase()}${rootTypeName.slice(1)}`;
|
|
2829
3043
|
const lines = [
|
|
2830
3044
|
`import type { ${rootTypeName}Api } from './Schema'`,
|
|
2831
|
-
`import { ${rootExportName}Sdk } from './Schema'`,
|
|
3045
|
+
`import { ${rootExportName}Manifest, ${rootExportName}Sdk } from './Schema'`,
|
|
2832
3046
|
"import { createSdk as createBoundSdk } from '@oapiex/sdk-kit'",
|
|
2833
|
-
"import type { BaseApi as KitBaseApi, Core as KitCore, InitOptions } from '@oapiex/sdk-kit'",
|
|
3047
|
+
"import type { AuthConfig, BaseApi as KitBaseApi, Core as KitCore, InitOptions } from '@oapiex/sdk-kit'",
|
|
2834
3048
|
"",
|
|
2835
3049
|
"export * from './Schema'"
|
|
2836
3050
|
];
|
|
@@ -2841,6 +3055,15 @@ var SdkPackageGenerator = class {
|
|
|
2841
3055
|
lines.push("export { Core } from './Core'");
|
|
2842
3056
|
}
|
|
2843
3057
|
lines.push("");
|
|
3058
|
+
lines.push(`export const securitySchemes = ${rootExportName}Manifest.securitySchemes`);
|
|
3059
|
+
lines.push(`export const security = ${rootExportName}Manifest.security`);
|
|
3060
|
+
if (manifest.securitySchemes.length > 0) {
|
|
3061
|
+
lines.push("");
|
|
3062
|
+
for (const scheme of manifest.securitySchemes) {
|
|
3063
|
+
lines.push(...this.renderSecurityHelper(scheme));
|
|
3064
|
+
lines.push("");
|
|
3065
|
+
}
|
|
3066
|
+
}
|
|
2844
3067
|
lines.push("export const createClient = (");
|
|
2845
3068
|
lines.push(" options: InitOptions");
|
|
2846
3069
|
lines.push(`): KitCore & { api: KitBaseApi & ${rootTypeName}Api } =>`);
|
|
@@ -2858,6 +3081,7 @@ var SdkPackageGenerator = class {
|
|
|
2858
3081
|
lines.push("} from '@oapiex/sdk-kit'");
|
|
2859
3082
|
lines.push("");
|
|
2860
3083
|
lines.push("export type {");
|
|
3084
|
+
lines.push(" AuthConfig,");
|
|
2861
3085
|
lines.push(" InitOptions,");
|
|
2862
3086
|
lines.push(" UnifiedResponse,");
|
|
2863
3087
|
lines.push(" XGenericObject,");
|
|
@@ -2869,6 +3093,47 @@ var SdkPackageGenerator = class {
|
|
|
2869
3093
|
return !["Record", "Promise"].includes(identifier);
|
|
2870
3094
|
})));
|
|
2871
3095
|
}
|
|
3096
|
+
renderSecurityHelper(scheme) {
|
|
3097
|
+
if (scheme.authType === "basic") return [
|
|
3098
|
+
`export const ${scheme.helperName} = (username: string, password: string): AuthConfig => ({`,
|
|
3099
|
+
" type: 'basic',",
|
|
3100
|
+
" username,",
|
|
3101
|
+
" password,",
|
|
3102
|
+
"})"
|
|
3103
|
+
];
|
|
3104
|
+
if (scheme.authType === "apiKey") return [
|
|
3105
|
+
`export const ${scheme.helperName} = (value: string): AuthConfig => ({`,
|
|
3106
|
+
" type: 'apiKey',",
|
|
3107
|
+
` name: ${JSON.stringify(scheme.parameterName ?? scheme.name)},`,
|
|
3108
|
+
" value,",
|
|
3109
|
+
` in: ${JSON.stringify(scheme.in ?? "header")},`,
|
|
3110
|
+
"})"
|
|
3111
|
+
];
|
|
3112
|
+
if (scheme.authType === "oauth2") return [
|
|
3113
|
+
`export const ${scheme.helperName} = (accessToken: string, tokenType = 'Bearer'): AuthConfig => ({`,
|
|
3114
|
+
" type: 'oauth2',",
|
|
3115
|
+
" accessToken,",
|
|
3116
|
+
" tokenType,",
|
|
3117
|
+
"})"
|
|
3118
|
+
];
|
|
3119
|
+
return [
|
|
3120
|
+
`export const ${scheme.helperName} = (token: string): AuthConfig => ({`,
|
|
3121
|
+
" type: 'bearer',",
|
|
3122
|
+
" token,",
|
|
3123
|
+
...scheme.scheme && scheme.scheme.toLowerCase() !== "bearer" ? [` prefix: ${JSON.stringify(this.normalizeHttpAuthPrefix(scheme.scheme))},`] : [],
|
|
3124
|
+
"})"
|
|
3125
|
+
];
|
|
3126
|
+
}
|
|
3127
|
+
createSecurityHelperName(schemeName) {
|
|
3128
|
+
const sanitized = this.typeBuilder.sanitizeTypeName(schemeName);
|
|
3129
|
+
return sanitized.endsWith("Auth") ? `create${sanitized}` : `create${sanitized}Auth`;
|
|
3130
|
+
}
|
|
3131
|
+
normalizeHttpAuthPrefix(scheme) {
|
|
3132
|
+
return scheme.charAt(0).toUpperCase() + scheme.slice(1);
|
|
3133
|
+
}
|
|
3134
|
+
toConstantCase(value) {
|
|
3135
|
+
return value.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^A-Za-z0-9]+/g, "_").replace(/^_+|_+$/g, "").toUpperCase() || "AUTH";
|
|
3136
|
+
}
|
|
2872
3137
|
};
|
|
2873
3138
|
|
|
2874
3139
|
//#endregion
|
package/dist/index.d.ts
CHANGED
|
@@ -117,10 +117,37 @@ interface OpenApiResponse {
|
|
|
117
117
|
description: string;
|
|
118
118
|
content?: Record<string, OpenApiMediaType>;
|
|
119
119
|
}
|
|
120
|
+
interface OpenApiOauthFlowLike {
|
|
121
|
+
authorizationUrl?: string;
|
|
122
|
+
tokenUrl?: string;
|
|
123
|
+
refreshUrl?: string;
|
|
124
|
+
scopes?: Record<string, string>;
|
|
125
|
+
}
|
|
126
|
+
type OpenApiSecurityRequirementLike = Record<string, string[]>;
|
|
127
|
+
type OpenApiSecuritySchemeLike = {
|
|
128
|
+
type: 'http';
|
|
129
|
+
description?: string;
|
|
130
|
+
scheme: string;
|
|
131
|
+
bearerFormat?: string;
|
|
132
|
+
} | {
|
|
133
|
+
type: 'apiKey';
|
|
134
|
+
description?: string;
|
|
135
|
+
name: string;
|
|
136
|
+
in: 'query' | 'header' | 'cookie';
|
|
137
|
+
} | {
|
|
138
|
+
type: 'oauth2';
|
|
139
|
+
description?: string;
|
|
140
|
+
flows?: Record<string, OpenApiOauthFlowLike>;
|
|
141
|
+
} | {
|
|
142
|
+
type: 'openIdConnect';
|
|
143
|
+
description?: string;
|
|
144
|
+
openIdConnectUrl: string;
|
|
145
|
+
};
|
|
120
146
|
interface OpenApiOperationLike {
|
|
121
147
|
summary?: string;
|
|
122
148
|
description?: string;
|
|
123
149
|
operationId?: string;
|
|
150
|
+
security?: OpenApiSecurityRequirementLike[];
|
|
124
151
|
parameters?: OpenApiParameterLike[];
|
|
125
152
|
requestBody?: {
|
|
126
153
|
description?: string;
|
|
@@ -135,6 +162,10 @@ interface OpenApiDocumentLike {
|
|
|
135
162
|
title: string;
|
|
136
163
|
version: string;
|
|
137
164
|
};
|
|
165
|
+
components?: {
|
|
166
|
+
securitySchemes?: Record<string, OpenApiSecuritySchemeLike>;
|
|
167
|
+
};
|
|
168
|
+
security?: OpenApiSecurityRequirementLike[];
|
|
138
169
|
paths: Record<string, Record<string, OpenApiOperationLike>>;
|
|
139
170
|
}
|
|
140
171
|
//#endregion
|
|
@@ -391,6 +422,26 @@ interface SdkParameterManifest {
|
|
|
391
422
|
required: boolean;
|
|
392
423
|
description?: string;
|
|
393
424
|
}
|
|
425
|
+
interface SdkSecurityRequirementSchemeManifest {
|
|
426
|
+
name: string;
|
|
427
|
+
scopes: string[];
|
|
428
|
+
}
|
|
429
|
+
interface SdkSecurityRequirementManifest {
|
|
430
|
+
schemes: SdkSecurityRequirementSchemeManifest[];
|
|
431
|
+
}
|
|
432
|
+
interface SdkSecuritySchemeManifest {
|
|
433
|
+
name: string;
|
|
434
|
+
helperName: string;
|
|
435
|
+
description?: string;
|
|
436
|
+
type: 'http' | 'apiKey' | 'oauth2' | 'openIdConnect';
|
|
437
|
+
authType: 'bearer' | 'basic' | 'apiKey' | 'oauth2';
|
|
438
|
+
scheme?: string;
|
|
439
|
+
bearerFormat?: string;
|
|
440
|
+
in?: 'header' | 'query' | 'cookie';
|
|
441
|
+
parameterName?: string;
|
|
442
|
+
openIdConnectUrl?: string;
|
|
443
|
+
scopes?: string[];
|
|
444
|
+
}
|
|
394
445
|
interface SdkOperationManifest {
|
|
395
446
|
path: string;
|
|
396
447
|
method: string;
|
|
@@ -410,6 +461,7 @@ interface SdkOperationManifest {
|
|
|
410
461
|
pathParams: SdkParameterManifest[];
|
|
411
462
|
queryParams: SdkParameterManifest[];
|
|
412
463
|
headerParams: SdkParameterManifest[];
|
|
464
|
+
security?: SdkSecurityRequirementManifest[];
|
|
413
465
|
}
|
|
414
466
|
interface SdkGroupManifest {
|
|
415
467
|
className: string;
|
|
@@ -418,6 +470,8 @@ interface SdkGroupManifest {
|
|
|
418
470
|
}
|
|
419
471
|
interface SdkManifest {
|
|
420
472
|
groups: SdkGroupManifest[];
|
|
473
|
+
securitySchemes: SdkSecuritySchemeManifest[];
|
|
474
|
+
security?: SdkSecurityRequirementManifest[];
|
|
421
475
|
}
|
|
422
476
|
interface PayloadSchemaCandidate {
|
|
423
477
|
schema?: OpenApiSchema;
|
|
@@ -500,6 +554,9 @@ declare class SdkPackageGenerator {
|
|
|
500
554
|
private renderReadmeClientBody;
|
|
501
555
|
private renderReadmeExports;
|
|
502
556
|
private pickExampleOperation;
|
|
557
|
+
private renderReadmeAuthLines;
|
|
558
|
+
private renderReadmeAuthFactoryCall;
|
|
559
|
+
private collectReadmeAuthHelperImports;
|
|
503
560
|
private collectReadmeTypeImports;
|
|
504
561
|
private renderReadmeOperationCall;
|
|
505
562
|
private renderReadmeGroupedArgs;
|
|
@@ -510,6 +567,10 @@ declare class SdkPackageGenerator {
|
|
|
510
567
|
private renderExportsTest;
|
|
511
568
|
private renderIndexFile;
|
|
512
569
|
private collectTypeIdentifiers;
|
|
570
|
+
private renderSecurityHelper;
|
|
571
|
+
private createSecurityHelperName;
|
|
572
|
+
private normalizeHttpAuthPrefix;
|
|
573
|
+
private toConstantCase;
|
|
513
574
|
}
|
|
514
575
|
//#endregion
|
|
515
576
|
//#region src/generator/TypeScriptGenerator.d.ts
|
|
@@ -623,4 +684,4 @@ interface ReadmeCrawledOperation extends ReadmeOperation {
|
|
|
623
684
|
}
|
|
624
685
|
declare const resolveReadmeSidebarUrls: (operation: Pick<ReadmeOperation, "sidebarLinks">, baseUrl: string) => string[];
|
|
625
686
|
//#endregion
|
|
626
|
-
export { Application, AttributeQueryNode, AttributedNode, BrowserName, Declaration, GenerateCommand, GeneratorContext, InitCommand, InterfaceAliasDeclaration, InterfaceDeclaration, JsonLike, JsonRepair, OpenApiDocumentLike, OpenApiMediaType, OpenApiOperationLike, OpenApiParameterLike, OpenApiResponse, OpenApiSchema, OpenApiTransformer, OperationTypeRefs, OutputGenerator, ParseCommand, PayloadSchemaCandidate, QueryableNode, ReadmeCodeSnippet, ReadmeCrawledOperation, ReadmeNormalizedRequestExample, ReadmeOperation, ReadmeParameter, ReadmeResponseBody, ReadmeResponseSchema, ReadmeSidebarLink, SdkGroupManifest, SdkManifest, SdkMethodNamingStrategy, SdkNamespaceNamingStrategy, SdkNamingStrategyOptions, SdkOperationManifest, SdkPackageGenerator, SdkPackageGeneratorOptions, SdkParameterManifest, SemanticModel, ShapeAliasDeclaration, ShapeNode, ShapeProperty, TextNodeLike, TypeReferenceAliasDeclaration, TypeScriptGenerator, UserConfig, browser, buildOperationUrl, defaultConfig, defineConfig, endBrowserSession, escapeSelector, extractBalancedSegment, extractButtonText, extractCodeMirrorText, extractCodeSnippets, extractFetchBody, extractFetchHeaders, extractObjectPropertyValue, extractOperationDescription, extractOperationParametersFromOpenApi, extractParameterDescription, extractReadmeOperationFromHtml, extractReadmeOperationFromSsrProps, extractRequestCodeSnippets, extractRequestParams, extractRequestParamsFromOpenApi, extractRequestSnippetLabel, extractResponseBodies, extractResponseBodiesFromOpenApi, extractResponseContentTypes, extractResponseLabels, extractResponseSchemas, extractResponseSchemasFromOpenApi, extractSidebarLinkLabel, extractSidebarLinks, extractStablePageHtml, extractStringLiteralValue, findParameterRoot, flattenOpenApiSchemaProperties, getBrowserSession, globalConfig, inferParameterLocation, inferParameterLocationFromText, inferParameterPath, inferParameterType, isRecord, isRequiredParameter, isSupportedBrowser, loadUserConfig, mergeReadmeOperations, mergeSsrPropsIntoRenderedHtml, normalizeCurlSnippet, normalizeFetchSnippet, normalizeRequestCodeSnippet, normalizeResponseBody, normalizeStructuredRequestBody, parseLooseStructuredValue, readInputValue, readText, readTexts, resolveConfig, resolveOpenApiMediaExample, resolveParameterInput, resolveReadmeSidebarUrls, resolveSsrOperation, startBrowserSession, supportedBrowsers, transformer };
|
|
687
|
+
export { Application, AttributeQueryNode, AttributedNode, BrowserName, Declaration, GenerateCommand, GeneratorContext, InitCommand, InterfaceAliasDeclaration, InterfaceDeclaration, JsonLike, JsonRepair, OpenApiDocumentLike, OpenApiMediaType, OpenApiOauthFlowLike, OpenApiOperationLike, OpenApiParameterLike, OpenApiResponse, OpenApiSchema, OpenApiSecurityRequirementLike, OpenApiSecuritySchemeLike, OpenApiTransformer, OperationTypeRefs, OutputGenerator, ParseCommand, PayloadSchemaCandidate, QueryableNode, ReadmeCodeSnippet, ReadmeCrawledOperation, ReadmeNormalizedRequestExample, ReadmeOperation, ReadmeParameter, ReadmeResponseBody, ReadmeResponseSchema, ReadmeSidebarLink, SdkGroupManifest, SdkManifest, SdkMethodNamingStrategy, SdkNamespaceNamingStrategy, SdkNamingStrategyOptions, SdkOperationManifest, SdkPackageGenerator, SdkPackageGeneratorOptions, SdkParameterManifest, SdkSecurityRequirementManifest, SdkSecurityRequirementSchemeManifest, SdkSecuritySchemeManifest, SemanticModel, ShapeAliasDeclaration, ShapeNode, ShapeProperty, TextNodeLike, TypeReferenceAliasDeclaration, TypeScriptGenerator, UserConfig, browser, buildOperationUrl, defaultConfig, defineConfig, endBrowserSession, escapeSelector, extractBalancedSegment, extractButtonText, extractCodeMirrorText, extractCodeSnippets, extractFetchBody, extractFetchHeaders, extractObjectPropertyValue, extractOperationDescription, extractOperationParametersFromOpenApi, extractParameterDescription, extractReadmeOperationFromHtml, extractReadmeOperationFromSsrProps, extractRequestCodeSnippets, extractRequestParams, extractRequestParamsFromOpenApi, extractRequestSnippetLabel, extractResponseBodies, extractResponseBodiesFromOpenApi, extractResponseContentTypes, extractResponseLabels, extractResponseSchemas, extractResponseSchemasFromOpenApi, extractSidebarLinkLabel, extractSidebarLinks, extractStablePageHtml, extractStringLiteralValue, findParameterRoot, flattenOpenApiSchemaProperties, getBrowserSession, globalConfig, inferParameterLocation, inferParameterLocationFromText, inferParameterPath, inferParameterType, isRecord, isRequiredParameter, isSupportedBrowser, loadUserConfig, mergeReadmeOperations, mergeSsrPropsIntoRenderedHtml, normalizeCurlSnippet, normalizeFetchSnippet, normalizeRequestCodeSnippet, normalizeResponseBody, normalizeStructuredRequestBody, parseLooseStructuredValue, readInputValue, readText, readTexts, resolveConfig, resolveOpenApiMediaExample, resolveParameterInput, resolveReadmeSidebarUrls, resolveSsrOperation, startBrowserSession, supportedBrowsers, transformer };
|