UNPKG

@vercube/schema

Version:

Schema (swagger) module for Vercube framework

187 lines (178 loc) 6.1 kB
import { OpenAPIRegistry, OpenApiGeneratorV3, extendZodWithOpenApi } from "@asteasolutions/zod-to-openapi"; import { z } from "zod"; import { BaseDecorator, Inject, createDecorator } from "@vercube/di"; import defu from "defu"; import { BasePlugin, Controller, Get } from "@vercube/core"; //#region src/Resolvers/SchemaBodyResolver.ts /** * Resolves the body schema for a given method. * @param metadata - The metadata of the method. * @param schema - The schema to resolve the body for. * @returns void */ function SchemaBodyResolver(metadata, schema) { const body = metadata.args.find((arg) => arg.type === "body"); if (!body || !body.validationSchema) return; schema.request = defu(schema?.request ?? {}, { body: { content: { "application/json": { schema: body.validationSchema } } } }); } //#endregion //#region src/Resolvers/SchemaQueryParamsResolver.ts /** * Resolves the query params schema for a given method. * @param metadata - The metadata of the method. * @param schema - The schema to resolve the query params for. * @returns void */ function SchemaQueryParamsResolver(metadata, schema) { const query = metadata.args.find((arg) => arg.type === "query-params"); if (!query || !query.validationSchema) return; schema.request = defu(schema?.request ?? {}, { query: query.validationSchema }); } //#endregion //#region src/Services/SchemaRegistry.ts /** * Manages the OpenAPI schema registry and provides utilities to generate OpenAPI components * from registered Zod schemas using the @asteasolutions/zod-to-openapi library. * * This class is intended to be used for collecting and generating OpenAPI-compatible * schema definitions for API documentation and validation purposes. */ var SchemaRegistry = class { /** * Internal registry instance for storing OpenAPI schema definitions. * @private */ fRegistry = new OpenAPIRegistry(); /** * Registers a route configuration with the registry. * @param cfg - The route configuration to register. */ register(cfg) { this.fRegistry.registerPath(cfg); } /** * Generates OpenAPI components from the registered schemas. * * @async * @returns {Promise<unknown>} A promise that resolves to the generated OpenAPI components object. */ async generateSchema() { return new OpenApiGeneratorV3(this.fRegistry.definitions).generateDocument({ openapi: "3.0.0", info: { title: "API", version: "1.0.0" } }); } }; //#endregion //#region \0@oxc-project+runtime@0.90.0/helpers/decorate.js function __decorate(decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; } //#endregion //#region src/Decorators/Schema.ts /** * A decorator class for handling OpenAPI schema registration for routes. * * This class extends BaseDecorator and is used to register route schemas * with the SchemaRegistry. It also applies schema resolvers for responses, * body, and query parameters. * * @extends {BaseDecorator<SchemaDecoratorOptions>} */ var SchemaDecorator = class extends BaseDecorator { gSchemaRegistry; async created() { await new Promise((resolve) => setTimeout(resolve, 0)); const _methodMeta = this.prototype.__metadata.__methods[this.propertyName]; const _schema = { method: _methodMeta.method.toLowerCase(), path: _methodMeta.url, ...this.options }; SchemaBodyResolver(_methodMeta, _schema); SchemaQueryParamsResolver(_methodMeta, _schema); this.gSchemaRegistry.register(_schema); } }; __decorate([Inject(SchemaRegistry)], SchemaDecorator.prototype, "gSchemaRegistry", void 0); /** * A decorator function for registering OpenAPI schema metadata for a route. * * This function creates an instance of the SchemaDecorator class and registers * the schema with the specified options. * * @param {SchemaDecoratorOptions} params - The schema options for the route. * @returns {Function} - The decorator function. */ function Schema(params) { return createDecorator(SchemaDecorator, params); } //#endregion //#region src/Controllers/SchameController.ts let SchemaController = class SchemaController$1 { gSchemaRegistry; /** * Handles GET requests to retrieve the generated OpenAPI schema. * * @returns {Promise<unknown>} The generated OpenAPI schema object. */ async get() { return this.gSchemaRegistry.generateSchema(); } }; __decorate([Inject(SchemaRegistry)], SchemaController.prototype, "gSchemaRegistry", void 0); __decorate([Get("/")], SchemaController.prototype, "get", null); SchemaController = __decorate([Controller("/_schema")], SchemaController); //#endregion //#region src/Plugins/SchemaPlugin.ts /** * Schema Plugin for Vercube framework * * Provides OpenAPI/Swagger schema generation and validation capabilities: * - Automatic OpenAPI schema generation from Zod schemas * - Route-level schema validation via @Schema decorator * - Runtime schema access via /_schema endpoint * - Seamless integration with request validation (@Body, @Query, etc) * * @example * ```ts * import { createApp } from '@vercube/core'; * import { SchemaPlugin } from '@vercube/schema'; * * const app = createApp({ * setup: async (app) => { * app.addPlugin(SchemaPlugin); * } * }); * ``` * * @see {@link https://vercube.dev} for full documentation */ var SchemaPlugin = class extends BasePlugin { /** * The name of the plugin. * @override */ name = "SchemaPlugin"; /** * Method to use the plugin with the given app. * @param {App} app - The application instance. * @returns {void | Promise<void>} * @override */ use(app, options) { app.container.bind(SchemaRegistry); app.container.bind(SchemaController); } }; //#endregion //#region src/index.ts extendZodWithOpenApi(z); //#endregion export { Schema, SchemaPlugin, z };