yaxa-svelte 2.2.0 → 2.4.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.
Files changed (39) hide show
  1. package/README.md +85 -14
  2. package/dist/server/db/schema-pg.d.ts +262 -0
  3. package/dist/server/db/schema-pg.js +20 -0
  4. package/dist/server/db/schema-sqlite.d.ts +276 -0
  5. package/dist/server/db/schema-sqlite.js +20 -0
  6. package/dist/server/db/types.d.ts +18 -0
  7. package/dist/server/endpoint/guards.d.ts +5 -0
  8. package/dist/server/endpoint/guards.js +19 -3
  9. package/dist/server/endpoint/index.js +4 -0
  10. package/dist/server/endpoint/types.d.ts +7 -0
  11. package/dist/server/index.d.ts +4 -0
  12. package/dist/server/index.js +4 -0
  13. package/dist/server/jobs/events.d.ts +29 -0
  14. package/dist/server/jobs/events.js +74 -0
  15. package/dist/server/jobs/index.d.ts +4 -0
  16. package/dist/server/jobs/index.js +3 -0
  17. package/dist/server/jobs/jobs.test.d.ts +1 -0
  18. package/dist/server/jobs/jobs.test.js +189 -0
  19. package/dist/server/jobs/queue.d.ts +14 -0
  20. package/dist/server/jobs/queue.js +90 -0
  21. package/dist/server/jobs/runner.d.ts +12 -0
  22. package/dist/server/jobs/runner.js +176 -0
  23. package/dist/server/jobs/types.d.ts +136 -0
  24. package/dist/server/jobs/types.js +1 -0
  25. package/dist/server/openapi/generator.d.ts +5 -0
  26. package/dist/server/openapi/generator.js +317 -0
  27. package/dist/server/openapi/handler.d.ts +7 -0
  28. package/dist/server/openapi/handler.js +117 -0
  29. package/dist/server/openapi/index.d.ts +5 -0
  30. package/dist/server/openapi/index.js +4 -0
  31. package/dist/server/openapi/openapi.test.d.ts +1 -0
  32. package/dist/server/openapi/openapi.test.js +219 -0
  33. package/dist/server/openapi/registry.d.ts +35 -0
  34. package/dist/server/openapi/registry.js +51 -0
  35. package/dist/server/openapi/schema.d.ts +4 -0
  36. package/dist/server/openapi/schema.js +59 -0
  37. package/dist/server/openapi/types.d.ts +127 -0
  38. package/dist/server/openapi/types.js +1 -0
  39. package/package.json +1 -1
@@ -0,0 +1,117 @@
1
+ import { generateOpenApiSpec } from './generator';
2
+ function renderScalarHtml(specJson, title) {
3
+ return `<!doctype html>
4
+ <html lang="en">
5
+ <head>
6
+ <meta charset="utf-8" />
7
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
8
+ <title>${title}</title>
9
+ <style>
10
+ body { margin: 0; background-color: #0f172a; }
11
+ </style>
12
+ </head>
13
+ <body>
14
+ <script id="api-reference" data-configuration='{"darkMode":true,"layout":"modern"}' type="application/json">
15
+ ${specJson}
16
+ </script>
17
+ <script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"></script>
18
+ </body>
19
+ </html>`;
20
+ }
21
+ function renderSwaggerHtml(specJson, title) {
22
+ return `<!DOCTYPE html>
23
+ <html lang="en">
24
+ <head>
25
+ <meta charset="utf-8" />
26
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
27
+ <title>${title}</title>
28
+ <link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css" />
29
+ <style>
30
+ body { margin: 0; background: #fafafa; }
31
+ </style>
32
+ </head>
33
+ <body>
34
+ <div id="swagger-ui"></div>
35
+ <script src="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js"></script>
36
+ <script>
37
+ window.ui = SwaggerUIBundle({
38
+ spec: ${specJson},
39
+ dom_id: '#swagger-ui',
40
+ deepLinking: true,
41
+ presets: [
42
+ SwaggerUIBundle.presets.apis,
43
+ SwaggerUIBundle.SwaggerUIStandalonePreset
44
+ ],
45
+ layout: "BaseLayout"
46
+ });
47
+ </script>
48
+ </body>
49
+ </html>`;
50
+ }
51
+ function renderRedocHtml(specJson, title) {
52
+ return `<!DOCTYPE html>
53
+ <html lang="en">
54
+ <head>
55
+ <meta charset="utf-8" />
56
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
57
+ <title>${title}</title>
58
+ <style>
59
+ body { margin: 0; padding: 0; }
60
+ </style>
61
+ </head>
62
+ <body>
63
+ <div id="redoc-container"></div>
64
+ <script src="https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js"></script>
65
+ <script>
66
+ Redoc.init(${specJson}, {
67
+ scrollYOffset: 50,
68
+ theme: {
69
+ colors: { primary: { main: '#3b82f6' } }
70
+ }
71
+ }, document.getElementById('redoc-container'));
72
+ </script>
73
+ </body>
74
+ </html>`;
75
+ }
76
+ /**
77
+ * Creates a turnkey SvelteKit RequestHandler that generates an interactive OpenAPI 3.1 documentation
78
+ * page (Scalar, Swagger UI, or Redoc) or returns raw OpenAPI 3.1 JSON when ?format=json is requested.
79
+ */
80
+ export function createApiDocsHandler(options = {}) {
81
+ const theme = options.theme || 'scalar';
82
+ return async (event) => {
83
+ const { url, request } = event;
84
+ const format = url.searchParams.get('format');
85
+ const acceptHeader = request.headers.get('accept') || '';
86
+ const spec = generateOpenApiSpec(options);
87
+ // If caller requests JSON via query param, accept header, or path ending in .json
88
+ if (format === 'json' ||
89
+ acceptHeader.includes('application/json') ||
90
+ url.pathname.endsWith('/openapi.json')) {
91
+ return Response.json(spec, {
92
+ headers: {
93
+ 'content-type': 'application/json; charset=utf-8',
94
+ 'cache-control': 'public, max-age=60'
95
+ }
96
+ });
97
+ }
98
+ // Render Interactive HTML Docs
99
+ const specJson = JSON.stringify(spec);
100
+ let html;
101
+ if (theme === 'swagger') {
102
+ html = renderSwaggerHtml(specJson, spec.info.title);
103
+ }
104
+ else if (theme === 'redoc') {
105
+ html = renderRedocHtml(specJson, spec.info.title);
106
+ }
107
+ else {
108
+ html = renderScalarHtml(specJson, spec.info.title);
109
+ }
110
+ return new Response(html, {
111
+ headers: {
112
+ 'content-type': 'text/html; charset=utf-8',
113
+ 'cache-control': 'public, max-age=300'
114
+ }
115
+ });
116
+ };
117
+ }
@@ -0,0 +1,5 @@
1
+ export { generateOpenApiSpec } from './generator';
2
+ export { createApiDocsHandler } from './handler';
3
+ export { ApiRegistry, createApiRegistry, globalApiRegistry } from './registry';
4
+ export { convertToJsonSchema } from './schema';
5
+ export type { OpenApiSpec31, OpenApiOperation, OpenApiParameter, OpenApiRequestBody, OpenApiResponse, GenerateOpenApiOptions, ApiDocsOptions, ApiDocsTheme, EndpointLike, EndpointMap } from './types';
@@ -0,0 +1,4 @@
1
+ export { generateOpenApiSpec } from './generator';
2
+ export { createApiDocsHandler } from './handler';
3
+ export { ApiRegistry, createApiRegistry, globalApiRegistry } from './registry';
4
+ export { convertToJsonSchema } from './schema';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,219 @@
1
+ import { describe, it, expect, beforeEach } from 'vitest';
2
+ import { z } from 'zod';
3
+ import { createMockRequestEvent } from '../../testing/index.js';
4
+ import { generateOpenApiSpec, createApiDocsHandler, createApiRegistry, globalApiRegistry, convertToJsonSchema } from './index.js';
5
+ import { yaxaEndpoint } from '../endpoint/index.js';
6
+ import { requireAuth, requireRole, rateLimit } from '../endpoint/guards.js';
7
+ describe('OpenAPI 3.1 Schema Engine', () => {
8
+ it('converts Zod schema into compliant JSON Schema', () => {
9
+ const schema = z.object({
10
+ title: z.string().min(3),
11
+ count: z.number().optional(),
12
+ role: z.enum(['admin', 'member'])
13
+ });
14
+ const jsonSchema = convertToJsonSchema(schema);
15
+ expect(jsonSchema.type).toBe('object');
16
+ expect(jsonSchema.properties.title.type).toBe('string');
17
+ expect(jsonSchema.properties.count.type).toBe('number');
18
+ expect(jsonSchema.required).toContain('title');
19
+ expect(jsonSchema.required).toContain('role');
20
+ expect(jsonSchema.required).not.toContain('count');
21
+ });
22
+ });
23
+ describe('API Route Registry', () => {
24
+ let registry;
25
+ beforeEach(() => {
26
+ registry = createApiRegistry();
27
+ globalApiRegistry.clear();
28
+ });
29
+ it('normalizes SvelteKit bracket path params to OpenAPI curly braces', () => {
30
+ expect(registry.normalizePath('/api/items/[id]')).toBe('/api/items/{id}');
31
+ expect(registry.normalizePath('/api/orgs/[orgSlug]/users/[userId]')).toBe('/api/orgs/{orgSlug}/users/{userId}');
32
+ expect(registry.normalizePath('/api/files/[...rest]')).toBe('/api/files/{rest}');
33
+ });
34
+ it('registers endpoints and retrieves them in normalized form', () => {
35
+ const getHandler = yaxaEndpoint({ handle: () => [] });
36
+ registry.register('/api/users/[id]', { GET: getHandler });
37
+ const endpoints = registry.getEndpoints();
38
+ expect(endpoints['/api/users/{id}']).toBeDefined();
39
+ expect(endpoints['/api/users/{id}']['GET']).toBe(getHandler);
40
+ });
41
+ });
42
+ describe('generateOpenApiSpec Engine', () => {
43
+ const ItemParamsSchema = z.object({
44
+ id: z.string()
45
+ });
46
+ const ItemQuerySchema = z.object({
47
+ filter: z.string().optional(),
48
+ limit: z.number().optional()
49
+ });
50
+ const CreateItemBodySchema = z.object({
51
+ name: z.string().min(2),
52
+ price: z.number().positive()
53
+ });
54
+ it('generates complete OpenAPI 3.1 document with parameters, body and tags', () => {
55
+ const registry = createApiRegistry();
56
+ const getEndpoint = yaxaEndpoint({
57
+ summary: 'Get Item By ID',
58
+ description: 'Retrieves an item record by its unique ID',
59
+ tags: ['Items'],
60
+ schema: {
61
+ params: ItemParamsSchema,
62
+ query: ItemQuerySchema
63
+ },
64
+ handle: ({ params }) => ({ id: params.id })
65
+ });
66
+ const postEndpoint = yaxaEndpoint({
67
+ summary: 'Create Item',
68
+ tags: ['Items'],
69
+ schema: {
70
+ body: CreateItemBodySchema
71
+ },
72
+ handle: ({ body }) => body
73
+ });
74
+ registry.register('/api/items/[id]', { GET: getEndpoint });
75
+ registry.register('/api/items', { POST: postEndpoint });
76
+ const spec = generateOpenApiSpec({
77
+ title: 'Inventory API',
78
+ version: '2.0.0',
79
+ description: 'Test Inventory System',
80
+ registry
81
+ });
82
+ expect(spec.openapi).toBe('3.1.0');
83
+ expect(spec.info.title).toBe('Inventory API');
84
+ expect(spec.info.version).toBe('2.0.0');
85
+ // Verify GET /api/items/{id}
86
+ const getOp = spec.paths['/api/items/{id}']['get'];
87
+ expect(getOp.summary).toBe('Get Item By ID');
88
+ expect(getOp.tags).toEqual(['Items']);
89
+ expect(getOp.parameters).toHaveLength(3); // id (path), filter (query), limit (query)
90
+ const idParam = getOp.parameters?.find((p) => p.name === 'id');
91
+ expect(idParam?.in).toBe('path');
92
+ expect(idParam?.required).toBe(true);
93
+ // Verify POST /api/items
94
+ const postOp = spec.paths['/api/items']['post'];
95
+ expect(postOp.summary).toBe('Create Item');
96
+ expect(postOp.requestBody).toBeDefined();
97
+ expect(postOp.requestBody?.content['application/json'].schema?.type).toBe('object');
98
+ expect(postOp.responses['201']).toBeDefined();
99
+ expect(postOp.responses['422']).toBeDefined(); // Schema validation failed
100
+ });
101
+ it('deduces security schemes and RFC 7807 responses from guards automatically', () => {
102
+ const registry = createApiRegistry();
103
+ const secureEndpoint = yaxaEndpoint({
104
+ guards: [
105
+ requireAuth(),
106
+ requireRole(['admin', 'billing_manager']),
107
+ rateLimit({ points: 15, windowSeconds: 60 })
108
+ ],
109
+ schema: {
110
+ body: CreateItemBodySchema
111
+ },
112
+ handle: () => ({ ok: true })
113
+ });
114
+ registry.register('/api/secure-action', { POST: secureEndpoint });
115
+ const spec = generateOpenApiSpec({ registry });
116
+ const op = spec.paths['/api/secure-action']['post'];
117
+ // Security schemes attached
118
+ expect(spec.components?.securitySchemes?.BearerAuth).toBeDefined();
119
+ expect(spec.components?.securitySchemes?.CookieAuth).toBeDefined();
120
+ expect(op.security).toBeDefined();
121
+ // Guard error responses generated
122
+ expect(op.responses['401']).toBeDefined();
123
+ expect(op.responses['403']).toBeDefined();
124
+ expect(op.responses['403'].description).toContain('admin, billing_manager');
125
+ expect(op.responses['422']).toBeDefined();
126
+ expect(op.responses['429']).toBeDefined();
127
+ expect(op.responses['429'].headers?.['Retry-After']).toBeDefined();
128
+ expect(op.responses['500']).toBeDefined();
129
+ // Components schema ProblemDetails registered
130
+ expect(spec.components?.schemas?.ProblemDetails).toBeDefined();
131
+ });
132
+ it('supports self-registration via yaxaEndpoint path and method metadata', () => {
133
+ globalApiRegistry.clear();
134
+ yaxaEndpoint({
135
+ path: '/api/v1/auto-registered',
136
+ method: 'GET',
137
+ summary: 'Auto Registered Route',
138
+ handle: () => 'ok'
139
+ });
140
+ const spec = generateOpenApiSpec();
141
+ expect(spec.paths['/api/v1/auto-registered']?.['get']?.summary).toBe('Auto Registered Route');
142
+ });
143
+ });
144
+ describe('createApiDocsHandler Endpoint', () => {
145
+ it('serves OpenAPI 3.1 JSON when format=json query parameter is present', async () => {
146
+ const handler = createApiDocsHandler({
147
+ title: 'Store API',
148
+ version: '1.2.3'
149
+ });
150
+ const event = createMockRequestEvent({
151
+ url: 'http://localhost:5173/api/docs?format=json'
152
+ });
153
+ const response = await handler(event);
154
+ expect(response.status).toBe(200);
155
+ expect(response.headers.get('content-type')).toContain('application/json');
156
+ const json = await response.json();
157
+ expect(json.openapi).toBe('3.1.0');
158
+ expect(json.info.title).toBe('Store API');
159
+ expect(json.info.version).toBe('1.2.3');
160
+ });
161
+ it('serves OpenAPI 3.1 JSON when Accept header requests application/json', async () => {
162
+ const handler = createApiDocsHandler();
163
+ const event = createMockRequestEvent({
164
+ url: 'http://localhost:5173/api/docs',
165
+ headers: { accept: 'application/json' }
166
+ });
167
+ const response = await handler(event);
168
+ expect(response.status).toBe(200);
169
+ expect(response.headers.get('content-type')).toContain('application/json');
170
+ });
171
+ it('renders Scalar HTML documentation by default', async () => {
172
+ const handler = createApiDocsHandler({
173
+ title: 'Scalar Docs Test',
174
+ theme: 'scalar'
175
+ });
176
+ const event = createMockRequestEvent({
177
+ url: 'http://localhost:5173/api/docs'
178
+ });
179
+ const response = await handler(event);
180
+ expect(response.status).toBe(200);
181
+ expect(response.headers.get('content-type')).toContain('text/html');
182
+ const html = await response.text();
183
+ expect(html).toContain('<title>Scalar Docs Test</title>');
184
+ expect(html).toContain('@scalar/api-reference');
185
+ expect(html).toContain('id="api-reference"');
186
+ });
187
+ it('renders Swagger UI HTML when theme is swagger', async () => {
188
+ const handler = createApiDocsHandler({
189
+ title: 'Swagger Docs Test',
190
+ theme: 'swagger'
191
+ });
192
+ const event = createMockRequestEvent({
193
+ url: 'http://localhost:5173/api/docs'
194
+ });
195
+ const response = await handler(event);
196
+ expect(response.status).toBe(200);
197
+ expect(response.headers.get('content-type')).toContain('text/html');
198
+ const html = await response.text();
199
+ expect(html).toContain('<title>Swagger Docs Test</title>');
200
+ expect(html).toContain('swagger-ui-dist');
201
+ expect(html).toContain('SwaggerUIBundle');
202
+ });
203
+ it('renders Redoc HTML when theme is redoc', async () => {
204
+ const handler = createApiDocsHandler({
205
+ title: 'Redoc Docs Test',
206
+ theme: 'redoc'
207
+ });
208
+ const event = createMockRequestEvent({
209
+ url: 'http://localhost:5173/api/docs'
210
+ });
211
+ const response = await handler(event);
212
+ expect(response.status).toBe(200);
213
+ expect(response.headers.get('content-type')).toContain('text/html');
214
+ const html = await response.text();
215
+ expect(html).toContain('<title>Redoc Docs Test</title>');
216
+ expect(html).toContain('redoc.standalone.js');
217
+ expect(html).toContain('redoc-container');
218
+ });
219
+ });
@@ -0,0 +1,35 @@
1
+ import type { EndpointLike, EndpointMap } from './types';
2
+ /**
3
+ * Route & Endpoint Registry for OpenAPI discovery and introspection.
4
+ */
5
+ export declare class ApiRegistry {
6
+ private endpoints;
7
+ /**
8
+ * Registers endpoints for a given path.
9
+ * @param path SvelteKit route path (e.g. '/api/projects' or '/api/projects/[id]')
10
+ * @param methods Map of HTTP methods to handlers or yaxaEndpoint configs
11
+ */
12
+ register(path: string, methods: Record<string, EndpointLike>): this;
13
+ /**
14
+ * Retrieves all registered endpoints.
15
+ */
16
+ getEndpoints(): EndpointMap;
17
+ /**
18
+ * Clears registered endpoints (useful in testing).
19
+ */
20
+ clear(): void;
21
+ /**
22
+ * Normalizes SvelteKit path parameters to OpenAPI format:
23
+ * '/api/projects/[id]' -> '/api/projects/{id}'
24
+ * '/api/teams/[orgSlug]/members/[userId]' -> '/api/teams/{orgSlug}/members/{userId}'
25
+ */
26
+ normalizePath(path: string): string;
27
+ }
28
+ /**
29
+ * Global singleton API registry for zero-config route registration.
30
+ */
31
+ export declare const globalApiRegistry: ApiRegistry;
32
+ /**
33
+ * Creates a new isolated API registry instance.
34
+ */
35
+ export declare function createApiRegistry(): ApiRegistry;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Route & Endpoint Registry for OpenAPI discovery and introspection.
3
+ */
4
+ export class ApiRegistry {
5
+ endpoints = {};
6
+ /**
7
+ * Registers endpoints for a given path.
8
+ * @param path SvelteKit route path (e.g. '/api/projects' or '/api/projects/[id]')
9
+ * @param methods Map of HTTP methods to handlers or yaxaEndpoint configs
10
+ */
11
+ register(path, methods) {
12
+ const normalizedPath = this.normalizePath(path);
13
+ if (!this.endpoints[normalizedPath]) {
14
+ this.endpoints[normalizedPath] = {};
15
+ }
16
+ for (const [method, handler] of Object.entries(methods)) {
17
+ this.endpoints[normalizedPath][method.toUpperCase()] = handler;
18
+ }
19
+ return this;
20
+ }
21
+ /**
22
+ * Retrieves all registered endpoints.
23
+ */
24
+ getEndpoints() {
25
+ return this.endpoints;
26
+ }
27
+ /**
28
+ * Clears registered endpoints (useful in testing).
29
+ */
30
+ clear() {
31
+ this.endpoints = {};
32
+ }
33
+ /**
34
+ * Normalizes SvelteKit path parameters to OpenAPI format:
35
+ * '/api/projects/[id]' -> '/api/projects/{id}'
36
+ * '/api/teams/[orgSlug]/members/[userId]' -> '/api/teams/{orgSlug}/members/{userId}'
37
+ */
38
+ normalizePath(path) {
39
+ return path.replace(/\[\.\.\.(\w+)\]/g, '{$1}').replace(/\[(\w+)\]/g, '{$1}');
40
+ }
41
+ }
42
+ /**
43
+ * Global singleton API registry for zero-config route registration.
44
+ */
45
+ export const globalApiRegistry = new ApiRegistry();
46
+ /**
47
+ * Creates a new isolated API registry instance.
48
+ */
49
+ export function createApiRegistry() {
50
+ return new ApiRegistry();
51
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Converts a Zod or Standard Schema validator into a compliant OpenAPI 3.1 JSON Schema.
3
+ */
4
+ export declare function convertToJsonSchema(validator: any): Record<string, any>;
@@ -0,0 +1,59 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Converts a Zod or Standard Schema validator into a compliant OpenAPI 3.1 JSON Schema.
4
+ */
5
+ export function convertToJsonSchema(validator) {
6
+ if (!validator) {
7
+ return { type: 'object' };
8
+ }
9
+ // 1. Zod native JSON schema converter
10
+ if (typeof z?.toJSONSchema === 'function') {
11
+ try {
12
+ const jsonSchema = z.toJSONSchema(validator);
13
+ if (jsonSchema && typeof jsonSchema === 'object') {
14
+ const cleanSchema = { ...jsonSchema };
15
+ delete cleanSchema.$schema;
16
+ return cleanSchema;
17
+ }
18
+ }
19
+ catch {
20
+ // Fall through to other strategies
21
+ }
22
+ }
23
+ // 2. Check if validator has built-in jsonSchema method/property
24
+ if (typeof validator.jsonSchema === 'function') {
25
+ try {
26
+ const res = validator.jsonSchema();
27
+ const cleanSchema = { ...res };
28
+ delete cleanSchema.$schema;
29
+ return cleanSchema;
30
+ }
31
+ catch {
32
+ // Fall through
33
+ }
34
+ }
35
+ if (typeof validator.jsonSchema === 'object' && validator.jsonSchema !== null) {
36
+ const cleanSchema = { ...validator.jsonSchema };
37
+ delete cleanSchema.$schema;
38
+ return cleanSchema;
39
+ }
40
+ // 3. Heuristic for common object schema shapes
41
+ if (typeof validator === 'object' && validator !== null) {
42
+ if ('shape' in validator && typeof validator.shape === 'object') {
43
+ const properties = {};
44
+ const required = [];
45
+ for (const [key, val] of Object.entries(validator.shape)) {
46
+ properties[key] = convertToJsonSchema(val);
47
+ if (!val?.isOptional?.()) {
48
+ required.push(key);
49
+ }
50
+ }
51
+ return {
52
+ type: 'object',
53
+ properties,
54
+ ...(required.length > 0 ? { required } : {})
55
+ };
56
+ }
57
+ }
58
+ return { type: 'string' };
59
+ }
@@ -0,0 +1,127 @@
1
+ import type { RequestHandler } from '@sveltejs/kit';
2
+ import type { YaxaEndpointConfig } from '../endpoint/types';
3
+ /**
4
+ * OpenAPI 3.1 Parameter Object
5
+ */
6
+ export interface OpenApiParameter {
7
+ name: string;
8
+ in: 'query' | 'header' | 'path' | 'cookie';
9
+ description?: string;
10
+ required?: boolean;
11
+ deprecated?: boolean;
12
+ schema?: Record<string, any>;
13
+ example?: any;
14
+ }
15
+ /**
16
+ * OpenAPI 3.1 Request Body Object
17
+ */
18
+ export interface OpenApiRequestBody {
19
+ description?: string;
20
+ required?: boolean;
21
+ content: {
22
+ [mediaType: string]: {
23
+ schema?: Record<string, any>;
24
+ example?: any;
25
+ };
26
+ };
27
+ }
28
+ /**
29
+ * OpenAPI 3.1 Response Object
30
+ */
31
+ export interface OpenApiResponse {
32
+ description: string;
33
+ headers?: Record<string, any>;
34
+ content?: {
35
+ [mediaType: string]: {
36
+ schema?: Record<string, any>;
37
+ example?: any;
38
+ };
39
+ };
40
+ }
41
+ /**
42
+ * OpenAPI 3.1 Operation Object
43
+ */
44
+ export interface OpenApiOperation {
45
+ summary?: string;
46
+ description?: string;
47
+ operationId?: string;
48
+ tags?: string[];
49
+ parameters?: OpenApiParameter[];
50
+ requestBody?: OpenApiRequestBody;
51
+ responses: Record<string, OpenApiResponse>;
52
+ deprecated?: boolean;
53
+ security?: Array<Record<string, string[]>>;
54
+ }
55
+ /**
56
+ * OpenAPI 3.1 Specification Object
57
+ */
58
+ export interface OpenApiSpec31 {
59
+ openapi: '3.1.0';
60
+ info: {
61
+ title: string;
62
+ version: string;
63
+ description?: string;
64
+ termsOfService?: string;
65
+ contact?: {
66
+ name?: string;
67
+ url?: string;
68
+ email?: string;
69
+ };
70
+ license?: {
71
+ name: string;
72
+ url?: string;
73
+ };
74
+ };
75
+ servers?: Array<{
76
+ url: string;
77
+ description?: string;
78
+ }>;
79
+ paths: {
80
+ [path: string]: {
81
+ [method: string]: OpenApiOperation;
82
+ };
83
+ };
84
+ components?: {
85
+ schemas?: Record<string, any>;
86
+ securitySchemes?: Record<string, any>;
87
+ responses?: Record<string, OpenApiResponse>;
88
+ parameters?: Record<string, OpenApiParameter>;
89
+ };
90
+ tags?: Array<{
91
+ name: string;
92
+ description?: string;
93
+ }>;
94
+ }
95
+ export type EndpointLike = (RequestHandler & {
96
+ _yaxaConfig?: YaxaEndpointConfig;
97
+ }) | YaxaEndpointConfig;
98
+ export type EndpointMap = Record<string, Record<string, EndpointLike>>;
99
+ export interface GenerateOpenApiOptions {
100
+ title?: string;
101
+ version?: string;
102
+ description?: string;
103
+ servers?: Array<{
104
+ url: string;
105
+ description?: string;
106
+ }>;
107
+ endpoints?: EndpointMap;
108
+ registry?: any;
109
+ }
110
+ export type ApiDocsTheme = 'scalar' | 'swagger' | 'redoc';
111
+ export interface ApiDocsOptions extends GenerateOpenApiOptions {
112
+ /**
113
+ * Interactive UI theme:
114
+ * - 'scalar' (default): Modern, dark-mode native, high contrast developer reference.
115
+ * - 'swagger': Classic Swagger UI with interactive Try-It-Out console.
116
+ * - 'redoc': Clean 3-panel technical documentation format.
117
+ */
118
+ theme?: ApiDocsTheme;
119
+ /**
120
+ * Mount path of documentation endpoint (default: '/api/docs').
121
+ */
122
+ docsPath?: string;
123
+ /**
124
+ * CDN version/URL overrides if needed.
125
+ */
126
+ cdnUrl?: string;
127
+ }
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yaxa-svelte",
3
- "version": "2.2.0",
3
+ "version": "2.4.0",
4
4
  "description": "The Intuitive Svelte UI Library — Nuxt UI v4 equivalent for SvelteKit 2 & 3 & Svelte 5 with automated SEO, dynamic OpenGraph cards, sitemaps, robots.txt, and Tailwind CSS v4.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://yaxa.vercel.app",