@vercube/schema
Version:
Schema (swagger) module for Vercube framework
187 lines (178 loc) • 6.1 kB
JavaScript
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 };