nural 0.1.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,458 @@
1
+ import { z } from 'zod';
2
+ export { z } from 'zod';
3
+ import { Request, Response } from 'express';
4
+ import { FastifyRequest, FastifyReply } from 'fastify';
5
+ export { extendZodWithOpenApi } from '@asteasolutions/zod-to-openapi';
6
+
7
+ /**
8
+ * Middleware Types and Helpers
9
+ */
10
+ /**
11
+ * Middleware handler function type
12
+ * Returns data to be merged into route context
13
+ */
14
+ type MiddlewareHandler<Req = unknown, Res = unknown> = (req: Req, res: Res) => Promise<Record<string, unknown> | void> | Record<string, unknown> | void;
15
+ /**
16
+ * Define a type-safe middleware
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * const authMiddleware = defineMiddleware(async (req: Request) => {
21
+ * const token = req.headers.authorization;
22
+ * if (!token) throw new Error('Unauthorized');
23
+ * return { user: { id: '123', role: 'admin' } };
24
+ * });
25
+ * ```
26
+ */
27
+ declare function defineMiddleware<T extends Record<string, unknown> | void, Req = unknown, Res = unknown>(fn: (req: Req, res: Res) => Promise<T> | T): (req: Req, res: Res) => Promise<T> | T;
28
+
29
+ /**
30
+ * HTTP Types
31
+ * Centralized HTTP-related type definitions
32
+ */
33
+ /**
34
+ * Supported HTTP methods
35
+ */
36
+ type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS" | "HEAD" | "ALL";
37
+ /**
38
+ * Common HTTP status codes
39
+ */
40
+ type HttpStatusCode = 200 | 201 | 204 | 400 | 401 | 403 | 404 | 500;
41
+
42
+ /**
43
+ * Route Types
44
+ * Type definitions for route configuration and handlers
45
+ */
46
+
47
+ /**
48
+ * Generic Zod type - either a Zod schema or undefined
49
+ */
50
+ type ZodAny = z.ZodTypeAny | undefined;
51
+ /**
52
+ * Inference helper: extracts type from Zod schema, returns unknown if undefined
53
+ */
54
+ type InferZ<T extends ZodAny> = T extends z.ZodTypeAny ? z.infer<T> : unknown;
55
+ /**
56
+ * Extract the return type of a single middleware
57
+ */
58
+ type MiddlewareReturn<M> = M extends MiddlewareHandler<any, any> ? Awaited<ReturnType<M>> : {};
59
+ /**
60
+ * Convert an array of middlewares into an intersection type
61
+ * @example [{user: string}] & [{role: string}] -> {user: string, role: string}
62
+ */
63
+ type MergeMiddlewareTypes<M extends MiddlewareHandler<any, any>[] | undefined> = M extends Array<any> ? MiddlewareReturn<M[number]> extends infer R ? R extends void ? {} : R : {} : {};
64
+ /**
65
+ * Context passed to route handlers
66
+ */
67
+ type RouteContext<P extends ZodAny, Q extends ZodAny, B extends ZodAny, M extends MiddlewareHandler<any, any>[] | undefined> = {
68
+ /** Validated path parameters */
69
+ params: InferZ<P>;
70
+ /** Validated query parameters */
71
+ query: InferZ<Q>;
72
+ /** Validated request body */
73
+ body: InferZ<B>;
74
+ /** Raw request object (Express or Fastify) */
75
+ req: Request | FastifyRequest;
76
+ /** Raw response object (Express or Fastify) */
77
+ res: Response | FastifyReply;
78
+ } & MergeMiddlewareTypes<M>;
79
+ /**
80
+ * Route handler function type
81
+ */
82
+ type RouteHandler<P extends ZodAny, Q extends ZodAny, B extends ZodAny, R extends ZodAny, M extends MiddlewareHandler<any, any>[] | undefined> = (ctx: RouteContext<P, Q, B, M>) => Promise<InferZ<R> | void> | InferZ<R> | void;
83
+ /**
84
+ * Route configuration object
85
+ */
86
+ interface RouteConfig<P extends ZodAny = undefined, Q extends ZodAny = undefined, B extends ZodAny = undefined, R extends ZodAny = undefined, M extends MiddlewareHandler<any, any>[] | undefined = undefined> {
87
+ /** HTTP method */
88
+ method: HttpMethod;
89
+ /** Route path (supports :param syntax) */
90
+ path: string;
91
+ /** Short summary for documentation */
92
+ summary?: string;
93
+ /** Detailed description for documentation */
94
+ description?: string;
95
+ /** Tags for grouping in documentation */
96
+ tags?: string[];
97
+ /** Middleware to run before handler */
98
+ middleware?: M;
99
+ /** Request validation schemas */
100
+ request?: {
101
+ /** Path parameters schema */
102
+ params?: P;
103
+ /** Query parameters schema */
104
+ query?: Q;
105
+ /** Request body schema */
106
+ body?: B;
107
+ };
108
+ /** Response schemas by status code */
109
+ responses?: Record<number, z.ZodTypeAny>;
110
+ /** Route handler function */
111
+ handler: RouteHandler<P, Q, B, R, M>;
112
+ }
113
+ /**
114
+ * Catch-all type for arrays of routes
115
+ */
116
+ type AnyRouteConfig = RouteConfig<any, any, any, any, any>;
117
+
118
+ /**
119
+ * Error Types and Handler
120
+ * Types for global error handling
121
+ */
122
+
123
+ /**
124
+ * Error context passed to error handlers
125
+ */
126
+ interface ErrorContext {
127
+ /** The error that occurred */
128
+ error: Error;
129
+ /** HTTP request (Express or Fastify) */
130
+ request: Request | FastifyRequest;
131
+ /** HTTP response (Express or Fastify) */
132
+ response: Response | FastifyReply;
133
+ /** Route path that errored */
134
+ path?: string;
135
+ /** HTTP method */
136
+ method?: string;
137
+ }
138
+ /**
139
+ * Error response returned by error handlers
140
+ */
141
+ interface ErrorResponse {
142
+ /** HTTP status code */
143
+ status: number;
144
+ /** Response body */
145
+ body: Record<string, unknown>;
146
+ /** Optional headers to set */
147
+ headers?: Record<string, string>;
148
+ }
149
+ /**
150
+ * Global error handler function type
151
+ */
152
+ type ErrorHandler = (ctx: ErrorContext) => ErrorResponse | Promise<ErrorResponse>;
153
+ /**
154
+ * Error handler configuration
155
+ */
156
+ interface ErrorHandlerConfig {
157
+ /** Custom error handler function */
158
+ handler?: ErrorHandler;
159
+ /** Include stack trace in development */
160
+ includeStack?: boolean;
161
+ /** Log errors to console */
162
+ logErrors?: boolean;
163
+ /** Custom error logger */
164
+ logger?: (error: Error, ctx: ErrorContext) => void;
165
+ }
166
+
167
+ /**
168
+ * Middleware Configuration Types
169
+ * Types for CORS and Helmet middleware configuration
170
+ */
171
+ /**
172
+ * CORS configuration options
173
+ */
174
+ interface CorsConfig {
175
+ /**
176
+ * Allowed origins
177
+ * - `true` or `'*'` allows all origins
178
+ * - String for single origin
179
+ * - Array for multiple origins
180
+ * - Function for dynamic origin check
181
+ */
182
+ origin?: boolean | string | string[] | ((origin: string) => boolean);
183
+ /** Allowed HTTP methods */
184
+ methods?: string[];
185
+ /** Allowed headers */
186
+ allowedHeaders?: string[];
187
+ /** Headers exposed to client */
188
+ exposedHeaders?: string[];
189
+ /** Allow credentials (cookies, authorization headers) */
190
+ credentials?: boolean;
191
+ /** Preflight cache max age in seconds */
192
+ maxAge?: number;
193
+ /** Pass preflight response to next handler */
194
+ preflightContinue?: boolean;
195
+ /** Success status code for OPTIONS requests */
196
+ optionsSuccessStatus?: number;
197
+ }
198
+ /**
199
+ * Helmet configuration options
200
+ */
201
+ interface HelmetConfig {
202
+ /** Content-Security-Policy header */
203
+ contentSecurityPolicy?: boolean | {
204
+ directives?: Record<string, string[]>;
205
+ };
206
+ /** Cross-Origin-Embedder-Policy header */
207
+ crossOriginEmbedderPolicy?: boolean;
208
+ /** Cross-Origin-Opener-Policy header */
209
+ crossOriginOpenerPolicy?: boolean | {
210
+ policy?: string;
211
+ };
212
+ /** Cross-Origin-Resource-Policy header */
213
+ crossOriginResourcePolicy?: boolean | {
214
+ policy?: string;
215
+ };
216
+ /** X-DNS-Prefetch-Control header */
217
+ dnsPrefetchControl?: boolean | {
218
+ allow?: boolean;
219
+ };
220
+ /** X-Frame-Options header */
221
+ frameguard?: boolean | {
222
+ action?: "deny" | "sameorigin";
223
+ };
224
+ /** Strict-Transport-Security header */
225
+ hsts?: boolean | {
226
+ maxAge?: number;
227
+ includeSubDomains?: boolean;
228
+ preload?: boolean;
229
+ };
230
+ /** X-Content-Type-Options header */
231
+ noSniff?: boolean;
232
+ /** X-Permitted-Cross-Domain-Policies header */
233
+ permittedCrossDomainPolicies?: boolean | {
234
+ policy?: string;
235
+ };
236
+ /** Referrer-Policy header */
237
+ referrerPolicy?: boolean | {
238
+ policy?: string | string[];
239
+ };
240
+ /** X-XSS-Protection header (legacy) */
241
+ xssFilter?: boolean;
242
+ }
243
+
244
+ /**
245
+ * Configuration Types
246
+ * Types for Nural framework configuration
247
+ */
248
+ /**
249
+ * Documentation configuration options
250
+ */
251
+ interface DocsConfig {
252
+ /** Enable documentation endpoint */
253
+ enabled?: boolean;
254
+ /** API title shown in docs */
255
+ title?: string;
256
+ /** API version */
257
+ version?: string;
258
+ /** API description */
259
+ description?: string;
260
+ /** Documentation UI path (default: /docs) */
261
+ path?: string;
262
+ /** Documentation UI type */
263
+ ui?: "scalar" | "swagger";
264
+ }
265
+ /**
266
+ * Main Nural framework configuration
267
+ */
268
+ interface NuralConfig {
269
+ /** Server framework to use */
270
+ framework?: "express" | "fastify";
271
+ /** Documentation settings (true for defaults, false to disable, or DocsConfig) */
272
+ docs?: boolean | DocsConfig;
273
+ /** CORS settings (true for defaults, false to disable, or CorsConfig) */
274
+ cors?: boolean | CorsConfig;
275
+ /** Helmet security headers (true for defaults, false to disable, or HelmetConfig) */
276
+ helmet?: boolean | HelmetConfig;
277
+ /** Logger configuration */
278
+ logger?: {
279
+ enabled?: boolean;
280
+ showUserAgent?: boolean;
281
+ showTime?: boolean;
282
+ };
283
+ /** Global error handler (true for defaults, function, or config) */
284
+ errorHandler?: boolean | ErrorHandler | ErrorHandlerConfig;
285
+ }
286
+
287
+ /**
288
+ * Zero-Dependency Logger
289
+ * Lightweight, colorful, and powerful logging system
290
+ */
291
+ interface LoggerConfig {
292
+ /** Enable/disable logging */
293
+ enabled?: boolean;
294
+ /** Minimum log level */
295
+ minLevel?: "log" | "error" | "warn" | "debug";
296
+ /** Show timestamp */
297
+ timestamp?: boolean;
298
+ }
299
+ /**
300
+ * Logger class for specialized context logging
301
+ */
302
+ declare class Logger {
303
+ private context;
304
+ private config;
305
+ constructor(context?: string, config?: LoggerConfig);
306
+ private getTimestamp;
307
+ private print;
308
+ log(message: string): void;
309
+ error(message: string, trace?: string): void;
310
+ warn(message: string): void;
311
+ debug(message: string): void;
312
+ }
313
+
314
+ /**
315
+ * Nural Framework
316
+ * Main application class that orchestrates adapters and documentation
317
+ */
318
+
319
+ /**
320
+ * Nural - The intelligent, schema-first REST framework
321
+ *
322
+ * @example
323
+ * ```typescript
324
+ * const app = new Nural({
325
+ * framework: 'express',
326
+ * docs: true,
327
+ * cors: true,
328
+ * helmet: true,
329
+ * errorHandler: true,
330
+ * });
331
+ * app.register([userRoute, healthRoute]);
332
+ * app.start(3000);
333
+ * ```
334
+ */
335
+ declare class Nural {
336
+ private adapter;
337
+ private docsGenerator;
338
+ private docsConfig;
339
+ private corsConfig;
340
+ private helmetConfig;
341
+ private errorHandlerConfig;
342
+ private isExpress;
343
+ logger: Logger;
344
+ constructor(config?: NuralConfig);
345
+ /**
346
+ * Apply CORS and Helmet middleware based on config
347
+ */
348
+ private applyBuiltInMiddleware;
349
+ /**
350
+ * Register routes with the application
351
+ */
352
+ register(routes: AnyRouteConfig[]): void;
353
+ /**
354
+ * Start the server
355
+ */
356
+ start(port: number): void;
357
+ /**
358
+ * Setup documentation routes
359
+ */
360
+ private setupDocs;
361
+ }
362
+
363
+ /**
364
+ * Route Helper
365
+ */
366
+
367
+ /**
368
+ * Create a type-safe route configuration
369
+ *
370
+ * @example
371
+ * ```typescript
372
+ * const userRoute = createRoute({
373
+ * method: 'GET',
374
+ * path: '/users/:id',
375
+ * summary: 'Get User by ID',
376
+ * request: { params: z.object({ id: z.string() }) },
377
+ * responses: { 200: z.object({ id: z.string(), name: z.string() }) },
378
+ * handler: async ({ params }) => {
379
+ * return { id: params.id, name: 'Chetan' };
380
+ * }
381
+ * });
382
+ * ```
383
+ */
384
+ declare function createRoute<P extends ZodAny = undefined, Q extends ZodAny = undefined, B extends ZodAny = undefined, R extends ZodAny = undefined, M extends MiddlewareHandler<any, any>[] | undefined = undefined>(config: RouteConfig<P, Q, B, R, M>): RouteConfig<P, Q, B, R, M>;
385
+
386
+ /**
387
+ * Unified Exception System
388
+ * NestJS-style HTTP exceptions for standardized error handling
389
+ */
390
+ interface HttpErrorResponse {
391
+ statusCode: number;
392
+ message: string;
393
+ error?: string;
394
+ timestamp?: string;
395
+ path?: string;
396
+ details?: unknown;
397
+ }
398
+ /**
399
+ * Base HTTP Exception Class
400
+ */
401
+ declare class HttpException extends Error {
402
+ readonly statusCode: number;
403
+ readonly error: string;
404
+ readonly details?: unknown;
405
+ constructor(response: string | Record<string, any>, statusCode: number, details?: unknown);
406
+ getResponse(): HttpErrorResponse;
407
+ private getStatusName;
408
+ }
409
+ declare class BadRequestException extends HttpException {
410
+ constructor(message?: string, details?: unknown);
411
+ }
412
+ declare class UnauthorizedException extends HttpException {
413
+ constructor(message?: string, details?: unknown);
414
+ }
415
+ declare class ForbiddenException extends HttpException {
416
+ constructor(message?: string, details?: unknown);
417
+ }
418
+ declare class NotFoundException extends HttpException {
419
+ constructor(message?: string, details?: unknown);
420
+ }
421
+ declare class ConflictException extends HttpException {
422
+ constructor(message?: string, details?: unknown);
423
+ }
424
+ declare class GoneException extends HttpException {
425
+ constructor(message?: string, details?: unknown);
426
+ }
427
+ declare class PayloadTooLargeException extends HttpException {
428
+ constructor(message?: string, details?: unknown);
429
+ }
430
+ declare class UnsupportedMediaTypeException extends HttpException {
431
+ constructor(message?: string, details?: unknown);
432
+ }
433
+ declare class UnprocessableEntityException extends HttpException {
434
+ constructor(message?: string, details?: unknown);
435
+ }
436
+ declare class InternalServerErrorException extends HttpException {
437
+ constructor(message?: string, details?: unknown);
438
+ }
439
+ declare class NotImplementedException extends HttpException {
440
+ constructor(message?: string, details?: unknown);
441
+ }
442
+ declare class BadGatewayException extends HttpException {
443
+ constructor(message?: string, details?: unknown);
444
+ }
445
+ declare class ServiceUnavailableException extends HttpException {
446
+ constructor(message?: string, details?: unknown);
447
+ }
448
+ declare class GatewayTimeoutException extends HttpException {
449
+ constructor(message?: string, details?: unknown);
450
+ }
451
+ /**
452
+ * Custom Exception for specific use cases
453
+ */
454
+ declare class CustomException extends HttpException {
455
+ constructor(message: string, statusCode: number, details?: unknown);
456
+ }
457
+
458
+ export { type AnyRouteConfig, BadGatewayException, BadRequestException, ConflictException, type CorsConfig, CustomException, type DocsConfig, type ErrorContext, type ErrorHandler, type ErrorHandlerConfig, ForbiddenException, GatewayTimeoutException, GoneException, type HelmetConfig, type HttpErrorResponse, HttpException, type HttpMethod, type HttpStatusCode, InternalServerErrorException, Logger, type LoggerConfig, NotFoundException, NotImplementedException, Nural, type NuralConfig, PayloadTooLargeException, type RouteConfig, type RouteContext, type RouteHandler, ServiceUnavailableException, UnauthorizedException, UnprocessableEntityException, UnsupportedMediaTypeException, createRoute, defineMiddleware };