@designofadecade/server 4.0.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 (84) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/LICENSE +21 -0
  3. package/README.md +297 -0
  4. package/dist/client/ApiClient.d.ts +121 -0
  5. package/dist/client/ApiClient.d.ts.map +1 -0
  6. package/dist/client/ApiClient.js +289 -0
  7. package/dist/client/ApiClient.js.map +1 -0
  8. package/dist/context/Context.d.ts +71 -0
  9. package/dist/context/Context.d.ts.map +1 -0
  10. package/dist/context/Context.js +81 -0
  11. package/dist/context/Context.js.map +1 -0
  12. package/dist/docs/OpenApiGenerator.d.ts +135 -0
  13. package/dist/docs/OpenApiGenerator.d.ts.map +1 -0
  14. package/dist/docs/OpenApiGenerator.js +165 -0
  15. package/dist/docs/OpenApiGenerator.js.map +1 -0
  16. package/dist/events/Events.d.ts +52 -0
  17. package/dist/events/Events.d.ts.map +1 -0
  18. package/dist/events/Events.js +70 -0
  19. package/dist/events/Events.js.map +1 -0
  20. package/dist/events/EventsManager.d.ts +46 -0
  21. package/dist/events/EventsManager.d.ts.map +1 -0
  22. package/dist/events/EventsManager.js +137 -0
  23. package/dist/events/EventsManager.js.map +1 -0
  24. package/dist/index.d.ts +32 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +38 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/local/Local.d.ts +83 -0
  29. package/dist/local/Local.d.ts.map +1 -0
  30. package/dist/local/Local.js +114 -0
  31. package/dist/local/Local.js.map +1 -0
  32. package/dist/logger/Logger.d.ts +365 -0
  33. package/dist/logger/Logger.d.ts.map +1 -0
  34. package/dist/logger/Logger.js +582 -0
  35. package/dist/logger/Logger.js.map +1 -0
  36. package/dist/middleware/RequestLogger.d.ts +62 -0
  37. package/dist/middleware/RequestLogger.d.ts.map +1 -0
  38. package/dist/middleware/RequestLogger.js +71 -0
  39. package/dist/middleware/RequestLogger.js.map +1 -0
  40. package/dist/notifications/Slack.d.ts +19 -0
  41. package/dist/notifications/Slack.d.ts.map +1 -0
  42. package/dist/notifications/Slack.js +55 -0
  43. package/dist/notifications/Slack.js.map +1 -0
  44. package/dist/router/RouteError.d.ts +21 -0
  45. package/dist/router/RouteError.d.ts.map +1 -0
  46. package/dist/router/RouteError.js +31 -0
  47. package/dist/router/RouteError.js.map +1 -0
  48. package/dist/router/Router.d.ts +66 -0
  49. package/dist/router/Router.d.ts.map +1 -0
  50. package/dist/router/Router.js +327 -0
  51. package/dist/router/Router.js.map +1 -0
  52. package/dist/router/Routes.d.ts +30 -0
  53. package/dist/router/Routes.d.ts.map +1 -0
  54. package/dist/router/Routes.js +52 -0
  55. package/dist/router/Routes.js.map +1 -0
  56. package/dist/router/StaticFileHandler.d.ts +44 -0
  57. package/dist/router/StaticFileHandler.d.ts.map +1 -0
  58. package/dist/router/StaticFileHandler.js +148 -0
  59. package/dist/router/StaticFileHandler.js.map +1 -0
  60. package/dist/sanitizer/HtmlSanitizer.d.ts +306 -0
  61. package/dist/sanitizer/HtmlSanitizer.d.ts.map +1 -0
  62. package/dist/sanitizer/HtmlSanitizer.js +808 -0
  63. package/dist/sanitizer/HtmlSanitizer.js.map +1 -0
  64. package/dist/server/Server.d.ts +28 -0
  65. package/dist/server/Server.d.ts.map +1 -0
  66. package/dist/server/Server.js +95 -0
  67. package/dist/server/Server.js.map +1 -0
  68. package/dist/state/AppState.d.ts +64 -0
  69. package/dist/state/AppState.d.ts.map +1 -0
  70. package/dist/state/AppState.js +89 -0
  71. package/dist/state/AppState.js.map +1 -0
  72. package/dist/utils/HtmlRenderer.d.ts +6 -0
  73. package/dist/utils/HtmlRenderer.d.ts.map +1 -0
  74. package/dist/utils/HtmlRenderer.js +128 -0
  75. package/dist/utils/HtmlRenderer.js.map +1 -0
  76. package/dist/websocket/WebSocketMessageFormatter.d.ts +40 -0
  77. package/dist/websocket/WebSocketMessageFormatter.d.ts.map +1 -0
  78. package/dist/websocket/WebSocketMessageFormatter.js +99 -0
  79. package/dist/websocket/WebSocketMessageFormatter.js.map +1 -0
  80. package/dist/websocket/WebSocketServer.d.ts +14 -0
  81. package/dist/websocket/WebSocketServer.d.ts.map +1 -0
  82. package/dist/websocket/WebSocketServer.js +138 -0
  83. package/dist/websocket/WebSocketServer.js.map +1 -0
  84. package/package.json +97 -0
@@ -0,0 +1,289 @@
1
+ /**
2
+ * API Client for making HTTP requests
3
+ * @class ApiClient
4
+ * @example
5
+ * const client = new ApiClient('https://api.example.com');
6
+ * client.setAuthToken('your-token');
7
+ * const result = await client.get('/users', { page: 1, limit: 10 });
8
+ */
9
+ export default class ApiClient {
10
+ #baseUrl = '';
11
+ #authToken = null;
12
+ #authType = 'Bearer';
13
+ #defaultHeaders = {};
14
+ #timeout = 30000; // 30 seconds default
15
+ #requestInterceptors = [];
16
+ #responseInterceptors = [];
17
+ #retryAttempts = 0;
18
+ #retryDelay = 1000;
19
+ /**
20
+ * Create an API Client
21
+ * @param {string} baseUrl - Base URL for all requests
22
+ * @param {Object} options - Configuration options
23
+ * @param {number} options.timeout - Request timeout in milliseconds (default: 30000)
24
+ * @param {number} options.retryAttempts - Number of retry attempts for failed requests (default: 0)
25
+ * @param {number} options.retryDelay - Delay between retries in milliseconds (default: 1000)
26
+ */
27
+ constructor(baseUrl, options = {}) {
28
+ this.#baseUrl = baseUrl;
29
+ this.#timeout = options.timeout || 30000;
30
+ this.#retryAttempts = options.retryAttempts || 0;
31
+ this.#retryDelay = options.retryDelay || 1000;
32
+ }
33
+ /**
34
+ * Set authentication token
35
+ * @param {string} token - Authentication token
36
+ * @param {string} type - Token type (default: 'Bearer')
37
+ */
38
+ setAuthToken(token, type = 'Bearer') {
39
+ this.#authToken = token;
40
+ this.#authType = type;
41
+ }
42
+ /**
43
+ * Clear authentication token
44
+ */
45
+ clearAuthToken() {
46
+ this.#authToken = null;
47
+ }
48
+ /**
49
+ * Set default headers for all requests
50
+ * @param {Object} headers - Headers object
51
+ */
52
+ setDefaultHeaders(headers) {
53
+ this.#defaultHeaders = { ...headers };
54
+ }
55
+ /**
56
+ * Add a request interceptor
57
+ * @param {Function} interceptor - Function that receives and modifies request config
58
+ */
59
+ addRequestInterceptor(interceptor) {
60
+ this.#requestInterceptors.push(interceptor);
61
+ }
62
+ /**
63
+ * Add a response interceptor
64
+ * @param {Function} interceptor - Function that receives and modifies response
65
+ */
66
+ addResponseInterceptor(interceptor) {
67
+ this.#responseInterceptors.push(interceptor);
68
+ }
69
+ /**
70
+ * Build query string from params object
71
+ * @param {Object} params - Query parameters
72
+ * @returns {string} Query string
73
+ */
74
+ #buildQueryString(params) {
75
+ if (!params || Object.keys(params).length === 0)
76
+ return '';
77
+ const queryString = new URLSearchParams(params).toString();
78
+ return `?${queryString}`;
79
+ }
80
+ /**
81
+ * Get headers for request
82
+ * @param {Object} customHeaders - Custom headers for this request
83
+ * @returns {Object} Combined headers
84
+ */
85
+ #getHeaders(customHeaders = {}) {
86
+ const headers = {
87
+ 'Content-Type': 'application/json',
88
+ 'Accept': 'application/json',
89
+ ...this.#defaultHeaders,
90
+ ...customHeaders
91
+ };
92
+ if (this.#authToken) {
93
+ headers['Authorization'] = `${this.#authType} ${this.#authToken}`;
94
+ }
95
+ return headers;
96
+ }
97
+ /**
98
+ * Execute request with timeout and retry logic
99
+ * @param {Function} fetchFn - Function that performs the fetch
100
+ * @param {AbortController} controller - Abort controller for timeout
101
+ * @param {number} attempt - Current attempt number
102
+ * @returns {Promise<Response>}
103
+ */
104
+ async #executeWithRetry(fetchFn, controller, attempt = 0) {
105
+ let timeoutId;
106
+ try {
107
+ timeoutId = setTimeout(() => controller.abort(), this.#timeout);
108
+ const response = await fetchFn();
109
+ return response;
110
+ }
111
+ catch (error) {
112
+ if (attempt < this.#retryAttempts && error.name !== 'AbortError') {
113
+ await new Promise(resolve => setTimeout(resolve, this.#retryDelay));
114
+ return this.#executeWithRetry(fetchFn, controller, attempt + 1);
115
+ }
116
+ throw error;
117
+ }
118
+ finally {
119
+ if (timeoutId) {
120
+ clearTimeout(timeoutId);
121
+ }
122
+ }
123
+ }
124
+ /**
125
+ * Process response through interceptors
126
+ * @param {Object} response - Response object
127
+ * @returns {Promise<Object>} Processed response
128
+ */
129
+ async #processResponse(response) {
130
+ let processedResponse = response;
131
+ for (const interceptor of this.#responseInterceptors) {
132
+ processedResponse = await interceptor(processedResponse);
133
+ }
134
+ return processedResponse;
135
+ }
136
+ /**
137
+ * Make HTTP request
138
+ * @param {string} url - Request URL
139
+ * @param {Object} config - Request configuration
140
+ * @returns {Promise<Object>} Response object
141
+ */
142
+ async #request(url, config) {
143
+ const controller = new AbortController();
144
+ try {
145
+ // Apply request interceptors
146
+ let requestConfig = { ...config, signal: controller.signal };
147
+ for (const interceptor of this.#requestInterceptors) {
148
+ requestConfig = await interceptor(requestConfig);
149
+ }
150
+ const fetchFn = () => fetch(`${this.#baseUrl}${url}`, requestConfig);
151
+ const response = await this.#executeWithRetry(fetchFn, controller);
152
+ let responseData = null;
153
+ const contentType = response.headers.get('content-type');
154
+ if (contentType && contentType.includes('application/json')) {
155
+ try {
156
+ responseData = await response.json();
157
+ }
158
+ catch (e) {
159
+ // Failed to parse JSON
160
+ }
161
+ }
162
+ else if (contentType && contentType.includes('text/')) {
163
+ try {
164
+ responseData = await response.text();
165
+ }
166
+ catch (e) {
167
+ // Failed to parse text
168
+ }
169
+ }
170
+ const result = {
171
+ ok: response.ok,
172
+ status: response.status,
173
+ statusText: response.statusText,
174
+ data: responseData,
175
+ error: !response.ok ? response.statusText : null,
176
+ headers: Object.fromEntries(response.headers.entries())
177
+ };
178
+ return await this.#processResponse(result);
179
+ }
180
+ catch (error) {
181
+ const errorResponse = {
182
+ ok: false,
183
+ status: null,
184
+ statusText: error.name === 'AbortError' ? 'Request Timeout' : 'Network Error',
185
+ data: null,
186
+ error: error.name === 'AbortError' ? 'Request timed out' : error.message,
187
+ headers: {}
188
+ };
189
+ return await this.#processResponse(errorResponse);
190
+ }
191
+ }
192
+ /**
193
+ * Make GET request
194
+ * @param {string} url - Request URL
195
+ * @param {Object} params - Query parameters (optional)
196
+ * @param {Object} options - Request options
197
+ * @param {Object} options.headers - Custom headers for this request
198
+ * @param {AbortSignal} options.signal - Abort signal for cancellation
199
+ * @returns {Promise<Object>} Response object
200
+ */
201
+ async get(url, params = null, options = {}) {
202
+ const queryString = params ? this.#buildQueryString(params) : '';
203
+ return this.#request(`${url}${queryString}`, {
204
+ method: 'GET',
205
+ headers: this.#getHeaders(options.headers),
206
+ signal: options.signal
207
+ });
208
+ }
209
+ /**
210
+ * Make POST request
211
+ * @param {string} url - Request URL
212
+ * @param {Object|FormData} data - Request body
213
+ * @param {Object} options - Request options
214
+ * @param {Object} options.headers - Custom headers for this request
215
+ * @param {AbortSignal} options.signal - Abort signal for cancellation
216
+ * @returns {Promise<Object>} Response object
217
+ */
218
+ async post(url, data, options = {}) {
219
+ const isFormData = data instanceof FormData;
220
+ const headers = this.#getHeaders(options.headers);
221
+ // Remove Content-Type for FormData (browser sets it with boundary)
222
+ if (isFormData) {
223
+ delete headers['Content-Type'];
224
+ }
225
+ return this.#request(url, {
226
+ method: 'POST',
227
+ headers: headers,
228
+ body: isFormData ? data : JSON.stringify(data),
229
+ signal: options.signal
230
+ });
231
+ }
232
+ /**
233
+ * Make PUT request
234
+ * @param {string} url - Request URL
235
+ * @param {Object|FormData} data - Request body
236
+ * @param {Object} options - Request options
237
+ * @param {Object} options.headers - Custom headers for this request
238
+ * @param {AbortSignal} options.signal - Abort signal for cancellation
239
+ * @returns {Promise<Object>} Response object
240
+ */
241
+ async put(url, data, options = {}) {
242
+ const isFormData = data instanceof FormData;
243
+ const headers = this.#getHeaders(options.headers);
244
+ // Remove Content-Type for FormData (browser sets it with boundary)
245
+ if (isFormData) {
246
+ delete headers['Content-Type'];
247
+ }
248
+ return this.#request(url, {
249
+ method: 'PUT',
250
+ headers: headers,
251
+ body: isFormData ? data : JSON.stringify(data),
252
+ signal: options.signal
253
+ });
254
+ }
255
+ /**
256
+ * Make DELETE request
257
+ * @param {string} url - Request URL
258
+ * @param {Object} options - Request options
259
+ * @param {Object} options.headers - Custom headers for this request
260
+ * @param {AbortSignal} options.signal - Abort signal for cancellation
261
+ * @returns {Promise<Object>} Response object
262
+ */
263
+ async delete(url, options = {}) {
264
+ const config = {
265
+ method: 'DELETE',
266
+ headers: this.#getHeaders(options.headers),
267
+ signal: options.signal
268
+ };
269
+ return this.#request(url, config);
270
+ }
271
+ /**
272
+ * Make PATCH request
273
+ * @param {string} url - Request URL
274
+ * @param {Object} data - Request body
275
+ * @param {Object} options - Request options
276
+ * @param {Object} options.headers - Custom headers for this request
277
+ * @param {AbortSignal} options.signal - Abort signal for cancellation
278
+ * @returns {Promise<Object>} Response object
279
+ */
280
+ async patch(url, data, options = {}) {
281
+ return this.#request(url, {
282
+ method: 'PATCH',
283
+ headers: this.#getHeaders(options.headers),
284
+ body: JSON.stringify(data),
285
+ signal: options.signal
286
+ });
287
+ }
288
+ }
289
+ //# sourceMappingURL=ApiClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApiClient.js","sourceRoot":"","sources":["../../src/client/ApiClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Abstract Context class for application context management
3
+ *
4
+ * This abstract class must be extended to provide type-safe context
5
+ * throughout the application. It enforces a pattern where context
6
+ * structure is explicitly defined through extension.
7
+ *
8
+ * @abstract
9
+ * @class Context
10
+ *
11
+ * @example
12
+ * // Define your application context
13
+ * class AppContext extends Context {
14
+ * constructor(
15
+ * public database: DatabaseConnection,
16
+ * public config: AppConfig,
17
+ * public services: Services
18
+ * ) {
19
+ * super();
20
+ * }
21
+ * }
22
+ *
23
+ * // Use in router initialization
24
+ * const context = new AppContext(db, config, services);
25
+ * const router = new Router({
26
+ * context,
27
+ * initRoutes: [UserRoutes, PostRoutes]
28
+ * });
29
+ *
30
+ * @example
31
+ * // Access context in route handlers
32
+ * class UserRoutes extends Routes {
33
+ * constructor(router: Router, context?: AppContext) {
34
+ * super(router, context);
35
+ *
36
+ * this.addRoute('/users', 'GET', async () => {
37
+ * const users = await (this.context as AppContext).database.getUsers();
38
+ * return { status: 200, body: users };
39
+ * });
40
+ * }
41
+ * }
42
+ */
43
+ export default abstract class Context {
44
+ /**
45
+ * Protected constructor ensures this class cannot be instantiated directly
46
+ * and must be extended by a concrete implementation
47
+ */
48
+ protected constructor();
49
+ /**
50
+ * Optional method to validate context state
51
+ * Override in derived classes to implement custom validation
52
+ *
53
+ * @returns {boolean} True if context is valid
54
+ */
55
+ protected validate(): boolean;
56
+ /**
57
+ * Optional method to initialize context
58
+ * Override in derived classes to implement custom initialization logic
59
+ *
60
+ * @returns {Promise<void>}
61
+ */
62
+ protected initialize(): Promise<void>;
63
+ /**
64
+ * Optional method to cleanup context resources
65
+ * Override in derived classes to implement custom cleanup logic
66
+ *
67
+ * @returns {Promise<void>}
68
+ */
69
+ protected dispose(): Promise<void>;
70
+ }
71
+ //# sourceMappingURL=Context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Context.d.ts","sourceRoot":"","sources":["../../src/context/Context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,MAAM,CAAC,OAAO,CAAC,QAAQ,OAAO,OAAO;IACnC;;;OAGG;IACH,SAAS;IAMT;;;;;OAKG;IACH,SAAS,CAAC,QAAQ,IAAI,OAAO;IAI7B;;;;;OAKG;cACa,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3C;;;;;OAKG;cACa,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAGzC"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Abstract Context class for application context management
3
+ *
4
+ * This abstract class must be extended to provide type-safe context
5
+ * throughout the application. It enforces a pattern where context
6
+ * structure is explicitly defined through extension.
7
+ *
8
+ * @abstract
9
+ * @class Context
10
+ *
11
+ * @example
12
+ * // Define your application context
13
+ * class AppContext extends Context {
14
+ * constructor(
15
+ * public database: DatabaseConnection,
16
+ * public config: AppConfig,
17
+ * public services: Services
18
+ * ) {
19
+ * super();
20
+ * }
21
+ * }
22
+ *
23
+ * // Use in router initialization
24
+ * const context = new AppContext(db, config, services);
25
+ * const router = new Router({
26
+ * context,
27
+ * initRoutes: [UserRoutes, PostRoutes]
28
+ * });
29
+ *
30
+ * @example
31
+ * // Access context in route handlers
32
+ * class UserRoutes extends Routes {
33
+ * constructor(router: Router, context?: AppContext) {
34
+ * super(router, context);
35
+ *
36
+ * this.addRoute('/users', 'GET', async () => {
37
+ * const users = await (this.context as AppContext).database.getUsers();
38
+ * return { status: 200, body: users };
39
+ * });
40
+ * }
41
+ * }
42
+ */
43
+ export default class Context {
44
+ /**
45
+ * Protected constructor ensures this class cannot be instantiated directly
46
+ * and must be extended by a concrete implementation
47
+ */
48
+ constructor() {
49
+ if (new.target === Context) {
50
+ throw new TypeError('Cannot construct Context instances directly. Context must be extended.');
51
+ }
52
+ }
53
+ /**
54
+ * Optional method to validate context state
55
+ * Override in derived classes to implement custom validation
56
+ *
57
+ * @returns {boolean} True if context is valid
58
+ */
59
+ validate() {
60
+ return true;
61
+ }
62
+ /**
63
+ * Optional method to initialize context
64
+ * Override in derived classes to implement custom initialization logic
65
+ *
66
+ * @returns {Promise<void>}
67
+ */
68
+ async initialize() {
69
+ // Override in derived classes
70
+ }
71
+ /**
72
+ * Optional method to cleanup context resources
73
+ * Override in derived classes to implement custom cleanup logic
74
+ *
75
+ * @returns {Promise<void>}
76
+ */
77
+ async dispose() {
78
+ // Override in derived classes
79
+ }
80
+ }
81
+ //# sourceMappingURL=Context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Context.js","sourceRoot":"","sources":["../../src/context/Context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,MAAM,CAAC,OAAO,OAAgB,OAAO;IACnC;;;OAGG;IACH;QACE,IAAI,GAAG,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;YAC3B,MAAM,IAAI,SAAS,CAAC,wEAAwE,CAAC,CAAC;QAChG,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACO,QAAQ;QAChB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;OAKG;IACO,KAAK,CAAC,UAAU;QACxB,8BAA8B;IAChC,CAAC;IAED;;;;;OAKG;IACO,KAAK,CAAC,OAAO;QACrB,8BAA8B;IAChC,CAAC;CACF"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * OpenAPI/Swagger Documentation Generator
3
+ *
4
+ * This utility helps generate OpenAPI 3.0 documentation for your API routes.
5
+ *
6
+ * Installation:
7
+ * ```bash
8
+ * npm install --save-dev swagger-jsdoc swagger-ui-dist
9
+ * ```
10
+ *
11
+ * Usage:
12
+ * ```typescript
13
+ * import { OpenApiGenerator } from '@designofadecade/server';
14
+ *
15
+ * const generator = new OpenApiGenerator({
16
+ * title: 'My API',
17
+ * version: '1.0.0',
18
+ * description: 'My API description'
19
+ * });
20
+ *
21
+ * // Add route documentation
22
+ * generator.addRoute({
23
+ * path: '/api/users',
24
+ * method: 'GET',
25
+ * summary: 'Get all users',
26
+ * responses: {
27
+ * 200: { description: 'Success', schema: { type: 'array' } }
28
+ * }
29
+ * });
30
+ *
31
+ * // Generate OpenAPI spec
32
+ * const spec = generator.generate();
33
+ * ```
34
+ */
35
+ export interface OpenApiInfo {
36
+ title: string;
37
+ version: string;
38
+ description?: string;
39
+ contact?: {
40
+ name?: string;
41
+ email?: string;
42
+ url?: string;
43
+ };
44
+ license?: {
45
+ name: string;
46
+ url?: string;
47
+ };
48
+ }
49
+ export interface OpenApiServer {
50
+ url: string;
51
+ description?: string;
52
+ }
53
+ export interface OpenApiParameter {
54
+ name: string;
55
+ in: 'path' | 'query' | 'header' | 'cookie';
56
+ description?: string;
57
+ required?: boolean;
58
+ schema: {
59
+ type: string;
60
+ [key: string]: unknown;
61
+ };
62
+ }
63
+ export interface OpenApiResponse {
64
+ description: string;
65
+ content?: {
66
+ [mediaType: string]: {
67
+ schema: unknown;
68
+ };
69
+ };
70
+ }
71
+ export interface OpenApiRouteConfig {
72
+ path: string;
73
+ method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
74
+ summary?: string;
75
+ description?: string;
76
+ operationId?: string;
77
+ tags?: string[];
78
+ parameters?: OpenApiParameter[];
79
+ requestBody?: {
80
+ description?: string;
81
+ required?: boolean;
82
+ content: {
83
+ [mediaType: string]: {
84
+ schema: unknown;
85
+ };
86
+ };
87
+ };
88
+ responses: {
89
+ [statusCode: string]: OpenApiResponse;
90
+ };
91
+ security?: Array<Record<string, string[]>>;
92
+ }
93
+ export interface OpenApiConfig {
94
+ info: OpenApiInfo;
95
+ servers?: OpenApiServer[];
96
+ tags?: Array<{
97
+ name: string;
98
+ description?: string;
99
+ }>;
100
+ components?: {
101
+ schemas?: Record<string, unknown>;
102
+ securitySchemes?: Record<string, unknown>;
103
+ };
104
+ }
105
+ export declare class OpenApiGenerator {
106
+ private config;
107
+ private routes;
108
+ constructor(config: OpenApiConfig);
109
+ /**
110
+ * Add a route to the OpenAPI documentation
111
+ */
112
+ addRoute(route: OpenApiRouteConfig): void;
113
+ /**
114
+ * Add multiple routes at once
115
+ */
116
+ addRoutes(routes: OpenApiRouteConfig[]): void;
117
+ /**
118
+ * Generate the complete OpenAPI specification
119
+ */
120
+ generate(): object;
121
+ /**
122
+ * Generate OpenAPI spec as JSON string
123
+ */
124
+ toJSON(): string;
125
+ /**
126
+ * Generate OpenAPI spec as YAML string (basic implementation)
127
+ */
128
+ toYAML(): string;
129
+ private objectToYaml;
130
+ }
131
+ /**
132
+ * Helper function to create Swagger UI HTML page
133
+ */
134
+ export declare function generateSwaggerUI(specUrl: string | object): string;
135
+ //# sourceMappingURL=OpenApiGenerator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OpenApiGenerator.d.ts","sourceRoot":"","sources":["../../src/docs/OpenApiGenerator.ts"],"names":[],"mappings":"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"}