@forinda/kickjs-swagger 1.3.2 → 1.4.1-alpha.0

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.
@@ -0,0 +1,33 @@
1
+ import 'reflect-metadata';
2
+ declare const SWAGGER_KEYS: {
3
+ OPERATION: symbol;
4
+ RESPONSES: symbol;
5
+ TAGS: symbol;
6
+ BEARER_AUTH: symbol;
7
+ EXCLUDE: symbol;
8
+ };
9
+ export { SWAGGER_KEYS };
10
+ export interface ApiOperationOptions {
11
+ summary?: string;
12
+ description?: string;
13
+ operationId?: string;
14
+ deprecated?: boolean;
15
+ }
16
+ export interface ApiResponseOptions {
17
+ status: number;
18
+ description?: string;
19
+ schema?: any;
20
+ /** Schema name in components/schemas (e.g., 'UserResponse', 'ErrorBody'). Auto-generated from handler name if omitted. */
21
+ name?: string;
22
+ }
23
+ /** Attach operation metadata to a route handler */
24
+ export declare function ApiOperation(options: ApiOperationOptions): MethodDecorator;
25
+ /** Document a response status. Can be stacked multiple times. */
26
+ export declare function ApiResponse(options: ApiResponseOptions): MethodDecorator;
27
+ /** Apply OpenAPI tags at class or method level */
28
+ export declare function ApiTags(...tags: string[]): ClassDecorator & MethodDecorator;
29
+ /** Mark endpoint as requiring Bearer token auth */
30
+ export declare function ApiBearerAuth(name?: string): ClassDecorator & MethodDecorator;
31
+ /** Exclude a controller or method from the OpenAPI spec */
32
+ export declare function ApiExclude(): ClassDecorator & MethodDecorator;
33
+ //# sourceMappingURL=decorators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAA;AAEzB,QAAA,MAAM,YAAY;;;;;;CAMjB,CAAA;AAED,OAAO,EAAE,YAAY,EAAE,CAAA;AAEvB,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,GAAG,CAAA;IACZ,0HAA0H;IAC1H,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,mDAAmD;AACnD,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,eAAe,CAI1E;AAED,iEAAiE;AACjE,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,eAAe,CAWxE;AAED,kDAAkD;AAClD,wBAAgB,OAAO,CAAC,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,cAAc,GAAG,eAAe,CAQ3E;AAED,mDAAmD;AACnD,wBAAgB,aAAa,CAAC,IAAI,SAAe,GAAG,cAAc,GAAG,eAAe,CAQnF;AAED,2DAA2D;AAC3D,wBAAgB,UAAU,IAAI,cAAc,GAAG,eAAe,CAQ7D"}
package/dist/index.d.ts CHANGED
@@ -1,150 +1,6 @@
1
- import { Express } from 'express';
2
- import { AppAdapter, Container } from '@forinda/kickjs-core';
3
-
4
- /**
5
- * Interface for converting validation library schemas to JSON Schema.
6
- *
7
- * KickJS ships with a Zod parser by default. To use a different validation
8
- * library (Yup, Joi, Valibot, ArkType, etc.), implement this interface and
9
- * pass it to the SwaggerAdapter.
10
- *
11
- * @example
12
- * ```ts
13
- * import Joi from 'joi'
14
- * import joiToJson from 'joi-to-json'
15
- *
16
- * const joiParser: SchemaParser = {
17
- * name: 'joi',
18
- * supports: (schema) => Joi.isSchema(schema),
19
- * toJsonSchema: (schema) => joiToJson(schema),
20
- * }
21
- *
22
- * new SwaggerAdapter({ schemaParser: joiParser })
23
- * ```
24
- */
25
- interface SchemaParser {
26
- /** Human-readable name for logging/debugging */
27
- readonly name: string;
28
- /**
29
- * Return true if this parser can handle the given schema object.
30
- * Called before `toJsonSchema` to allow graceful fallback.
31
- */
32
- supports(schema: unknown): boolean;
33
- /**
34
- * Convert a validation schema to a JSON Schema object.
35
- * Should return a plain object conforming to JSON Schema draft-07 or later.
36
- * Must not include the top-level `$schema` key — the builder adds it.
37
- */
38
- toJsonSchema(schema: unknown): Record<string, unknown>;
39
- }
40
- /**
41
- * Default schema parser for Zod v4+.
42
- * Uses Zod's built-in `.toJSONSchema()` instance method.
43
- */
44
- declare const zodSchemaParser: SchemaParser;
45
-
46
- interface ApiOperationOptions {
47
- summary?: string;
48
- description?: string;
49
- operationId?: string;
50
- deprecated?: boolean;
51
- }
52
- interface ApiResponseOptions {
53
- status: number;
54
- description?: string;
55
- schema?: any;
56
- /** Schema name in components/schemas (e.g., 'UserResponse', 'ErrorBody'). Auto-generated from handler name if omitted. */
57
- name?: string;
58
- }
59
- /** Attach operation metadata to a route handler */
60
- declare function ApiOperation(options: ApiOperationOptions): MethodDecorator;
61
- /** Document a response status. Can be stacked multiple times. */
62
- declare function ApiResponse(options: ApiResponseOptions): MethodDecorator;
63
- /** Apply OpenAPI tags at class or method level */
64
- declare function ApiTags(...tags: string[]): ClassDecorator & MethodDecorator;
65
- /** Mark endpoint as requiring Bearer token auth */
66
- declare function ApiBearerAuth(name?: string): ClassDecorator & MethodDecorator;
67
- /** Exclude a controller or method from the OpenAPI spec */
68
- declare function ApiExclude(): ClassDecorator & MethodDecorator;
69
-
70
- interface OpenAPIInfo {
71
- title: string;
72
- version: string;
73
- description?: string;
74
- }
75
- interface SwaggerOptions {
76
- info?: Partial<OpenAPIInfo>;
77
- servers?: {
78
- url: string;
79
- description?: string;
80
- }[];
81
- bearerAuth?: boolean;
82
- /**
83
- * Pluggable schema parser for converting validation schemas to JSON Schema.
84
- * Defaults to `zodSchemaParser` which handles Zod v4+ schemas.
85
- *
86
- * Override this to use Yup, Joi, Valibot, ArkType, or any other library.
87
- *
88
- * @example
89
- * ```ts
90
- * new SwaggerAdapter({
91
- * schemaParser: myYupParser,
92
- * })
93
- * ```
94
- */
95
- schemaParser?: SchemaParser;
96
- }
97
- /** Register a controller for OpenAPI introspection (called by Application during route mounting) */
98
- declare function registerControllerForDocs(controllerClass: any, mountPath: string): void;
99
- /** Clear all registered routes (for HMR) */
100
- declare function clearRegisteredRoutes(): void;
101
- /** Build a full OpenAPI 3.0.3 spec from registered controllers and their decorators */
102
- declare function buildOpenAPISpec(options?: SwaggerOptions): any;
103
-
104
- interface SwaggerAdapterOptions extends SwaggerOptions {
105
- /** Path to serve Swagger UI (default: '/docs') */
106
- docsPath?: string;
107
- /** Path to serve ReDoc (default: '/redoc') */
108
- redocPath?: string;
109
- /** Path to serve the raw JSON spec (default: '/openapi.json') */
110
- specPath?: string;
111
- /** Other adapters to discover (e.g., WsAdapter for WebSocket server URLs) */
112
- adapters?: any[];
113
- }
114
- /**
115
- * Swagger adapter — auto-generates OpenAPI spec from decorators and serves docs.
116
- *
117
- * @example
118
- * ```ts
119
- * bootstrap({
120
- * modules,
121
- * adapters: [
122
- * new SwaggerAdapter({
123
- * info: { title: 'My API', version: '1.0.0' },
124
- * }),
125
- * ],
126
- * })
127
- * ```
128
- *
129
- * Endpoints:
130
- * GET /docs — Swagger UI
131
- * GET /redoc — ReDoc
132
- * GET /openapi.json — Raw OpenAPI 3.0.3 spec
133
- */
134
- declare class SwaggerAdapter implements AppAdapter {
135
- private options;
136
- name: string;
137
- constructor(options?: SwaggerAdapterOptions);
138
- /** Auto-detect server URLs from the running HTTP server and peer adapters */
139
- afterStart(server: any, _container: Container): void;
140
- /** Collect controller metadata as routes are mounted */
141
- onRouteMount(controllerClass: any, mountPath: string): void;
142
- beforeMount(app: Express, _container: Container): void;
143
- }
144
-
145
- /** Generate Swagger UI HTML that loads from CDN */
146
- declare function swaggerUIHtml(specUrl: string, title?: string): string;
147
- /** Generate ReDoc HTML that loads from CDN */
148
- declare function redocHtml(specUrl: string, title?: string): string;
149
-
150
- export { ApiBearerAuth, ApiExclude, ApiOperation, type ApiOperationOptions, ApiResponse, type ApiResponseOptions, ApiTags, type OpenAPIInfo, type SchemaParser, SwaggerAdapter, type SwaggerAdapterOptions, type SwaggerOptions, buildOpenAPISpec, clearRegisteredRoutes, redocHtml, registerControllerForDocs, swaggerUIHtml, zodSchemaParser };
1
+ export { zodSchemaParser, type SchemaParser } from './schema-parser';
2
+ export { ApiOperation, ApiResponse, ApiTags, ApiBearerAuth, ApiExclude, type ApiOperationOptions, type ApiResponseOptions, } from './decorators';
3
+ export { buildOpenAPISpec, registerControllerForDocs, clearRegisteredRoutes, type OpenAPIInfo, type SwaggerOptions, } from './openapi-builder';
4
+ export { SwaggerAdapter, type SwaggerAdapterOptions } from './swagger.adapter';
5
+ export { swaggerUIHtml, redocHtml } from './ui';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAGpE,OAAO,EACL,YAAY,EACZ,WAAW,EACX,OAAO,EACP,aAAa,EACb,UAAU,EACV,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,GACxB,MAAM,cAAc,CAAA;AAGrB,OAAO,EACL,gBAAgB,EAChB,yBAAyB,EACzB,qBAAqB,EACrB,KAAK,WAAW,EAChB,KAAK,cAAc,GACpB,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AAG9E,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,MAAM,CAAA"}
package/dist/index.js CHANGED
@@ -1,35 +1,345 @@
1
- var z=Object.defineProperty;var c=(e,t)=>z(e,"name",{value:t,configurable:!0});var v={name:"zod",supports(e){return e!=null&&typeof e=="object"&&typeof e.safeParse=="function"&&typeof e.toJSONSchema=="function"},toJsonSchema(e){let{$schema:t,...o}=e.toJSONSchema();return o}};import"reflect-metadata";var p={OPERATION:Symbol("kick:swagger:operation"),RESPONSES:Symbol("kick:swagger:responses"),TAGS:Symbol("kick:swagger:tags"),BEARER_AUTH:Symbol("kick:swagger:bearer"),EXCLUDE:Symbol("kick:swagger:exclude")};function W(e){return(t,o)=>{Reflect.defineMetadata(p.OPERATION,e,t.constructor,o)}}c(W,"ApiOperation");function X(e){return(t,o)=>{let n=Reflect.getMetadata(p.RESPONSES,t.constructor,o)||[];Reflect.defineMetadata(p.RESPONSES,[...n,e],t.constructor,o)}}c(X,"ApiResponse");function Y(...e){return(t,o)=>{o?Reflect.defineMetadata(p.TAGS,e,t.constructor,o):Reflect.defineMetadata(p.TAGS,e,t)}}c(Y,"ApiTags");function Z(e="BearerAuth"){return(t,o)=>{o?Reflect.defineMetadata(p.BEARER_AUTH,e,t.constructor,o):Reflect.defineMetadata(p.BEARER_AUTH,e,t)}}c(Z,"ApiBearerAuth");function Q(){return(e,t)=>{t?Reflect.defineMetadata(p.EXCLUDE,!0,e.constructor,t):Reflect.defineMetadata(p.EXCLUDE,!0,e)}}c(Q,"ApiExclude");import"reflect-metadata";import{METADATA as x,joinPaths as V}from"@forinda/kickjs-core";var U=[];function j(e,t){U.push({controllerClass:e,mountPath:t})}c(j,"registerControllerForDocs");function M(){U.length=0}c(M,"clearRegisteredRoutes");function N(e={}){let t=e.schemaParser??v,o=c(a=>{try{return t.supports(a)?t.toJsonSchema(a):null}catch{return null}},"toJsonSchema"),n={},S=0,u=c((a,w)=>{let h=a.title||a.label||w||"";if(h||(h=`Schema${++S}`),h=h.replace(/[^a-zA-Z0-9]/g,""),!n[h]){let b={...a};delete b.title,delete b.label,delete b.$schema,n[h]=b}return{$ref:`#/components/schemas/${h}`}},"registerSchema"),r={openapi:"3.0.3",info:{title:e.info?.title||"API",version:e.info?.version||"1.0.0",...e.info?.description?{description:e.info.description}:{}},paths:{},components:{schemas:{},securitySchemes:{}},tags:[]};e.servers&&(r.servers=e.servers);let f=new Set,m={};for(let{controllerClass:a,mountPath:w}of U){if(Reflect.getMetadata(p.EXCLUDE,a))continue;let h=Reflect.getMetadata(x.ROUTES,a)||[],b=Reflect.getMetadata(p.TAGS,a)||[],L=Reflect.getMetadata(p.BEARER_AUTH,a);for(let i of h){if(Reflect.getMetadata(p.EXCLUDE,a,i.handlerName))continue;let D=V(w,i.path),q=D.replace(/:([a-zA-Z_]+)/g,"{$1}"),E=i.method.toLowerCase(),A=Reflect.getMetadata(p.OPERATION,a,i.handlerName)||{},C=Reflect.getMetadata(p.RESPONSES,a,i.handlerName)||[],H=Reflect.getMetadata(p.TAGS,a,i.handlerName)||[],G=Reflect.getMetadata(p.BEARER_AUTH,a,i.handlerName),T=H.length>0?H:b;T.forEach(s=>f.add(s));let l={...T.length>0?{tags:T}:{},...A.summary?{summary:A.summary}:{},...A.description?{description:A.description}:{},...A.operationId?{operationId:A.operationId}:{},...A.deprecated?{deprecated:!0}:{},parameters:[],responses:{}},J=D.match(/:([a-zA-Z_]+)/g)||[];for(let s of J){let d=s.slice(1),g={type:"string"};if(i.validation?.params){let y=o(i.validation.params);if(y?.properties&&typeof y.properties=="object"){let F=y.properties;F[d]&&(g=F[d])}}l.parameters.push({name:d,in:"path",required:!0,schema:g})}if(i.validation?.query){let s=o(i.validation.query);if(s?.properties&&typeof s.properties=="object"){let d=Array.isArray(s.required)?s.required:[];for(let[g,y]of Object.entries(s.properties))l.parameters.push({name:g,in:"query",required:d.includes(g),schema:y})}}let R=Reflect.getMetadata(x.QUERY_PARAMS,a,i.handlerName);if(R&&(R.filterable?.length&&l.parameters.push({name:"filter",in:"query",required:!1,description:`Filter fields: ${R.filterable.join(", ")}. Format: \`field:operator:value\`. Operators: eq, neq, gt, gte, lt, lte, contains, starts, ends, in, between`,schema:{type:"array",items:{type:"string"}},style:"form",explode:!0}),R.sortable?.length&&l.parameters.push({name:"sort",in:"query",required:!1,description:`Sort fields: ${R.sortable.join(", ")}. Format: \`field:asc\` or \`field:desc\``,schema:{type:"array",items:{type:"string"}},style:"form",explode:!0}),R.searchable?.length&&l.parameters.push({name:"q",in:"query",required:!1,description:`Search across: ${R.searchable.join(", ")}`,schema:{type:"string"}}),l.parameters.push({name:"page",in:"query",required:!1,description:"Page number (default: 1)",schema:{type:"integer",minimum:1,default:1}},{name:"limit",in:"query",required:!1,description:"Items per page (default: 20, max: 100)",schema:{type:"integer",minimum:1,maximum:100,default:20}})),l.parameters.length===0&&delete l.parameters,i.validation?.body&&["post","put","patch"].includes(E)){let s=o(i.validation.body);if(s){let d=i.validation.name||`${i.handlerName}Body`,g=u(s,d);l.requestBody={required:!0,content:{"application/json":{schema:g}}}}}let P=Reflect.getMetadata(x.FILE_UPLOAD,a,i.handlerName);if(P){let s=P.fieldName??"file",d={};P.mode==="array"?d[s]={type:"array",items:{type:"string",format:"binary"}}:P.mode!=="none"&&(d[s]={type:"string",format:"binary"}),l.requestBody={required:!0,content:{"multipart/form-data":{schema:{type:"object",properties:d}}}}}if(C.length>0)for(let s of C)l.responses[String(s.status)]={description:s.description||"",...s.schema?(()=>{let d=typeof s.schema=="function"||typeof s.schema=="object"?o(s.schema):null,g=s.name||`${i.handlerName}Response${s.status}`,y=d?u(d,g):typeof s.schema=="object"?s.schema:void 0;return y?{content:{"application/json":{schema:y}}}:{}})():{}};else{let s=E==="post"?"201":E==="delete"?"204":"200";l.responses[s]={description:"Successful operation"},i.validation?.body&&(l.responses[422]={description:"Validation error"})}let O=G||L;O&&(l.security=[{[O]:[]}],m[O]={type:"http",scheme:"bearer",bearerFormat:"JWT"}),r.paths[q]||(r.paths[q]={}),r.paths[q][E]=l}}return r.tags=Array.from(f).map(a=>({name:a})),r.components.securitySchemes=m,e.bearerAuth&&(m.BearerAuth||(r.components.securitySchemes.BearerAuth={type:"http",scheme:"bearer",bearerFormat:"JWT"}),r.security=[{BearerAuth:[]}]),r.components.schemas=n,Object.keys(r.components.schemas).length===0&&delete r.components.schemas,Object.keys(r.components.securitySchemes).length===0&&delete r.components.securitySchemes,Object.keys(r.components).length===0&&delete r.components,r}c(N,"buildOpenAPISpec");import{Router as K}from"express";import{Logger as ee}from"@forinda/kickjs-core";function $(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}c($,"escapeHtml");function k(e,t="API Docs"){let o=$(t),n=JSON.stringify(e).replace(/</g,"\\u003c");return`<!DOCTYPE html>
1
+ import "reflect-metadata";
2
+ import { Logger as D, METADATA as T, joinPaths as C } from "@forinda/kickjs-core";
3
+ import { Router as L } from "express";
4
+ var H = {
5
+ name: "zod",
6
+ supports(e) {
7
+ return e != null && typeof e == "object" && typeof e.safeParse == "function" && typeof e.toJSONSchema == "function";
8
+ },
9
+ toJsonSchema(e) {
10
+ const { $schema: r, ...t } = e.toJSONSchema();
11
+ return t;
12
+ }
13
+ }, i = {
14
+ OPERATION: /* @__PURE__ */ Symbol("kick:swagger:operation"),
15
+ RESPONSES: /* @__PURE__ */ Symbol("kick:swagger:responses"),
16
+ TAGS: /* @__PURE__ */ Symbol("kick:swagger:tags"),
17
+ BEARER_AUTH: /* @__PURE__ */ Symbol("kick:swagger:bearer"),
18
+ EXCLUDE: /* @__PURE__ */ Symbol("kick:swagger:exclude")
19
+ };
20
+ function Z(e) {
21
+ return (r, t) => {
22
+ Reflect.defineMetadata(i.OPERATION, e, r.constructor, t);
23
+ };
24
+ }
25
+ function Q(e) {
26
+ return (r, t) => {
27
+ const d = Reflect.getMetadata(i.RESPONSES, r.constructor, t) || [];
28
+ Reflect.defineMetadata(i.RESPONSES, [...d, e], r.constructor, t);
29
+ };
30
+ }
31
+ function V(...e) {
32
+ return (r, t) => {
33
+ t ? Reflect.defineMetadata(i.TAGS, e, r.constructor, t) : Reflect.defineMetadata(i.TAGS, e, r);
34
+ };
35
+ }
36
+ function K(e = "BearerAuth") {
37
+ return (r, t) => {
38
+ t ? Reflect.defineMetadata(i.BEARER_AUTH, e, r.constructor, t) : Reflect.defineMetadata(i.BEARER_AUTH, e, r);
39
+ };
40
+ }
41
+ function ee() {
42
+ return (e, r) => {
43
+ r ? Reflect.defineMetadata(i.EXCLUDE, !0, e.constructor, r) : Reflect.defineMetadata(i.EXCLUDE, !0, e);
44
+ };
45
+ }
46
+ var M = [];
47
+ function F(e, r) {
48
+ M.push({
49
+ controllerClass: e,
50
+ mountPath: r
51
+ });
52
+ }
53
+ function x() {
54
+ M.length = 0;
55
+ }
56
+ function J(e = {}) {
57
+ const r = e.schemaParser ?? H, t = (o) => {
58
+ try {
59
+ return r.supports(o) ? r.toJsonSchema(o) : null;
60
+ } catch {
61
+ return null;
62
+ }
63
+ }, d = {};
64
+ let u = 0;
65
+ const p = (o, w) => {
66
+ let f = o.title || o.label || w || "";
67
+ if (f || (f = `Schema${++u}`), f = f.replace(/[^a-zA-Z0-9]/g, ""), !d[f]) {
68
+ const R = { ...o };
69
+ delete R.title, delete R.label, delete R.$schema, d[f] = R;
70
+ }
71
+ return { $ref: `#/components/schemas/${f}` };
72
+ }, a = {
73
+ openapi: "3.0.3",
74
+ info: {
75
+ title: e.info?.title || "API",
76
+ version: e.info?.version || "1.0.0",
77
+ ...e.info?.description ? { description: e.info.description } : {}
78
+ },
79
+ paths: {},
80
+ components: {
81
+ schemas: {},
82
+ securitySchemes: {}
83
+ },
84
+ tags: []
85
+ };
86
+ e.servers && (a.servers = e.servers);
87
+ const m = /* @__PURE__ */ new Set(), g = {};
88
+ for (const { controllerClass: o, mountPath: w } of M) {
89
+ if (Reflect.getMetadata(i.EXCLUDE, o)) continue;
90
+ const f = Reflect.getMetadata(T.ROUTES, o) || [], R = Reflect.getMetadata(i.TAGS, o) || [], I = Reflect.getMetadata(i.BEARER_AUTH, o);
91
+ for (const n of f) {
92
+ if (Reflect.getMetadata(i.EXCLUDE, o, n.handlerName)) continue;
93
+ const $ = C(w, n.path), P = $.replace(/:([a-zA-Z_]+)/g, "{$1}"), b = n.method.toLowerCase(), y = Reflect.getMetadata(i.OPERATION, o, n.handlerName) || {}, N = Reflect.getMetadata(i.RESPONSES, o, n.handlerName) || [], k = Reflect.getMetadata(i.TAGS, o, n.handlerName) || [], _ = Reflect.getMetadata(i.BEARER_AUTH, o, n.handlerName), v = k.length > 0 ? k : R;
94
+ v.forEach((s) => m.add(s));
95
+ const c = {
96
+ ...v.length > 0 ? { tags: v } : {},
97
+ ...y.summary ? { summary: y.summary } : {},
98
+ ...y.description ? { description: y.description } : {},
99
+ ...y.operationId ? { operationId: y.operationId } : {},
100
+ ...y.deprecated ? { deprecated: !0 } : {},
101
+ parameters: [],
102
+ responses: {}
103
+ }, B = $.match(/:([a-zA-Z_]+)/g) || [];
104
+ for (const s of B) {
105
+ const l = s.slice(1);
106
+ let A = { type: "string" };
107
+ if (n.validation?.params) {
108
+ const h = t(n.validation.params);
109
+ if (h?.properties && typeof h.properties == "object") {
110
+ const U = h.properties;
111
+ U[l] && (A = U[l]);
112
+ }
113
+ }
114
+ c.parameters.push({
115
+ name: l,
116
+ in: "path",
117
+ required: !0,
118
+ schema: A
119
+ });
120
+ }
121
+ if (n.validation?.query) {
122
+ const s = t(n.validation.query);
123
+ if (s?.properties && typeof s.properties == "object") {
124
+ const l = Array.isArray(s.required) ? s.required : [];
125
+ for (const [A, h] of Object.entries(s.properties)) c.parameters.push({
126
+ name: A,
127
+ in: "query",
128
+ required: l.includes(A),
129
+ schema: h
130
+ });
131
+ }
132
+ }
133
+ const S = Reflect.getMetadata(T.QUERY_PARAMS, o, n.handlerName);
134
+ if (S && (S.filterable?.length && c.parameters.push({
135
+ name: "filter",
136
+ in: "query",
137
+ required: !1,
138
+ description: `Filter fields: ${S.filterable.join(", ")}. Format: \`field:operator:value\`. Operators: eq, neq, gt, gte, lt, lte, contains, starts, ends, in, between`,
139
+ schema: {
140
+ type: "array",
141
+ items: { type: "string" }
142
+ },
143
+ style: "form",
144
+ explode: !0
145
+ }), S.sortable?.length && c.parameters.push({
146
+ name: "sort",
147
+ in: "query",
148
+ required: !1,
149
+ description: `Sort fields: ${S.sortable.join(", ")}. Format: \`field:asc\` or \`field:desc\``,
150
+ schema: {
151
+ type: "array",
152
+ items: { type: "string" }
153
+ },
154
+ style: "form",
155
+ explode: !0
156
+ }), S.searchable?.length && c.parameters.push({
157
+ name: "q",
158
+ in: "query",
159
+ required: !1,
160
+ description: `Search across: ${S.searchable.join(", ")}`,
161
+ schema: { type: "string" }
162
+ }), c.parameters.push({
163
+ name: "page",
164
+ in: "query",
165
+ required: !1,
166
+ description: "Page number (default: 1)",
167
+ schema: {
168
+ type: "integer",
169
+ minimum: 1,
170
+ default: 1
171
+ }
172
+ }, {
173
+ name: "limit",
174
+ in: "query",
175
+ required: !1,
176
+ description: "Items per page (default: 20, max: 100)",
177
+ schema: {
178
+ type: "integer",
179
+ minimum: 1,
180
+ maximum: 100,
181
+ default: 20
182
+ }
183
+ })), c.parameters.length === 0 && delete c.parameters, n.validation?.body && [
184
+ "post",
185
+ "put",
186
+ "patch"
187
+ ].includes(b)) {
188
+ const s = t(n.validation.body);
189
+ if (s) {
190
+ const l = p(s, n.validation.name || `${n.handlerName}Body`);
191
+ c.requestBody = {
192
+ required: !0,
193
+ content: { "application/json": { schema: l } }
194
+ };
195
+ }
196
+ }
197
+ const E = Reflect.getMetadata(T.FILE_UPLOAD, o, n.handlerName);
198
+ if (E) {
199
+ const s = E.fieldName ?? "file", l = {};
200
+ E.mode === "array" ? l[s] = {
201
+ type: "array",
202
+ items: {
203
+ type: "string",
204
+ format: "binary"
205
+ }
206
+ } : E.mode !== "none" && (l[s] = {
207
+ type: "string",
208
+ format: "binary"
209
+ }), c.requestBody = {
210
+ required: !0,
211
+ content: { "multipart/form-data": { schema: {
212
+ type: "object",
213
+ properties: l
214
+ } } }
215
+ };
216
+ }
217
+ if (N.length > 0) for (const s of N) c.responses[String(s.status)] = {
218
+ description: s.description || "",
219
+ ...s.schema ? (() => {
220
+ const l = typeof s.schema == "function" || typeof s.schema == "object" ? t(s.schema) : null, A = s.name || `${n.handlerName}Response${s.status}`, h = l ? p(l, A) : typeof s.schema == "object" ? s.schema : void 0;
221
+ return h ? { content: { "application/json": { schema: h } } } : {};
222
+ })() : {}
223
+ };
224
+ else {
225
+ const s = b === "post" ? "201" : b === "delete" ? "204" : "200";
226
+ c.responses[s] = { description: "Successful operation" }, n.validation?.body && (c.responses[422] = { description: "Validation error" });
227
+ }
228
+ const q = _ || I;
229
+ q && (c.security = [{ [q]: [] }], g[q] = {
230
+ type: "http",
231
+ scheme: "bearer",
232
+ bearerFormat: "JWT"
233
+ }), a.paths[P] || (a.paths[P] = {}), a.paths[P][b] = c;
234
+ }
235
+ }
236
+ return a.tags = Array.from(m).map((o) => ({ name: o })), a.components.securitySchemes = g, e.bearerAuth && (g.BearerAuth || (a.components.securitySchemes.BearerAuth = {
237
+ type: "http",
238
+ scheme: "bearer",
239
+ bearerFormat: "JWT"
240
+ }), a.security = [{ BearerAuth: [] }]), a.components.schemas = d, Object.keys(a.components.schemas).length === 0 && delete a.components.schemas, Object.keys(a.components.securitySchemes).length === 0 && delete a.components.securitySchemes, Object.keys(a.components).length === 0 && delete a.components, a;
241
+ }
242
+ function j(e) {
243
+ return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
244
+ }
245
+ function G(e, r = "API Docs") {
246
+ return `<!DOCTYPE html>
2
247
  <html lang="en">
3
248
  <head>
4
249
  <meta charset="UTF-8">
5
250
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>${o}</title>
251
+ <title>${j(r)}</title>
7
252
  <link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css">
8
253
  </head>
9
254
  <body>
10
255
  <div id="swagger-ui"></div>
11
- <script src="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js"></script>
12
- <script src="https://unpkg.com/swagger-ui-dist@5/swagger-ui-standalone-preset.js"></script>
256
+ <script src="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js"><\/script>
257
+ <script src="https://unpkg.com/swagger-ui-dist@5/swagger-ui-standalone-preset.js"><\/script>
13
258
  <script>
14
259
  SwaggerUIBundle({
15
- url: ${n},
260
+ url: ${JSON.stringify(e).replace(/</g, "\\u003c")},
16
261
  dom_id: '#swagger-ui',
17
262
  deepLinking: true,
18
263
  presets: [SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset],
19
264
  plugins: [SwaggerUIBundle.plugins.DownloadUrl],
20
265
  layout: 'StandaloneLayout',
21
266
  });
22
- </script>
267
+ <\/script>
23
268
  </body>
24
- </html>`}c(k,"swaggerUIHtml");function I(e,t="API Docs"){let o=$(t),n=$(e);return`<!DOCTYPE html>
269
+ </html>`;
270
+ }
271
+ function z(e, r = "API Docs") {
272
+ return `<!DOCTYPE html>
25
273
  <html lang="en">
26
274
  <head>
27
275
  <meta charset="UTF-8">
28
276
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
29
- <title>${o}</title>
277
+ <title>${j(r)}</title>
30
278
  </head>
31
279
  <body>
32
- <redoc spec-url="${n}"></redoc>
33
- <script src="https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js"></script>
280
+ <redoc spec-url="${j(e)}"></redoc>
281
+ <script src="https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js"><\/script>
34
282
  </body>
35
- </html>`}c(I,"redocHtml");var _=ee.for("SwaggerAdapter"),B=class{static{c(this,"SwaggerAdapter")}options;name="SwaggerAdapter";constructor(t={}){this.options=t}afterStart(t,o){let n=t?.address?.();if(!n||typeof n!="object")return;let S=n.address==="::"||n.address==="0.0.0.0"?"localhost":n.address;(!this.options.servers||this.options.servers.length===0)&&(this.options.servers=[{url:`http://${S}:${n.port}`,description:"HTTP server"}]);let u=this.options.adapters?.find(r=>r.name==="WsAdapter"&&typeof r.getStats=="function");if(u){let r=u.getStats();for(let f of Object.keys(r.namespaces||{}))this.options.servers.push({url:`ws://${S}:${n.port}${f}`,description:`WebSocket: ${f}`})}}onRouteMount(t,o){j(t,o)}beforeMount(t,o){M();let n=this.options.docsPath??"/docs",S=this.options.redocPath??"/redoc",u=this.options.specPath??"/openapi.json",r=K();r.use((f,m,a)=>{m.setHeader("Content-Security-Policy",["default-src 'self'","script-src 'self' 'unsafe-inline' https://unpkg.com https://cdn.redoc.ly https://cdn.jsdelivr.net","style-src 'self' 'unsafe-inline' https://unpkg.com https://fonts.googleapis.com","font-src 'self' https://fonts.gstatic.com","img-src 'self' data: https://unpkg.com","connect-src 'self'"].join("; ")),a()}),r.get(u,(f,m)=>{let a=N(this.options);m.json(a)}),r.get(n,(f,m)=>{m.type("html").send(k(u,this.options.info?.title))}),r.get(S,(f,m)=>{m.type("html").send(I(u,this.options.info?.title))}),t.use(r),_.info(`Swagger UI: ${n}`),_.info(`ReDoc: ${S}`),_.info(`OpenAPI spec: ${u}`)}};export{Z as ApiBearerAuth,Q as ApiExclude,W as ApiOperation,X as ApiResponse,Y as ApiTags,B as SwaggerAdapter,N as buildOpenAPISpec,M as clearRegisteredRoutes,I as redocHtml,j as registerControllerForDocs,k as swaggerUIHtml,v as zodSchemaParser};
283
+ </html>`;
284
+ }
285
+ var O = D.for("SwaggerAdapter"), te = class {
286
+ name = "SwaggerAdapter";
287
+ constructor(e = {}) {
288
+ this.options = e;
289
+ }
290
+ afterStart(e, r) {
291
+ const t = e?.address?.();
292
+ if (!t || typeof t != "object") return;
293
+ const d = t.address === "::" || t.address === "0.0.0.0" ? "localhost" : t.address;
294
+ (!this.options.servers || this.options.servers.length === 0) && (this.options.servers = [{
295
+ url: `http://${d}:${t.port}`,
296
+ description: "HTTP server"
297
+ }]);
298
+ const u = this.options.adapters?.find((p) => p.name === "WsAdapter" && typeof p.getStats == "function");
299
+ if (u) {
300
+ const p = u.getStats();
301
+ for (const a of Object.keys(p.namespaces || {})) this.options.servers.push({
302
+ url: `ws://${d}:${t.port}${a}`,
303
+ description: `WebSocket: ${a}`
304
+ });
305
+ }
306
+ }
307
+ onRouteMount(e, r) {
308
+ F(e, r);
309
+ }
310
+ beforeMount(e, r) {
311
+ x();
312
+ const t = this.options.docsPath ?? "/docs", d = this.options.redocPath ?? "/redoc", u = this.options.specPath ?? "/openapi.json", p = L();
313
+ p.use((a, m, g) => {
314
+ m.setHeader("Content-Security-Policy", [
315
+ "default-src 'self'",
316
+ "script-src 'self' 'unsafe-inline' https://unpkg.com https://cdn.redoc.ly https://cdn.jsdelivr.net",
317
+ "style-src 'self' 'unsafe-inline' https://unpkg.com https://fonts.googleapis.com",
318
+ "font-src 'self' https://fonts.gstatic.com",
319
+ "img-src 'self' data: https://unpkg.com",
320
+ "connect-src 'self'"
321
+ ].join("; ")), g();
322
+ }), p.get(u, (a, m) => {
323
+ const g = J(this.options);
324
+ m.json(g);
325
+ }), p.get(t, (a, m) => {
326
+ m.type("html").send(G(u, this.options.info?.title));
327
+ }), p.get(d, (a, m) => {
328
+ m.type("html").send(z(u, this.options.info?.title));
329
+ }), e.use(p), O.info(`Swagger UI: ${t}`), O.info(`ReDoc: ${d}`), O.info(`OpenAPI spec: ${u}`);
330
+ }
331
+ };
332
+ export {
333
+ K as ApiBearerAuth,
334
+ ee as ApiExclude,
335
+ Z as ApiOperation,
336
+ Q as ApiResponse,
337
+ V as ApiTags,
338
+ te as SwaggerAdapter,
339
+ J as buildOpenAPISpec,
340
+ x as clearRegisteredRoutes,
341
+ z as redocHtml,
342
+ F as registerControllerForDocs,
343
+ G as swaggerUIHtml,
344
+ H as zodSchemaParser
345
+ };
@@ -0,0 +1,36 @@
1
+ import 'reflect-metadata';
2
+ import { type SchemaParser } from './schema-parser';
3
+ export interface OpenAPIInfo {
4
+ title: string;
5
+ version: string;
6
+ description?: string;
7
+ }
8
+ export interface SwaggerOptions {
9
+ info?: Partial<OpenAPIInfo>;
10
+ servers?: {
11
+ url: string;
12
+ description?: string;
13
+ }[];
14
+ bearerAuth?: boolean;
15
+ /**
16
+ * Pluggable schema parser for converting validation schemas to JSON Schema.
17
+ * Defaults to `zodSchemaParser` which handles Zod v4+ schemas.
18
+ *
19
+ * Override this to use Yup, Joi, Valibot, ArkType, or any other library.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * new SwaggerAdapter({
24
+ * schemaParser: myYupParser,
25
+ * })
26
+ * ```
27
+ */
28
+ schemaParser?: SchemaParser;
29
+ }
30
+ /** Register a controller for OpenAPI introspection (called by Application during route mounting) */
31
+ export declare function registerControllerForDocs(controllerClass: any, mountPath: string): void;
32
+ /** Clear all registered routes (for HMR) */
33
+ export declare function clearRegisteredRoutes(): void;
34
+ /** Build a full OpenAPI 3.0.3 spec from registered controllers and their decorators */
35
+ export declare function buildOpenAPISpec(options?: SwaggerOptions): any;
36
+ //# sourceMappingURL=openapi-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openapi-builder.d.ts","sourceRoot":"","sources":["../src/openapi-builder.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAA;AAGzB,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAEpE,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;IAC3B,OAAO,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACjD,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;;;;;;;;;OAYG;IACH,YAAY,CAAC,EAAE,YAAY,CAAA;CAC5B;AASD,oGAAoG;AACpG,wBAAgB,yBAAyB,CAAC,eAAe,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAEvF;AAED,4CAA4C;AAC5C,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED,uFAAuF;AACvF,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,cAAmB,GAAG,GAAG,CA6UlE"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Interface for converting validation library schemas to JSON Schema.
3
+ *
4
+ * KickJS ships with a Zod parser by default. To use a different validation
5
+ * library (Yup, Joi, Valibot, ArkType, etc.), implement this interface and
6
+ * pass it to the SwaggerAdapter.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import Joi from 'joi'
11
+ * import joiToJson from 'joi-to-json'
12
+ *
13
+ * const joiParser: SchemaParser = {
14
+ * name: 'joi',
15
+ * supports: (schema) => Joi.isSchema(schema),
16
+ * toJsonSchema: (schema) => joiToJson(schema),
17
+ * }
18
+ *
19
+ * new SwaggerAdapter({ schemaParser: joiParser })
20
+ * ```
21
+ */
22
+ export interface SchemaParser {
23
+ /** Human-readable name for logging/debugging */
24
+ readonly name: string;
25
+ /**
26
+ * Return true if this parser can handle the given schema object.
27
+ * Called before `toJsonSchema` to allow graceful fallback.
28
+ */
29
+ supports(schema: unknown): boolean;
30
+ /**
31
+ * Convert a validation schema to a JSON Schema object.
32
+ * Should return a plain object conforming to JSON Schema draft-07 or later.
33
+ * Must not include the top-level `$schema` key — the builder adds it.
34
+ */
35
+ toJsonSchema(schema: unknown): Record<string, unknown>;
36
+ }
37
+ /**
38
+ * Default schema parser for Zod v4+.
39
+ * Uses Zod's built-in `.toJSONSchema()` instance method.
40
+ */
41
+ export declare const zodSchemaParser: SchemaParser;
42
+ //# sourceMappingURL=schema-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-parser.d.ts","sourceRoot":"","sources":["../src/schema-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,YAAY;IAC3B,gDAAgD;IAChD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IAErB;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAA;IAElC;;;;OAIG;IACH,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACvD;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,YAgB7B,CAAA"}
@@ -0,0 +1,45 @@
1
+ import type { Express } from 'express';
2
+ import { type AppAdapter, type Container } from '@forinda/kickjs-core';
3
+ import { registerControllerForDocs, clearRegisteredRoutes, type SwaggerOptions } from './openapi-builder';
4
+ export interface SwaggerAdapterOptions extends SwaggerOptions {
5
+ /** Path to serve Swagger UI (default: '/docs') */
6
+ docsPath?: string;
7
+ /** Path to serve ReDoc (default: '/redoc') */
8
+ redocPath?: string;
9
+ /** Path to serve the raw JSON spec (default: '/openapi.json') */
10
+ specPath?: string;
11
+ /** Other adapters to discover (e.g., WsAdapter for WebSocket server URLs) */
12
+ adapters?: any[];
13
+ }
14
+ /**
15
+ * Swagger adapter — auto-generates OpenAPI spec from decorators and serves docs.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * bootstrap({
20
+ * modules,
21
+ * adapters: [
22
+ * new SwaggerAdapter({
23
+ * info: { title: 'My API', version: '1.0.0' },
24
+ * }),
25
+ * ],
26
+ * })
27
+ * ```
28
+ *
29
+ * Endpoints:
30
+ * GET /docs — Swagger UI
31
+ * GET /redoc — ReDoc
32
+ * GET /openapi.json — Raw OpenAPI 3.0.3 spec
33
+ */
34
+ export declare class SwaggerAdapter implements AppAdapter {
35
+ private options;
36
+ name: string;
37
+ constructor(options?: SwaggerAdapterOptions);
38
+ /** Auto-detect server URLs from the running HTTP server and peer adapters */
39
+ afterStart(server: any, _container: Container): void;
40
+ /** Collect controller metadata as routes are mounted */
41
+ onRouteMount(controllerClass: any, mountPath: string): void;
42
+ beforeMount(app: Express, _container: Container): void;
43
+ }
44
+ export { registerControllerForDocs, clearRegisteredRoutes };
45
+ //# sourceMappingURL=swagger.adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swagger.adapter.d.ts","sourceRoot":"","sources":["../src/swagger.adapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAU,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAC9E,OAAO,EAEL,yBAAyB,EACzB,qBAAqB,EACrB,KAAK,cAAc,EACpB,MAAM,mBAAmB,CAAA;AAK1B,MAAM,WAAW,qBAAsB,SAAQ,cAAc;IAC3D,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,iEAAiE;IACjE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,GAAG,EAAE,CAAA;CACjB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,cAAe,YAAW,UAAU;IAGnC,OAAO,CAAC,OAAO;IAF3B,IAAI,SAAmB;gBAEH,OAAO,GAAE,qBAA0B;IAEvD,6EAA6E;IAC7E,UAAU,CAAC,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,SAAS,GAAG,IAAI;IA0BpD,wDAAwD;IACxD,YAAY,CAAC,eAAe,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAI3D,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,GAAG,IAAI;CA+CvD;AAGD,OAAO,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,CAAA"}
package/dist/ui.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ /** Generate Swagger UI HTML that loads from CDN */
2
+ export declare function swaggerUIHtml(specUrl: string, title?: string): string;
3
+ /** Generate ReDoc HTML that loads from CDN */
4
+ export declare function redocHtml(specUrl: string, title?: string): string;
5
+ //# sourceMappingURL=ui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAUA,mDAAmD;AACnD,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,SAAa,GAAG,MAAM,CA4BzE;AAED,8CAA8C;AAC9C,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,SAAa,GAAG,MAAM,CAgBrE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forinda/kickjs-swagger",
3
- "version": "1.3.2",
3
+ "version": "1.4.1-alpha.0",
4
4
  "description": "OpenAPI spec generation from decorators, Swagger UI and ReDoc serving for KickJS",
5
5
  "keywords": [
6
6
  "kickjs",
@@ -34,7 +34,8 @@
34
34
  "@forinda/kickjs-queue",
35
35
  "@forinda/kickjs-multi-tenant",
36
36
  "@forinda/kickjs-devtools",
37
- "@forinda/kickjs-notifications"
37
+ "@forinda/kickjs-notifications",
38
+ "vite"
38
39
  ],
39
40
  "type": "module",
40
41
  "main": "dist/index.js",
@@ -50,7 +51,7 @@
50
51
  ],
51
52
  "dependencies": {
52
53
  "reflect-metadata": "^0.2.2",
53
- "@forinda/kickjs-core": "1.3.2"
54
+ "@forinda/kickjs-core": "1.4.1-alpha.0"
54
55
  },
55
56
  "peerDependencies": {
56
57
  "express": "^5.1.0",
@@ -64,11 +65,10 @@
64
65
  "devDependencies": {
65
66
  "@swc/core": "^1.7.28",
66
67
  "@types/express": "^5.0.6",
67
- "@types/node": "^24.5.2",
68
+ "@types/node": "^25.0.0",
68
69
  "express": "^5.1.0",
69
- "tsup": "^8.5.0",
70
70
  "typescript": "^5.9.2",
71
- "vitest": "^3.2.4",
71
+ "vitest": "^4.1.1",
72
72
  "zod": "^4.3.6"
73
73
  },
74
74
  "publishConfig": {
@@ -89,8 +89,9 @@
89
89
  "url": "https://github.com/forinda/kick-js/issues"
90
90
  },
91
91
  "scripts": {
92
- "build": "tsup",
93
- "dev": "tsup --watch",
92
+ "build": "vite build && pnpm build:types",
93
+ "build:types": "tsc -p tsconfig.build.json",
94
+ "dev": "vite build --watch",
94
95
  "test": "vitest run --passWithNoTests",
95
96
  "test:watch": "vitest",
96
97
  "typecheck": "tsc --noEmit",