@kubb/plugin-oas
Version:
OpenAPI Specification (OAS) plugin for Kubb, providing core functionality for parsing and processing OpenAPI/Swagger schemas for code generation.
324 lines (320 loc) • 12.1 kB
JavaScript
const require_chunk = require('./chunk-CbDLau6x.cjs');
const require_generators = require('./generators--9_lTBjl.cjs');
const require_SchemaGenerator = require('./SchemaGenerator-Bg5O155W.cjs');
require('./getFooter-BWck5e2D.cjs');
const require_SchemaMapper = require('./SchemaMapper-BUV8vhg0.cjs');
require('./getSchemas-BTCpbjet.cjs');
let __kubb_core = require("@kubb/core");
let __kubb_core_transformers = require("@kubb/core/transformers");
__kubb_core_transformers = require_chunk.__toESM(__kubb_core_transformers);
let node_path = require("node:path");
node_path = require_chunk.__toESM(node_path);
let __kubb_oas = require("@kubb/oas");
//#region src/OperationGenerator.ts
var OperationGenerator = class extends __kubb_core.BaseGenerator {
#getOptions(operation, method) {
const { override = [] } = this.context;
const operationId = operation.getOperationId({ friendlyCase: true });
const contentType = operation.getContentType();
return override.find(({ pattern, type }) => {
switch (type) {
case "tag": return operation.getTags().some((tag) => tag.name.match(pattern));
case "operationId": return !!operationId.match(pattern);
case "path": return !!operation.path.match(pattern);
case "method": return !!method.match(pattern);
case "contentType": return !!contentType.match(pattern);
default: return false;
}
})?.options || {};
}
#isExcluded(operation, method) {
const { exclude = [] } = this.context;
const operationId = operation.getOperationId({ friendlyCase: true });
const contentType = operation.getContentType();
return exclude.some(({ pattern, type }) => {
switch (type) {
case "tag": return operation.getTags().some((tag) => tag.name.match(pattern));
case "operationId": return !!operationId.match(pattern);
case "path": return !!operation.path.match(pattern);
case "method": return !!method.match(pattern);
case "contentType": return !!contentType.match(pattern);
default: return false;
}
});
}
#isIncluded(operation, method) {
const { include = [] } = this.context;
const operationId = operation.getOperationId({ friendlyCase: true });
const contentType = operation.getContentType();
return include.some(({ pattern, type }) => {
switch (type) {
case "tag": return operation.getTags().some((tag) => tag.name.match(pattern));
case "operationId": return !!operationId.match(pattern);
case "path": return !!operation.path.match(pattern);
case "method": return !!method.match(pattern);
case "contentType": return !!contentType.match(pattern);
default: return false;
}
});
}
getSchemas(operation, { resolveName = (name) => name } = {}) {
const operationId = operation.getOperationId({ friendlyCase: true });
const method = operation.method;
const operationName = __kubb_core_transformers.default.pascalCase(operationId);
const resolveKeys = (schema) => schema?.properties ? Object.keys(schema.properties) : void 0;
const pathParamsSchema = this.context.oas.getParametersSchema(operation, "path");
const queryParamsSchema = this.context.oas.getParametersSchema(operation, "query");
const headerParamsSchema = this.context.oas.getParametersSchema(operation, "header");
const requestSchema = this.context.oas.getRequestSchema(operation);
const statusCodes = operation.getResponseStatusCodes().map((statusCode) => {
const name = statusCode === "default" ? "error" : statusCode;
const schema = this.context.oas.getResponseSchema(operation, statusCode);
const keys = resolveKeys(schema);
return {
name: resolveName(__kubb_core_transformers.default.pascalCase(`${operationId} ${name}`)),
description: operation.getResponseByStatusCode(statusCode)?.description,
schema,
operation,
operationName,
statusCode: name === "error" ? void 0 : Number(statusCode),
keys,
keysToOmit: keys?.filter((key) => (schema?.properties?.[key])?.writeOnly)
};
});
const successful = statusCodes.filter((item) => item.statusCode?.toString().startsWith("2"));
const errors = statusCodes.filter((item) => item.statusCode?.toString().startsWith("4") || item.statusCode?.toString().startsWith("5"));
return {
pathParams: pathParamsSchema ? {
name: resolveName(__kubb_core_transformers.default.pascalCase(`${operationId} PathParams`)),
operation,
operationName,
schema: pathParamsSchema,
keys: resolveKeys(pathParamsSchema)
} : void 0,
queryParams: queryParamsSchema ? {
name: resolveName(__kubb_core_transformers.default.pascalCase(`${operationId} QueryParams`)),
operation,
operationName,
schema: queryParamsSchema,
keys: resolveKeys(queryParamsSchema) || []
} : void 0,
headerParams: headerParamsSchema ? {
name: resolveName(__kubb_core_transformers.default.pascalCase(`${operationId} HeaderParams`)),
operation,
operationName,
schema: headerParamsSchema,
keys: resolveKeys(headerParamsSchema)
} : void 0,
request: requestSchema ? {
name: resolveName(__kubb_core_transformers.default.pascalCase(`${operationId} ${method === "get" ? "queryRequest" : "mutationRequest"}`)),
description: operation.schema.requestBody?.description,
operation,
operationName,
schema: requestSchema,
keys: resolveKeys(requestSchema),
keysToOmit: resolveKeys(requestSchema)?.filter((key) => (requestSchema.properties?.[key])?.readOnly)
} : void 0,
response: {
name: resolveName(__kubb_core_transformers.default.pascalCase(`${operationId} ${method === "get" ? "queryResponse" : "mutationResponse"}`)),
operation,
operationName,
schema: { oneOf: successful.map((item) => ({
...item.schema,
$ref: item.name
})) || void 0 }
},
responses: successful,
errors,
statusCodes
};
}
async getOperations() {
const { oas } = this.context;
const paths = oas.getPaths();
return Object.entries(paths).flatMap(([path$1, methods]) => Object.entries(methods).map((values) => {
const [method, operation] = values;
if (this.#isExcluded(operation, method)) return null;
if (this.context.include && !this.#isIncluded(operation, method)) return null;
return operation ? {
path: path$1,
method,
operation
} : null;
}).filter(Boolean));
}
async build(...generators) {
const operations = await this.getOperations();
const generatorLimit = require_SchemaGenerator.pLimit(1);
const operationLimit = require_SchemaGenerator.pLimit(10);
const writeTasks = generators.map((generator) => generatorLimit(async () => {
const operationTasks = operations.map(({ operation, method }) => operationLimit(async () => {
const options = this.#getOptions(operation, method);
if (generator.type === "react") {
await require_SchemaGenerator.buildOperation(operation, {
config: this.context.pluginManager.config,
fabric: this.context.fabric,
Component: generator.Operation,
generator: this,
plugin: {
...this.context.plugin,
options: {
...this.options,
...options
}
}
});
return [];
}
return await generator.operation?.({
generator: this,
config: this.context.pluginManager.config,
operation,
plugin: {
...this.context.plugin,
options: {
...this.options,
...options
}
}
}) ?? [];
}));
const opResultsFlat = (await Promise.all(operationTasks)).flat();
if (generator.type === "react") {
await require_SchemaGenerator.buildOperations(operations.map((op) => op.operation), {
fabric: this.context.fabric,
config: this.context.pluginManager.config,
Component: generator.Operations,
generator: this,
plugin: this.context.plugin
});
return [];
}
const operationsResult = await generator.operations?.({
generator: this,
config: this.context.pluginManager.config,
operations: operations.map((op) => op.operation),
plugin: this.context.plugin
});
return [...opResultsFlat, ...operationsResult ?? []];
}));
return (await Promise.all(writeTasks)).flat();
}
};
//#endregion
//#region src/plugin.ts
const pluginOasName = "plugin-oas";
const pluginOas = (0, __kubb_core.definePlugin)((options) => {
const { output = { path: "schemas" }, group, validate = true, generators = [require_generators.jsonGenerator], serverIndex, contentType, oasClass, discriminator = "strict" } = options;
const getOas = async ({ config }) => {
const oas = await (0, __kubb_oas.parseFromConfig)(config, oasClass);
oas.setOptions({
contentType,
discriminator
});
try {
if (validate) await oas.valdiate();
} catch (e) {
const error = e;
console.warn(error?.message);
}
return oas;
};
return {
name: pluginOasName,
options: {
output,
validate,
discriminator,
...options
},
inject() {
const config = this.config;
let oas;
return {
async getOas() {
if (!oas) oas = await getOas({ config });
return oas;
},
async getBaseURL() {
const oas$1 = await getOas({ config });
if (serverIndex) return oas$1.api.servers?.at(serverIndex)?.url;
}
};
},
resolvePath(baseName, pathMode, options$1) {
const root = node_path.default.resolve(this.config.root, this.config.output.path);
if ((pathMode ?? (0, __kubb_core.getMode)(node_path.default.resolve(root, output.path))) === "single")
/**
* when output is a file then we will always append to the same file(output file), see fileManager.addOrAppend
* Other plugins then need to call addOrAppend instead of just add from the fileManager class
*/
return node_path.default.resolve(root, output.path);
if (group && (options$1?.group?.path || options$1?.group?.tag)) {
const groupName = group?.name ? group.name : (ctx) => {
if (group?.type === "path") return `${ctx.group.split("/")[1]}`;
return `${(0, __kubb_core_transformers.camelCase)(ctx.group)}Controller`;
};
return node_path.default.resolve(root, output.path, groupName({ group: group.type === "path" ? options$1.group.path : options$1.group.tag }), baseName);
}
return node_path.default.resolve(root, output.path, baseName);
},
async install() {
if (!output) return;
const oas = await this.getOas();
await oas.dereference();
const schemaFiles = await new require_SchemaGenerator.SchemaGenerator({
unknownType: "unknown",
emptySchemaType: "unknown",
dateType: "date",
transformers: {},
...this.plugin.options
}, {
fabric: this.fabric,
oas,
pluginManager: this.pluginManager,
plugin: this.plugin,
contentType,
include: void 0,
override: void 0,
mode: "split",
output: output.path
}).build(...generators);
await this.upsertFile(...schemaFiles);
const operationFiles = await new OperationGenerator(this.plugin.options, {
fabric: this.fabric,
oas,
pluginManager: this.pluginManager,
plugin: this.plugin,
contentType,
exclude: void 0,
include: void 0,
override: void 0,
mode: "split"
}).build(...generators);
await this.upsertFile(...operationFiles);
}
};
});
//#endregion
//#region src/index.ts
/**
* @deprecated use `import { createGenerator } from '@kubb/plugin-oas/generators'`
*/
const createGenerator = require_generators.createGenerator;
/**
* @deprecated use `import { createReactGenerator } from '@kubb/plugin-oas/generators'`
*/
const createReactGenerator = require_generators.createReactGenerator;
//#endregion
exports.OperationGenerator = OperationGenerator;
exports.SchemaGenerator = require_SchemaGenerator.SchemaGenerator;
exports.buildOperation = require_SchemaGenerator.buildOperation;
exports.buildOperations = require_SchemaGenerator.buildOperations;
exports.buildSchema = require_SchemaGenerator.buildSchema;
exports.createGenerator = createGenerator;
exports.createReactGenerator = createReactGenerator;
exports.isKeyword = require_SchemaMapper.isKeyword;
exports.pluginOas = pluginOas;
exports.pluginOasName = pluginOasName;
exports.schemaKeywords = require_SchemaMapper.schemaKeywords;
//# sourceMappingURL=index.cjs.map