@morojs/moro 1.8.12 → 1.8.13
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.
- package/README.md +4 -2
- package/dist/core/cluster/thread-cluster.d.ts +25 -0
- package/dist/core/cluster/thread-cluster.js +95 -3
- package/dist/core/cluster/thread-cluster.js.map +1 -1
- package/dist/core/config/config-validator.js +15 -0
- package/dist/core/config/config-validator.js.map +1 -1
- package/dist/core/config/index.js +19 -2
- package/dist/core/config/index.js.map +1 -1
- package/dist/core/framework.d.ts +26 -0
- package/dist/core/framework.js +195 -6
- package/dist/core/framework.js.map +1 -1
- package/dist/core/http/http-server.d.ts +17 -0
- package/dist/core/http/http-server.js +21 -1
- package/dist/core/http/http-server.js.map +1 -1
- package/dist/core/http/http2-server.d.ts +13 -0
- package/dist/core/http/http2-server.js +11 -0
- package/dist/core/http/http2-server.js.map +1 -1
- package/dist/core/http/moro-engine-server.d.ts +28 -0
- package/dist/core/http/moro-engine-server.js +115 -11
- package/dist/core/http/moro-engine-server.js.map +1 -1
- package/dist/core/http/utils/body-type.d.ts +12 -0
- package/dist/core/http/utils/body-type.js +70 -0
- package/dist/core/http/utils/body-type.js.map +1 -0
- package/dist/core/http/utils/ssl-config.d.ts +11 -0
- package/dist/core/http/utils/ssl-config.js +3 -0
- package/dist/core/http/utils/ssl-config.js.map +1 -1
- package/dist/core/http/utils/uws-worker-clustering.js +5 -4
- package/dist/core/http/utils/uws-worker-clustering.js.map +1 -1
- package/dist/core/http/uws-http-server.d.ts +3 -0
- package/dist/core/http/uws-http-server.js +22 -1
- package/dist/core/http/uws-http-server.js.map +1 -1
- package/dist/core/middleware/built-in/body-parsers/index.d.ts +18 -0
- package/dist/core/middleware/built-in/body-parsers/index.js +41 -0
- package/dist/core/middleware/built-in/body-parsers/index.js.map +1 -1
- package/dist/core/middleware/built-in/cache/adapters/cache/redis.d.ts +32 -8
- package/dist/core/middleware/built-in/cache/adapters/cache/redis.js +117 -25
- package/dist/core/middleware/built-in/cache/adapters/cache/redis.js.map +1 -1
- package/dist/core/middleware/built-in/compression/core.js +5 -0
- package/dist/core/middleware/built-in/compression/core.js.map +1 -1
- package/dist/core/middleware/built-in/session/core.d.ts +1 -0
- package/dist/core/middleware/built-in/session/core.js.map +1 -1
- package/dist/core/middleware/built-in/static/core.d.ts +18 -0
- package/dist/core/middleware/built-in/static/core.js +128 -7
- package/dist/core/middleware/built-in/static/core.js.map +1 -1
- package/dist/core/networking/adapters/engine-adapter.d.ts +2 -2
- package/dist/core/networking/adapters/engine-adapter.js +40 -1
- package/dist/core/networking/adapters/engine-adapter.js.map +1 -1
- package/dist/core/networking/adapters/socketio-adapter.d.ts +2 -2
- package/dist/core/networking/adapters/socketio-adapter.js +10 -1
- package/dist/core/networking/adapters/socketio-adapter.js.map +1 -1
- package/dist/core/networking/adapters/uws-adapter.d.ts +2 -2
- package/dist/core/networking/adapters/uws-adapter.js +54 -3
- package/dist/core/networking/adapters/uws-adapter.js.map +1 -1
- package/dist/core/networking/adapters/ws-adapter.d.ts +9 -2
- package/dist/core/networking/adapters/ws-adapter.js +97 -12
- package/dist/core/networking/adapters/ws-adapter.js.map +1 -1
- package/dist/core/networking/websocket-adapter.d.ts +19 -1
- package/dist/core/networking/websocket-adapter.js.map +1 -1
- package/dist/core/routing/index.d.ts +12 -8
- package/dist/core/routing/index.js +7 -2
- package/dist/core/routing/index.js.map +1 -1
- package/dist/core/routing/unified-router.d.ts +46 -8
- package/dist/core/routing/unified-router.js +108 -32
- package/dist/core/routing/unified-router.js.map +1 -1
- package/dist/core/utilities/package-utils.d.ts +7 -0
- package/dist/core/utilities/package-utils.js +2 -0
- package/dist/core/utilities/package-utils.js.map +1 -1
- package/dist/core/workers/worker-manager.js +2 -2
- package/dist/core/workers/worker-manager.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/moro.d.ts +12 -1
- package/dist/moro.js +63 -7
- package/dist/moro.js.map +1 -1
- package/dist/types/cache.d.ts +2 -0
- package/dist/types/cache.js.map +1 -1
- package/dist/types/config.d.ts +9 -0
- package/dist/types/config.js.map +1 -1
- package/dist/types/http.d.ts +6 -0
- package/dist/types/http.js.map +1 -1
- package/dist/types/session.d.ts +1 -0
- package/dist/types/session.js.map +1 -1
- package/package.json +1 -1
package/dist/types/cache.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ export interface CacheAdapter {
|
|
|
5
5
|
clear(): Promise<void>;
|
|
6
6
|
exists(key: string): Promise<boolean>;
|
|
7
7
|
ttl(key: string): Promise<number>;
|
|
8
|
+
/** Release any connection the adapter owns (optional; Redis implements it). */
|
|
9
|
+
close?(): Promise<void>;
|
|
8
10
|
}
|
|
9
11
|
export interface CacheStrategy {
|
|
10
12
|
key: (req: any) => string;
|
package/dist/types/cache.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/types/cache.ts"],"names":[],"mappings":"","sourcesContent":["// Cache Types and Interfaces\nexport interface CacheAdapter {\n get(key: string): Promise<any>;\n set(key: string, value: any, ttl?: number): Promise<void>;\n del(key: string): Promise<void>;\n clear(): Promise<void>;\n exists(key: string): Promise<boolean>;\n ttl(key: string): Promise<number>;\n}\n\nexport interface CacheStrategy {\n key: (req: any) => string;\n ttl: number;\n condition?: (req: any, res: any) => boolean;\n invalidateOn?: string[];\n}\n\nexport interface CacheOptions {\n adapter?: string | CacheAdapter;\n adapterOptions?: any;\n strategies?: {\n [pattern: string]: CacheStrategy;\n };\n defaultTtl?: number;\n keyPrefix?: string;\n\n // HTTP Caching Options\n httpCaching?: boolean;\n maxAge?: number;\n cacheControl?: string;\n staleWhileRevalidate?: number;\n vary?: string[];\n etag?: boolean | 'weak' | 'strong';\n conditionalRequests?: boolean;\n generateETag?: (content: string, type?: string) => string;\n}\n\nexport interface CachedResponse {\n body: any;\n status: number;\n headers: Record<string, any>;\n contentType?: string;\n timestamp: number;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/types/cache.ts"],"names":[],"mappings":"","sourcesContent":["// Cache Types and Interfaces\nexport interface CacheAdapter {\n get(key: string): Promise<any>;\n set(key: string, value: any, ttl?: number): Promise<void>;\n del(key: string): Promise<void>;\n clear(): Promise<void>;\n exists(key: string): Promise<boolean>;\n ttl(key: string): Promise<number>;\n /** Release any connection the adapter owns (optional; Redis implements it). */\n close?(): Promise<void>;\n}\n\nexport interface CacheStrategy {\n key: (req: any) => string;\n ttl: number;\n condition?: (req: any, res: any) => boolean;\n invalidateOn?: string[];\n}\n\nexport interface CacheOptions {\n adapter?: string | CacheAdapter;\n adapterOptions?: any;\n strategies?: {\n [pattern: string]: CacheStrategy;\n };\n defaultTtl?: number;\n keyPrefix?: string;\n\n // HTTP Caching Options\n httpCaching?: boolean;\n maxAge?: number;\n cacheControl?: string;\n staleWhileRevalidate?: number;\n vary?: string[];\n etag?: boolean | 'weak' | 'strong';\n conditionalRequests?: boolean;\n generateETag?: (content: string, type?: string) => string;\n}\n\nexport interface CachedResponse {\n body: any;\n status: number;\n headers: Record<string, any>;\n contentType?: string;\n timestamp: number;\n}\n"]}
|
package/dist/types/config.d.ts
CHANGED
|
@@ -26,6 +26,14 @@ export interface SSLConfig {
|
|
|
26
26
|
minVersion?: 'TLSv1.2' | 'TLSv1.3';
|
|
27
27
|
requestCert?: boolean;
|
|
28
28
|
rejectUnauthorized?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Reload the certificate when the key/cert files change on disk (file-path
|
|
31
|
+
* shape only; `true` = 1000 ms debounce). Equivalent to calling
|
|
32
|
+
* `app.reloadTLS()` after each change.
|
|
33
|
+
*/
|
|
34
|
+
watch?: boolean | {
|
|
35
|
+
debounceMs?: number;
|
|
36
|
+
};
|
|
29
37
|
}
|
|
30
38
|
/** Per-phase receive timeouts. 0 = use the per-server default / disabled. */
|
|
31
39
|
export interface ServerTimeoutsConfig {
|
|
@@ -216,6 +224,7 @@ export interface ModuleDefaultsConfig {
|
|
|
216
224
|
enabled: boolean;
|
|
217
225
|
store: 'memory' | 'redis' | 'file';
|
|
218
226
|
storeOptions?: {
|
|
227
|
+
url?: string;
|
|
219
228
|
host?: string;
|
|
220
229
|
port?: number;
|
|
221
230
|
password?: string;
|
package/dist/types/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA,0DAA0D","sourcesContent":["// TypeScript-based Configuration Types for Moro Framework\n\n/**\n * CORS origin function type for dynamic origin validation\n */\nexport type OriginFunction = (\n origin: string | undefined,\n req: any\n) => string | string[] | boolean | Promise<string | string[] | boolean>;\n\n/**\n * Deep partial type that makes all properties and nested properties optional\n * Used for user-provided configuration where only partial overrides are needed\n */\nexport type DeepPartial<T> = T extends object\n ? T extends Array<infer U>\n ? Array<DeepPartial<U>>\n : T extends (...args: any[]) => any\n ? T\n : { [P in keyof T]?: DeepPartial<T[P]> }\n : T;\n\n/** Unified SSL/TLS config (superset of both historical shapes). */\nexport interface SSLConfig {\n /** File-path shape (uWS-style; keyFile/certFile also accepted) */\n key_file_name?: string;\n cert_file_name?: string;\n ca_file_name?: string | string[];\n keyFile?: string;\n certFile?: string;\n caFile?: string | string[];\n /** Inline-PEM shape (node-style) */\n key?: string | Buffer;\n cert?: string | Buffer;\n ca?: string | Buffer | Array<string | Buffer>;\n passphrase?: string;\n minVersion?: 'TLSv1.2' | 'TLSv1.3';\n requestCert?: boolean;\n rejectUnauthorized?: boolean;\n}\n\n/** Per-phase receive timeouts. 0 = use the per-server default / disabled. */\nexport interface ServerTimeoutsConfig {\n /** Full-request receive budget (ms); does NOT reset on activity. */\n request?: number;\n /** Socket inactivity timeout (ms). */\n idle?: number;\n /** Node keep-alive socket timeout (ms). Default 5000. */\n keepAlive?: number;\n /** Node headers-received timeout (ms). Default 6000. */\n headers?: number;\n}\n\nexport interface MultipartLimitsConfig {\n maxParts?: number;\n maxPartHeaderBytes?: number | string;\n maxFiles?: number;\n maxFileSize?: number | string;\n}\n\n/** Fine-grained limits; every value is a documented default, not a hard cap. */\nexport interface ServerLimitsConfig {\n /** Max request head (request line + headers) size. Node maxHeaderSize / engine maxHeadSize. */\n maxHeaderSize?: number | string;\n /** Max header count. Node maxHeadersCount / engine maxHeaders. */\n maxHeaders?: number;\n multipart?: MultipartLimitsConfig;\n /** Reassembled WebSocket message cap (engine wsMaxMessageSize). */\n wsMaxMessageSize?: number | string;\n /** WebSocket send backpressure cap (engine wsBackpressureLimit). 0 = unlimited. */\n wsBackpressureLimit?: number | string;\n /** Write-queue high-water mark (engine writeHighWaterMark). */\n writeHighWaterMark?: number | string;\n /** Per-connection not-yet-parsed backlog cap (engine maxPendingBytes). */\n maxPendingBytes?: number | string;\n}\n\nexport interface Http2SettingsConfig {\n maxConcurrentStreams?: number;\n initialWindowSize?: number;\n maxFrameSize?: number;\n maxHeaderListSize?: number;\n headerTableSize?: number;\n enablePush?: boolean;\n enableConnectProtocol?: boolean;\n maxHeaderSize?: number;\n}\n\nexport interface ServerConfig {\n port: number;\n host: string;\n maxConnections: number;\n /** @deprecated Use timeouts.request. Kept as an alias; still honored. */\n timeout: number;\n bodySizeLimit: string;\n maxUploadSize: string; // Maximum size for file uploads (multipart/form-data)\n /** Per-phase receive timeouts (finally applied to every runtime). */\n timeouts?: ServerTimeoutsConfig;\n /** Fine-grained size/count limits, passed through to whichever runtime serves. */\n limits?: ServerLimitsConfig;\n /** TCP listen backlog. */\n backlog?: number;\n /** HTTP/2: true, or an options object. Served natively by the engine when\n * it supports h2 (feature-detected), else by the Node http2 server. */\n http2?:\n boolean | { allowHTTP1?: boolean; maxSessionMemory?: number; settings?: Http2SettingsConfig };\n requestTracking: {\n enabled: boolean;\n };\n requestLogging: {\n enabled: boolean;\n };\n errorBoundary: {\n enabled: boolean;\n };\n /**\n * HTTP engine selection. Default: 'moro'.\n * - 'moro' (default): Moro's own native engine (@morojs/engine), falling back\n * to the Node.js http server if it cannot load on this platform/Node ABI\n * - 'node': the Node.js http server (no native engine)\n * - 'uws': opt in to uWebSockets.js, falling back to Node.js if it cannot load\n * Any chosen engine that cannot load degrades to Node.js and logs why; the app\n * never fails to boot. Inspect what actually booted via app.engine.\n */\n engine?: 'moro' | 'node' | 'uws';\n /** @deprecated Use engine: 'uws' instead. Enable uWebSockets for both HTTP and WebSocket */\n useUWebSockets?: boolean;\n /** Unified SSL/TLS config; flows to whichever runtime serves. */\n ssl?: SSLConfig;\n}\n\nexport interface ServiceDiscoveryConfig {\n enabled: boolean;\n type: 'memory' | 'consul' | 'kubernetes';\n consulUrl: string;\n kubernetesNamespace: string;\n healthCheckInterval: number;\n retryAttempts: number;\n}\n\nexport interface DatabaseConfig {\n url?: string;\n redis?: {\n url: string;\n maxRetries: number;\n retryDelay: number;\n keyPrefix: string;\n };\n mysql?: {\n host: string;\n port: number;\n database?: string;\n username?: string;\n password?: string;\n connectionLimit: number;\n acquireTimeout: number;\n timeout: number;\n };\n postgresql?: {\n host: string;\n port: number;\n database?: string;\n user?: string;\n password?: string;\n connectionLimit: number;\n ssl?: boolean;\n };\n sqlite?: {\n filename: string;\n memory?: boolean;\n verbose?: boolean;\n };\n mongodb?: {\n url?: string;\n host?: string;\n port?: number;\n database?: string;\n username?: string;\n password?: string;\n };\n}\n\n// Validation error context passed to error handlers\nexport interface ValidationErrorContext {\n request: {\n method: string;\n path: string;\n url: string;\n headers: Record<string, any>;\n };\n route?: {\n path: string;\n method: string;\n };\n field: 'body' | 'query' | 'params' | 'headers';\n}\n\n// Validation error detail structure\nexport interface ValidationErrorDetail {\n field: string;\n message: string;\n code?: string;\n value?: any;\n path?: (string | number)[];\n}\n\n// Validation error response structure\nexport interface ValidationErrorResponse {\n status: number;\n body: any;\n headers?: Record<string, string>;\n}\n\n// Validation error handler function type\nexport type ValidationErrorHandler = (\n errors: ValidationErrorDetail[],\n context: ValidationErrorContext\n) => ValidationErrorResponse;\n\nexport interface ModuleDefaultsConfig {\n apiPrefix?: string; // Prefix for module routes, defaults to '/api/' - set to empty string '' to disable\n cache: {\n enabled: boolean;\n defaultTtl: number;\n maxSize: number;\n strategy: 'lru' | 'lfu' | 'fifo';\n };\n rateLimit: {\n enabled: boolean;\n defaultRequests: number;\n defaultWindow: number;\n skipSuccessfulRequests: boolean;\n skipFailedRequests: boolean;\n };\n validation: {\n enabled: boolean;\n stripUnknown: boolean;\n abortEarly: boolean;\n allowUnknown?: boolean;\n onError?: ValidationErrorHandler;\n };\n session?: {\n enabled: boolean;\n store: 'memory' | 'redis' | 'file';\n storeOptions?: {\n host?: string;\n port?: number;\n password?: string;\n keyPrefix?: string;\n path?: string;\n max?: number;\n };\n secret?: string;\n name?: string;\n rolling?: boolean;\n resave?: boolean;\n saveUninitialized?: boolean;\n cookie?: {\n maxAge?: number;\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: 'strict' | 'lax' | 'none';\n domain?: string;\n path?: string;\n };\n proxy?: boolean;\n unset?: 'destroy' | 'keep';\n };\n autoDiscovery: {\n enabled: boolean;\n paths: string[];\n patterns: string[];\n recursive: boolean;\n loadingStrategy: 'eager' | 'lazy' | 'conditional';\n watchForChanges: boolean;\n ignorePatterns: string[];\n loadOrder: 'alphabetical' | 'dependency' | 'custom';\n failOnError: boolean;\n maxDepth: number;\n };\n}\n\nexport interface LoggingConfig {\n level: 'debug' | 'info' | 'warn' | 'error' | 'fatal';\n format: 'pretty' | 'json' | 'compact';\n enableColors: boolean;\n enableTimestamp: boolean;\n enableContext: boolean;\n // Opt-in: appends a JSON metadata object (e.g. {\"framework\":\"moro\",...}) to pretty log lines.\n // Has no effect on 'json' format - structured output always includes metadata.\n enableMetadata: boolean;\n // Opt-in: collects and renders per-log performance data such as memory usage (e.g. \"(210MB)\").\n // Disabling skips the process.memoryUsage() call on every log line.\n enablePerformance: boolean;\n outputs: {\n console: boolean;\n file: {\n enabled: boolean;\n path: string;\n maxSize: string;\n maxFiles: number;\n };\n webhook: {\n enabled: boolean;\n url?: string;\n headers: Record<string, string>;\n };\n };\n}\n\nexport interface SecurityConfig {\n cors: {\n enabled: boolean;\n origin: string | string[] | boolean | OriginFunction;\n methods: string[];\n allowedHeaders: string[];\n exposedHeaders?: string[];\n credentials: boolean;\n maxAge?: number;\n preflightContinue?: boolean;\n };\n helmet: {\n enabled: boolean;\n // Simplified options (backward compatible)\n contentSecurityPolicy?: boolean;\n hsts?: boolean;\n noSniff?: boolean;\n frameguard?: boolean;\n // Detailed options (for advanced configuration)\n xFrameOptions?: 'DENY' | 'SAMEORIGIN';\n xContentTypeOptions?: boolean;\n xXssProtection?: boolean;\n referrerPolicy?: string;\n strictTransportSecurity?: { maxAge?: number; includeSubDomains?: boolean };\n xDownloadOptions?: boolean;\n xPermittedCrossDomainPolicies?: boolean;\n };\n csrf?: {\n enabled: boolean;\n secret?: string;\n tokenLength?: number;\n cookieName?: string;\n headerName?: string;\n ignoreMethods?: string[];\n sameSite?: boolean;\n };\n csp?: {\n enabled: boolean;\n directives?: {\n defaultSrc?: string[];\n scriptSrc?: string[];\n styleSrc?: string[];\n imgSrc?: string[];\n connectSrc?: string[];\n fontSrc?: string[];\n objectSrc?: string[];\n mediaSrc?: string[];\n frameSrc?: string[];\n childSrc?: string[];\n workerSrc?: string[];\n formAction?: string[];\n upgradeInsecureRequests?: boolean;\n blockAllMixedContent?: boolean;\n };\n reportOnly?: boolean;\n reportUri?: string;\n nonce?: boolean;\n };\n rateLimit: {\n global: {\n enabled: boolean;\n requests: number;\n window: number;\n };\n };\n}\n\nexport interface ExternalServicesConfig {\n stripe?: {\n secretKey?: string | undefined;\n publishableKey?: string | undefined;\n webhookSecret?: string | undefined;\n apiVersion: string;\n };\n paypal?: {\n clientId?: string | undefined;\n clientSecret?: string | undefined;\n webhookId?: string | undefined;\n environment: 'sandbox' | 'production';\n };\n smtp?: {\n host?: string | undefined;\n port: number;\n secure: boolean;\n username?: string | undefined;\n password?: string | undefined;\n };\n}\n\nexport interface PerformanceConfig {\n compression: {\n enabled: boolean;\n level: number;\n threshold: number;\n /** Encoding preference order (default ['br','gzip','deflate']). */\n encodings?: Array<'br' | 'gzip' | 'deflate'>;\n };\n circuitBreaker: {\n enabled: boolean;\n failureThreshold: number;\n resetTimeout: number;\n monitoringPeriod: number;\n };\n clustering: {\n enabled: boolean;\n workers: number | 'auto';\n memoryPerWorkerGB?: number | undefined;\n };\n}\n\nexport interface WebSocketConfig {\n enabled: boolean;\n adapter?: string | 'socket.io' | 'ws' | 'uws';\n compression?: boolean;\n customIdGenerator?: () => string;\n options?: {\n cors?: {\n origin?: string | string[];\n credentials?: boolean;\n };\n path?: string;\n maxPayloadLength?: number;\n idleTimeout?: number;\n ssl?: {\n key_file_name?: string;\n cert_file_name?: string;\n passphrase?: string;\n };\n };\n}\n\nexport interface JobsConfig {\n enabled?: boolean;\n maxConcurrentJobs?: number;\n gracefulShutdownTimeout?: number;\n leaderElection?: {\n enabled?: boolean;\n strategy?: 'file' | 'redis' | 'none';\n lockPath?: string;\n lockTimeout?: number;\n heartbeatInterval?: number;\n };\n executor?: {\n maxRetries?: number;\n retryDelay?: number;\n retryBackoff?: 'linear' | 'exponential';\n retryBackoffMultiplier?: number;\n maxRetryDelay?: number;\n timeout?: number;\n enableCircuitBreaker?: boolean;\n circuitBreakerThreshold?: number;\n circuitBreakerResetTimeout?: number;\n enableMemoryMonitoring?: boolean;\n memoryThreshold?: number;\n };\n stateManager?: {\n persistPath?: string;\n historySize?: number;\n persistInterval?: number;\n enableAutoPersist?: boolean;\n enableRecovery?: boolean;\n };\n}\n\n// File-based routing configuration. When enabled, route files under the\n// configured directories are imported during startup (after module discovery)\n// so their `getApp().get(...)` registrations execute automatically.\nexport interface RoutingConfig {\n enabled: boolean;\n // Directories scanned via loadRoutes(). Defaults to ./src/routes in\n // development and ./dist/(src/)routes in production when omitted.\n paths?: string[];\n}\n\n// Main configuration interface\nexport interface AppConfig {\n server: ServerConfig;\n serviceDiscovery: ServiceDiscoveryConfig;\n database: DatabaseConfig;\n modules: ModuleDefaultsConfig;\n // Enable file-based auto routing (./src/routes). Defaults to true.\n routing: boolean | RoutingConfig;\n logging: LoggingConfig;\n security: SecurityConfig;\n external: ExternalServicesConfig;\n performance: PerformanceConfig;\n websocket: WebSocketConfig;\n jobs?: JobsConfig;\n queue?: QueueConfig;\n}\n\n// Queue Configuration\nexport interface QueueConfig {\n adapter?: 'bull' | 'rabbitmq' | 'sqs' | 'kafka' | 'memory';\n connection?: {\n host?: string;\n port?: number;\n username?: string;\n password?: string;\n database?: number;\n brokers?: string[];\n groupId?: string;\n region?: string;\n queueUrl?: string;\n [key: string]: any;\n };\n concurrency?: number;\n retry?: {\n maxAttempts: number;\n backoff: 'fixed' | 'exponential' | 'linear';\n initialDelay: number;\n maxDelay?: number;\n };\n deadLetterQueue?: {\n enabled: boolean;\n maxRetries: number;\n queueName?: string;\n };\n defaultJobOptions?: {\n removeOnComplete?: boolean | number;\n removeOnFail?: boolean | number;\n attempts?: number;\n backoff?: {\n type: 'fixed' | 'exponential' | 'linear';\n delay: number;\n };\n };\n prefix?: string;\n limiter?: {\n max: number;\n duration: number;\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA,0DAA0D","sourcesContent":["// TypeScript-based Configuration Types for Moro Framework\n\n/**\n * CORS origin function type for dynamic origin validation\n */\nexport type OriginFunction = (\n origin: string | undefined,\n req: any\n) => string | string[] | boolean | Promise<string | string[] | boolean>;\n\n/**\n * Deep partial type that makes all properties and nested properties optional\n * Used for user-provided configuration where only partial overrides are needed\n */\nexport type DeepPartial<T> = T extends object\n ? T extends Array<infer U>\n ? Array<DeepPartial<U>>\n : T extends (...args: any[]) => any\n ? T\n : { [P in keyof T]?: DeepPartial<T[P]> }\n : T;\n\n/** Unified SSL/TLS config (superset of both historical shapes). */\nexport interface SSLConfig {\n /** File-path shape (uWS-style; keyFile/certFile also accepted) */\n key_file_name?: string;\n cert_file_name?: string;\n ca_file_name?: string | string[];\n keyFile?: string;\n certFile?: string;\n caFile?: string | string[];\n /** Inline-PEM shape (node-style) */\n key?: string | Buffer;\n cert?: string | Buffer;\n ca?: string | Buffer | Array<string | Buffer>;\n passphrase?: string;\n minVersion?: 'TLSv1.2' | 'TLSv1.3';\n requestCert?: boolean;\n rejectUnauthorized?: boolean;\n /**\n * Reload the certificate when the key/cert files change on disk (file-path\n * shape only; `true` = 1000 ms debounce). Equivalent to calling\n * `app.reloadTLS()` after each change.\n */\n watch?: boolean | { debounceMs?: number };\n}\n\n/** Per-phase receive timeouts. 0 = use the per-server default / disabled. */\nexport interface ServerTimeoutsConfig {\n /** Full-request receive budget (ms); does NOT reset on activity. */\n request?: number;\n /** Socket inactivity timeout (ms). */\n idle?: number;\n /** Node keep-alive socket timeout (ms). Default 5000. */\n keepAlive?: number;\n /** Node headers-received timeout (ms). Default 6000. */\n headers?: number;\n}\n\nexport interface MultipartLimitsConfig {\n maxParts?: number;\n maxPartHeaderBytes?: number | string;\n maxFiles?: number;\n maxFileSize?: number | string;\n}\n\n/** Fine-grained limits; every value is a documented default, not a hard cap. */\nexport interface ServerLimitsConfig {\n /** Max request head (request line + headers) size. Node maxHeaderSize / engine maxHeadSize. */\n maxHeaderSize?: number | string;\n /** Max header count. Node maxHeadersCount / engine maxHeaders. */\n maxHeaders?: number;\n multipart?: MultipartLimitsConfig;\n /** Reassembled WebSocket message cap (engine wsMaxMessageSize). */\n wsMaxMessageSize?: number | string;\n /** WebSocket send backpressure cap (engine wsBackpressureLimit). 0 = unlimited. */\n wsBackpressureLimit?: number | string;\n /** Write-queue high-water mark (engine writeHighWaterMark). */\n writeHighWaterMark?: number | string;\n /** Per-connection not-yet-parsed backlog cap (engine maxPendingBytes). */\n maxPendingBytes?: number | string;\n}\n\nexport interface Http2SettingsConfig {\n maxConcurrentStreams?: number;\n initialWindowSize?: number;\n maxFrameSize?: number;\n maxHeaderListSize?: number;\n headerTableSize?: number;\n enablePush?: boolean;\n enableConnectProtocol?: boolean;\n maxHeaderSize?: number;\n}\n\nexport interface ServerConfig {\n port: number;\n host: string;\n maxConnections: number;\n /** @deprecated Use timeouts.request. Kept as an alias; still honored. */\n timeout: number;\n bodySizeLimit: string;\n maxUploadSize: string; // Maximum size for file uploads (multipart/form-data)\n /** Per-phase receive timeouts (finally applied to every runtime). */\n timeouts?: ServerTimeoutsConfig;\n /** Fine-grained size/count limits, passed through to whichever runtime serves. */\n limits?: ServerLimitsConfig;\n /** TCP listen backlog. */\n backlog?: number;\n /** HTTP/2: true, or an options object. Served natively by the engine when\n * it supports h2 (feature-detected), else by the Node http2 server. */\n http2?:\n boolean | { allowHTTP1?: boolean; maxSessionMemory?: number; settings?: Http2SettingsConfig };\n requestTracking: {\n enabled: boolean;\n };\n requestLogging: {\n enabled: boolean;\n };\n errorBoundary: {\n enabled: boolean;\n };\n /**\n * HTTP engine selection. Default: 'moro'.\n * - 'moro' (default): Moro's own native engine (@morojs/engine), falling back\n * to the Node.js http server if it cannot load on this platform/Node ABI\n * - 'node': the Node.js http server (no native engine)\n * - 'uws': opt in to uWebSockets.js, falling back to Node.js if it cannot load\n * Any chosen engine that cannot load degrades to Node.js and logs why; the app\n * never fails to boot. Inspect what actually booted via app.engine.\n */\n engine?: 'moro' | 'node' | 'uws';\n /** @deprecated Use engine: 'uws' instead. Enable uWebSockets for both HTTP and WebSocket */\n useUWebSockets?: boolean;\n /** Unified SSL/TLS config; flows to whichever runtime serves. */\n ssl?: SSLConfig;\n}\n\nexport interface ServiceDiscoveryConfig {\n enabled: boolean;\n type: 'memory' | 'consul' | 'kubernetes';\n consulUrl: string;\n kubernetesNamespace: string;\n healthCheckInterval: number;\n retryAttempts: number;\n}\n\nexport interface DatabaseConfig {\n url?: string;\n redis?: {\n url: string;\n maxRetries: number;\n retryDelay: number;\n keyPrefix: string;\n };\n mysql?: {\n host: string;\n port: number;\n database?: string;\n username?: string;\n password?: string;\n connectionLimit: number;\n acquireTimeout: number;\n timeout: number;\n };\n postgresql?: {\n host: string;\n port: number;\n database?: string;\n user?: string;\n password?: string;\n connectionLimit: number;\n ssl?: boolean;\n };\n sqlite?: {\n filename: string;\n memory?: boolean;\n verbose?: boolean;\n };\n mongodb?: {\n url?: string;\n host?: string;\n port?: number;\n database?: string;\n username?: string;\n password?: string;\n };\n}\n\n// Validation error context passed to error handlers\nexport interface ValidationErrorContext {\n request: {\n method: string;\n path: string;\n url: string;\n headers: Record<string, any>;\n };\n route?: {\n path: string;\n method: string;\n };\n field: 'body' | 'query' | 'params' | 'headers';\n}\n\n// Validation error detail structure\nexport interface ValidationErrorDetail {\n field: string;\n message: string;\n code?: string;\n value?: any;\n path?: (string | number)[];\n}\n\n// Validation error response structure\nexport interface ValidationErrorResponse {\n status: number;\n body: any;\n headers?: Record<string, string>;\n}\n\n// Validation error handler function type\nexport type ValidationErrorHandler = (\n errors: ValidationErrorDetail[],\n context: ValidationErrorContext\n) => ValidationErrorResponse;\n\nexport interface ModuleDefaultsConfig {\n apiPrefix?: string; // Prefix for module routes, defaults to '/api/' - set to empty string '' to disable\n cache: {\n enabled: boolean;\n defaultTtl: number;\n maxSize: number;\n strategy: 'lru' | 'lfu' | 'fifo';\n };\n rateLimit: {\n enabled: boolean;\n defaultRequests: number;\n defaultWindow: number;\n skipSuccessfulRequests: boolean;\n skipFailedRequests: boolean;\n };\n validation: {\n enabled: boolean;\n stripUnknown: boolean;\n abortEarly: boolean;\n allowUnknown?: boolean;\n onError?: ValidationErrorHandler;\n };\n session?: {\n enabled: boolean;\n store: 'memory' | 'redis' | 'file';\n storeOptions?: {\n url?: string;\n host?: string;\n port?: number;\n password?: string;\n keyPrefix?: string;\n path?: string;\n max?: number;\n };\n secret?: string;\n name?: string;\n rolling?: boolean;\n resave?: boolean;\n saveUninitialized?: boolean;\n cookie?: {\n maxAge?: number;\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: 'strict' | 'lax' | 'none';\n domain?: string;\n path?: string;\n };\n proxy?: boolean;\n unset?: 'destroy' | 'keep';\n };\n autoDiscovery: {\n enabled: boolean;\n paths: string[];\n patterns: string[];\n recursive: boolean;\n loadingStrategy: 'eager' | 'lazy' | 'conditional';\n watchForChanges: boolean;\n ignorePatterns: string[];\n loadOrder: 'alphabetical' | 'dependency' | 'custom';\n failOnError: boolean;\n maxDepth: number;\n };\n}\n\nexport interface LoggingConfig {\n level: 'debug' | 'info' | 'warn' | 'error' | 'fatal';\n format: 'pretty' | 'json' | 'compact';\n enableColors: boolean;\n enableTimestamp: boolean;\n enableContext: boolean;\n // Opt-in: appends a JSON metadata object (e.g. {\"framework\":\"moro\",...}) to pretty log lines.\n // Has no effect on 'json' format - structured output always includes metadata.\n enableMetadata: boolean;\n // Opt-in: collects and renders per-log performance data such as memory usage (e.g. \"(210MB)\").\n // Disabling skips the process.memoryUsage() call on every log line.\n enablePerformance: boolean;\n outputs: {\n console: boolean;\n file: {\n enabled: boolean;\n path: string;\n maxSize: string;\n maxFiles: number;\n };\n webhook: {\n enabled: boolean;\n url?: string;\n headers: Record<string, string>;\n };\n };\n}\n\nexport interface SecurityConfig {\n cors: {\n enabled: boolean;\n origin: string | string[] | boolean | OriginFunction;\n methods: string[];\n allowedHeaders: string[];\n exposedHeaders?: string[];\n credentials: boolean;\n maxAge?: number;\n preflightContinue?: boolean;\n };\n helmet: {\n enabled: boolean;\n // Simplified options (backward compatible)\n contentSecurityPolicy?: boolean;\n hsts?: boolean;\n noSniff?: boolean;\n frameguard?: boolean;\n // Detailed options (for advanced configuration)\n xFrameOptions?: 'DENY' | 'SAMEORIGIN';\n xContentTypeOptions?: boolean;\n xXssProtection?: boolean;\n referrerPolicy?: string;\n strictTransportSecurity?: { maxAge?: number; includeSubDomains?: boolean };\n xDownloadOptions?: boolean;\n xPermittedCrossDomainPolicies?: boolean;\n };\n csrf?: {\n enabled: boolean;\n secret?: string;\n tokenLength?: number;\n cookieName?: string;\n headerName?: string;\n ignoreMethods?: string[];\n sameSite?: boolean;\n };\n csp?: {\n enabled: boolean;\n directives?: {\n defaultSrc?: string[];\n scriptSrc?: string[];\n styleSrc?: string[];\n imgSrc?: string[];\n connectSrc?: string[];\n fontSrc?: string[];\n objectSrc?: string[];\n mediaSrc?: string[];\n frameSrc?: string[];\n childSrc?: string[];\n workerSrc?: string[];\n formAction?: string[];\n upgradeInsecureRequests?: boolean;\n blockAllMixedContent?: boolean;\n };\n reportOnly?: boolean;\n reportUri?: string;\n nonce?: boolean;\n };\n rateLimit: {\n global: {\n enabled: boolean;\n requests: number;\n window: number;\n };\n };\n}\n\nexport interface ExternalServicesConfig {\n stripe?: {\n secretKey?: string | undefined;\n publishableKey?: string | undefined;\n webhookSecret?: string | undefined;\n apiVersion: string;\n };\n paypal?: {\n clientId?: string | undefined;\n clientSecret?: string | undefined;\n webhookId?: string | undefined;\n environment: 'sandbox' | 'production';\n };\n smtp?: {\n host?: string | undefined;\n port: number;\n secure: boolean;\n username?: string | undefined;\n password?: string | undefined;\n };\n}\n\nexport interface PerformanceConfig {\n compression: {\n enabled: boolean;\n level: number;\n threshold: number;\n /** Encoding preference order (default ['br','gzip','deflate']). */\n encodings?: Array<'br' | 'gzip' | 'deflate'>;\n };\n circuitBreaker: {\n enabled: boolean;\n failureThreshold: number;\n resetTimeout: number;\n monitoringPeriod: number;\n };\n clustering: {\n enabled: boolean;\n workers: number | 'auto';\n memoryPerWorkerGB?: number | undefined;\n };\n}\n\nexport interface WebSocketConfig {\n enabled: boolean;\n adapter?: string | 'socket.io' | 'ws' | 'uws';\n compression?: boolean;\n customIdGenerator?: () => string;\n options?: {\n cors?: {\n origin?: string | string[];\n credentials?: boolean;\n };\n path?: string;\n maxPayloadLength?: number;\n idleTimeout?: number;\n ssl?: {\n key_file_name?: string;\n cert_file_name?: string;\n passphrase?: string;\n };\n };\n}\n\nexport interface JobsConfig {\n enabled?: boolean;\n maxConcurrentJobs?: number;\n gracefulShutdownTimeout?: number;\n leaderElection?: {\n enabled?: boolean;\n strategy?: 'file' | 'redis' | 'none';\n lockPath?: string;\n lockTimeout?: number;\n heartbeatInterval?: number;\n };\n executor?: {\n maxRetries?: number;\n retryDelay?: number;\n retryBackoff?: 'linear' | 'exponential';\n retryBackoffMultiplier?: number;\n maxRetryDelay?: number;\n timeout?: number;\n enableCircuitBreaker?: boolean;\n circuitBreakerThreshold?: number;\n circuitBreakerResetTimeout?: number;\n enableMemoryMonitoring?: boolean;\n memoryThreshold?: number;\n };\n stateManager?: {\n persistPath?: string;\n historySize?: number;\n persistInterval?: number;\n enableAutoPersist?: boolean;\n enableRecovery?: boolean;\n };\n}\n\n// File-based routing configuration. When enabled, route files under the\n// configured directories are imported during startup (after module discovery)\n// so their `getApp().get(...)` registrations execute automatically.\nexport interface RoutingConfig {\n enabled: boolean;\n // Directories scanned via loadRoutes(). Defaults to ./src/routes in\n // development and ./dist/(src/)routes in production when omitted.\n paths?: string[];\n}\n\n// Main configuration interface\nexport interface AppConfig {\n server: ServerConfig;\n serviceDiscovery: ServiceDiscoveryConfig;\n database: DatabaseConfig;\n modules: ModuleDefaultsConfig;\n // Enable file-based auto routing (./src/routes). Defaults to true.\n routing: boolean | RoutingConfig;\n logging: LoggingConfig;\n security: SecurityConfig;\n external: ExternalServicesConfig;\n performance: PerformanceConfig;\n websocket: WebSocketConfig;\n jobs?: JobsConfig;\n queue?: QueueConfig;\n}\n\n// Queue Configuration\nexport interface QueueConfig {\n adapter?: 'bull' | 'rabbitmq' | 'sqs' | 'kafka' | 'memory';\n connection?: {\n host?: string;\n port?: number;\n username?: string;\n password?: string;\n database?: number;\n brokers?: string[];\n groupId?: string;\n region?: string;\n queueUrl?: string;\n [key: string]: any;\n };\n concurrency?: number;\n retry?: {\n maxAttempts: number;\n backoff: 'fixed' | 'exponential' | 'linear';\n initialDelay: number;\n maxDelay?: number;\n };\n deadLetterQueue?: {\n enabled: boolean;\n maxRetries: number;\n queueName?: string;\n };\n defaultJobOptions?: {\n removeOnComplete?: boolean | number;\n removeOnFail?: boolean | number;\n attempts?: number;\n backoff?: {\n type: 'fixed' | 'exponential' | 'linear';\n delay: number;\n };\n };\n prefix?: string;\n limiter?: {\n max: number;\n duration: number;\n };\n}\n"]}
|
package/dist/types/http.d.ts
CHANGED
|
@@ -3,6 +3,12 @@ export interface HttpRequest extends IncomingMessage {
|
|
|
3
3
|
params: Record<string, string>;
|
|
4
4
|
query: Record<string, string>;
|
|
5
5
|
body: any;
|
|
6
|
+
/**
|
|
7
|
+
* The request body exactly as received, before any parsing (JSON included),
|
|
8
|
+
* or null when the request carried none. What webhook signature checks
|
|
9
|
+
* (HMAC over the wire bytes) need; bounded by the same body size limits.
|
|
10
|
+
*/
|
|
11
|
+
readonly rawBody: Buffer | null;
|
|
6
12
|
path: string;
|
|
7
13
|
headers: Record<string, string>;
|
|
8
14
|
ip: string;
|
package/dist/types/http.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/types/http.ts"],"names":[],"mappings":"","sourcesContent":["// HTTP Server Types\nimport type { IncomingMessage, ServerResponse } from 'http';\n\nexport interface HttpRequest extends IncomingMessage {\n params: Record<string, string>;\n query: Record<string, string>;\n body: any;\n path: string;\n headers: Record<string, string>;\n ip: string;\n requestId: string;\n cookies?: Record<string, string>;\n /** Signed cookies whose signature verified; requires a cookie middleware secret. */\n signedCookies?: Record<string, string>;\n files?: Record<string, any>;\n\n // Per-request typed context (pass data between middlewares without monkey-patching req)\n context: Record<string, any>;\n\n // Express-compatible helpers\n get(name: string): string | undefined;\n header(name: string): string | undefined;\n is(type: string): boolean;\n accepts(types?: string | string[]): string | false;\n acceptsLanguages(langs?: string | string[]): string | false;\n hostname: string;\n protocol: string;\n secure: boolean;\n xhr: boolean;\n originalUrl: string;\n ips: string[];\n subdomains: string[];\n\n [key: string]: any;\n}\n\nexport interface CookieOptions {\n maxAge?: number;\n expires?: Date;\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: 'strict' | 'lax' | 'none';\n domain?: string;\n path?: string;\n // Security options\n signed?: boolean; // Sign the value; needs a cookie middleware secret\n critical?: boolean; // Mark as critical for security (throws on late set)\n throwOnLateSet?: boolean; // Force throw if headers already sent\n}\n\nexport interface ResponseState {\n headersSent: boolean;\n statusCode: number;\n headers: Record<string, any>;\n finished: boolean;\n writable: boolean;\n}\n\nexport interface MoroResponseMethods {\n json(data: any): void;\n status(code: number): HttpResponse;\n send(data: string | Buffer): void;\n cookie(name: string, value: string, options?: CookieOptions): HttpResponse;\n clearCookie(name: string, options?: CookieOptions): HttpResponse;\n redirect(url: string, status?: number): void;\n sendFile(filePath: string): Promise<void>;\n render?(template: string, data?: any): Promise<void>;\n\n // Per-response typed state bag (Express-compatible res.locals)\n locals: Record<string, any>;\n\n // Express-compatible response helpers\n set(\n field: string | Record<string, string | string[] | number>,\n value?: string | string[] | number\n ): HttpResponse;\n get(field: string): string | number | string[] | undefined;\n append(field: string, value: string | string[]): HttpResponse;\n type(contentType: string): HttpResponse;\n sendStatus(code: number): void;\n location(url: string): HttpResponse;\n vary(field: string | string[]): HttpResponse;\n links(links: Record<string, string>): HttpResponse;\n attachment(filename?: string): HttpResponse;\n download(filePath: string, filename?: string): Promise<void>;\n format(handlers: Record<string, () => any | Promise<any>>): void;\n\n // Header management utilities\n hasHeader(name: string): boolean;\n setBulkHeaders(headers: Record<string, string | number>): HttpResponse;\n appendHeader(name: string, value: string | string[]): HttpResponse;\n\n // Response state utilities\n canSetHeaders(): boolean;\n getResponseState(): ResponseState;\n\n // Standardized response helpers\n success<T = any>(data: T, message?: string): void;\n error(error: string, code?: string, message?: string): void;\n\n // Common HTTP error helpers (automatically set status code)\n unauthorized(message?: string): void;\n forbidden(message?: string): void;\n notFound(resource?: string): void;\n badRequest(message?: string): void;\n conflict(message: string): void;\n internalError(message?: string): void;\n validationError(errors: Array<{ field: string; message: string; code?: string }>): void;\n rateLimited(retryAfter?: number): void;\n\n // Common success patterns\n created<T = any>(data: T, location?: string): void;\n noContent(): void;\n paginated<T = any>(\n data: T[],\n pagination: {\n page: number;\n limit: number;\n total: number;\n }\n ): void;\n}\n\nexport type HttpResponse = ServerResponse & MoroResponseMethods;\n\nexport type HttpHandler = (req: HttpRequest, res: HttpResponse) => Promise<void> | void;\nexport type Middleware = (\n req: HttpRequest,\n res: HttpResponse,\n next: () => void\n) => Promise<void> | void;\nexport type MiddlewareFunction = (\n req: HttpRequest,\n res: HttpResponse,\n next: () => void\n) => void | Promise<void>;\n\n// Internal router types\nexport interface RouteEntry {\n method: string;\n path: string;\n pattern: RegExp;\n paramNames: string[];\n handler: HttpHandler;\n middleware: Middleware[];\n}\n\nexport interface RouteDefinition {\n method: string;\n path: string;\n pattern: RegExp;\n paramNames: string[];\n handler: HttpHandler;\n middleware: Middleware[];\n}\n"]}
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/types/http.ts"],"names":[],"mappings":"","sourcesContent":["// HTTP Server Types\nimport type { IncomingMessage, ServerResponse } from 'http';\n\nexport interface HttpRequest extends IncomingMessage {\n params: Record<string, string>;\n query: Record<string, string>;\n body: any;\n /**\n * The request body exactly as received, before any parsing (JSON included),\n * or null when the request carried none. What webhook signature checks\n * (HMAC over the wire bytes) need; bounded by the same body size limits.\n */\n readonly rawBody: Buffer | null;\n path: string;\n headers: Record<string, string>;\n ip: string;\n requestId: string;\n cookies?: Record<string, string>;\n /** Signed cookies whose signature verified; requires a cookie middleware secret. */\n signedCookies?: Record<string, string>;\n files?: Record<string, any>;\n\n // Per-request typed context (pass data between middlewares without monkey-patching req)\n context: Record<string, any>;\n\n // Express-compatible helpers\n get(name: string): string | undefined;\n header(name: string): string | undefined;\n is(type: string): boolean;\n accepts(types?: string | string[]): string | false;\n acceptsLanguages(langs?: string | string[]): string | false;\n hostname: string;\n protocol: string;\n secure: boolean;\n xhr: boolean;\n originalUrl: string;\n ips: string[];\n subdomains: string[];\n\n [key: string]: any;\n}\n\nexport interface CookieOptions {\n maxAge?: number;\n expires?: Date;\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: 'strict' | 'lax' | 'none';\n domain?: string;\n path?: string;\n // Security options\n signed?: boolean; // Sign the value; needs a cookie middleware secret\n critical?: boolean; // Mark as critical for security (throws on late set)\n throwOnLateSet?: boolean; // Force throw if headers already sent\n}\n\nexport interface ResponseState {\n headersSent: boolean;\n statusCode: number;\n headers: Record<string, any>;\n finished: boolean;\n writable: boolean;\n}\n\nexport interface MoroResponseMethods {\n json(data: any): void;\n status(code: number): HttpResponse;\n send(data: string | Buffer): void;\n cookie(name: string, value: string, options?: CookieOptions): HttpResponse;\n clearCookie(name: string, options?: CookieOptions): HttpResponse;\n redirect(url: string, status?: number): void;\n sendFile(filePath: string): Promise<void>;\n render?(template: string, data?: any): Promise<void>;\n\n // Per-response typed state bag (Express-compatible res.locals)\n locals: Record<string, any>;\n\n // Express-compatible response helpers\n set(\n field: string | Record<string, string | string[] | number>,\n value?: string | string[] | number\n ): HttpResponse;\n get(field: string): string | number | string[] | undefined;\n append(field: string, value: string | string[]): HttpResponse;\n type(contentType: string): HttpResponse;\n sendStatus(code: number): void;\n location(url: string): HttpResponse;\n vary(field: string | string[]): HttpResponse;\n links(links: Record<string, string>): HttpResponse;\n attachment(filename?: string): HttpResponse;\n download(filePath: string, filename?: string): Promise<void>;\n format(handlers: Record<string, () => any | Promise<any>>): void;\n\n // Header management utilities\n hasHeader(name: string): boolean;\n setBulkHeaders(headers: Record<string, string | number>): HttpResponse;\n appendHeader(name: string, value: string | string[]): HttpResponse;\n\n // Response state utilities\n canSetHeaders(): boolean;\n getResponseState(): ResponseState;\n\n // Standardized response helpers\n success<T = any>(data: T, message?: string): void;\n error(error: string, code?: string, message?: string): void;\n\n // Common HTTP error helpers (automatically set status code)\n unauthorized(message?: string): void;\n forbidden(message?: string): void;\n notFound(resource?: string): void;\n badRequest(message?: string): void;\n conflict(message: string): void;\n internalError(message?: string): void;\n validationError(errors: Array<{ field: string; message: string; code?: string }>): void;\n rateLimited(retryAfter?: number): void;\n\n // Common success patterns\n created<T = any>(data: T, location?: string): void;\n noContent(): void;\n paginated<T = any>(\n data: T[],\n pagination: {\n page: number;\n limit: number;\n total: number;\n }\n ): void;\n}\n\nexport type HttpResponse = ServerResponse & MoroResponseMethods;\n\nexport type HttpHandler = (req: HttpRequest, res: HttpResponse) => Promise<void> | void;\nexport type Middleware = (\n req: HttpRequest,\n res: HttpResponse,\n next: () => void\n) => Promise<void> | void;\nexport type MiddlewareFunction = (\n req: HttpRequest,\n res: HttpResponse,\n next: () => void\n) => void | Promise<void>;\n\n// Internal router types\nexport interface RouteEntry {\n method: string;\n path: string;\n pattern: RegExp;\n paramNames: string[];\n handler: HttpHandler;\n middleware: Middleware[];\n}\n\nexport interface RouteDefinition {\n method: string;\n path: string;\n pattern: RegExp;\n paramNames: string[];\n handler: HttpHandler;\n middleware: Middleware[];\n}\n"]}
|
package/dist/types/session.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/types/session.ts"],"names":[],"mappings":"","sourcesContent":["// Session Types\nexport interface SessionData {\n [key: string]: any;\n cookie?: {\n originalMaxAge?: number;\n expires?: Date;\n secure?: boolean;\n httpOnly?: boolean;\n sameSite?: string;\n };\n}\n\nexport interface SessionInstance {\n // Session data proxy\n [key: string]: any;\n\n // Session methods\n save(): Promise<void>;\n destroy(): Promise<void>;\n regenerate(): Promise<string>;\n touch(): Promise<void>;\n\n // Session properties\n readonly sessionID: string;\n readonly cookie?: SessionData['cookie'];\n readonly isNew?: boolean;\n readonly isModified?: boolean;\n}\n\nexport interface SessionOptions {\n // Store configuration\n store?: 'memory' | 'redis' | 'file' | any;\n storeOptions?: {\n // Redis options\n host?: string;\n port?: number;\n password?: string;\n keyPrefix?: string;\n // File options\n path?: string;\n // Memory options\n max?: number;\n };\n\n // Session configuration\n secret?: string;\n name?: string; // Session cookie name\n genid?: () => string; // Session ID generator\n rolling?: boolean; // Reset expiry on each request\n resave?: boolean; // Save session even if not modified\n saveUninitialized?: boolean; // Save new but not modified sessions\n\n // Cookie configuration\n cookie?: {\n maxAge?: number; // Session timeout in ms\n expires?: Date; // Absolute expiry\n httpOnly?: boolean; // Prevent XSS access\n secure?: boolean; // HTTPS only\n sameSite?: 'strict' | 'lax' | 'none';\n domain?: string;\n path?: string;\n };\n\n // Security\n proxy?: boolean; // Trust proxy for secure cookies\n unset?: 'destroy' | 'keep'; // What to do when session is unset\n}\n\n// Extend the HTTP request type to include session\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/no-namespace\n namespace Express {\n interface Request {\n session: SessionInstance;\n }\n }\n}\n\n// For non-Express environments\nexport interface RequestWithSession {\n session: SessionInstance;\n}\n\nexport interface SessionStore {\n get(key: string): Promise<SessionData | null>;\n set(key: string, data: SessionData, ttl?: number): Promise<void>;\n del(key: string): Promise<void>;\n clear?(): Promise<void>;\n touch?(key: string): Promise<void>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/types/session.ts"],"names":[],"mappings":"","sourcesContent":["// Session Types\nexport interface SessionData {\n [key: string]: any;\n cookie?: {\n originalMaxAge?: number;\n expires?: Date;\n secure?: boolean;\n httpOnly?: boolean;\n sameSite?: string;\n };\n}\n\nexport interface SessionInstance {\n // Session data proxy\n [key: string]: any;\n\n // Session methods\n save(): Promise<void>;\n destroy(): Promise<void>;\n regenerate(): Promise<string>;\n touch(): Promise<void>;\n\n // Session properties\n readonly sessionID: string;\n readonly cookie?: SessionData['cookie'];\n readonly isNew?: boolean;\n readonly isModified?: boolean;\n}\n\nexport interface SessionOptions {\n // Store configuration\n store?: 'memory' | 'redis' | 'file' | any;\n storeOptions?: {\n // Redis options (node-redis 4+; url wins over host/port)\n url?: string;\n host?: string;\n port?: number;\n password?: string;\n keyPrefix?: string;\n // File options\n path?: string;\n // Memory options\n max?: number;\n };\n\n // Session configuration\n secret?: string;\n name?: string; // Session cookie name\n genid?: () => string; // Session ID generator\n rolling?: boolean; // Reset expiry on each request\n resave?: boolean; // Save session even if not modified\n saveUninitialized?: boolean; // Save new but not modified sessions\n\n // Cookie configuration\n cookie?: {\n maxAge?: number; // Session timeout in ms\n expires?: Date; // Absolute expiry\n httpOnly?: boolean; // Prevent XSS access\n secure?: boolean; // HTTPS only\n sameSite?: 'strict' | 'lax' | 'none';\n domain?: string;\n path?: string;\n };\n\n // Security\n proxy?: boolean; // Trust proxy for secure cookies\n unset?: 'destroy' | 'keep'; // What to do when session is unset\n}\n\n// Extend the HTTP request type to include session\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/no-namespace\n namespace Express {\n interface Request {\n session: SessionInstance;\n }\n }\n}\n\n// For non-Express environments\nexport interface RequestWithSession {\n session: SessionInstance;\n}\n\nexport interface SessionStore {\n get(key: string): Promise<SessionData | null>;\n set(key: string, data: SessionData, ttl?: number): Promise<void>;\n del(key: string): Promise<void>;\n clear?(): Promise<void>;\n touch?(key: string): Promise<void>;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@morojs/moro",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.13",
|
|
4
4
|
"description": "High-performance Node.js framework with intelligent routing, automatic middleware ordering, enterprise authentication (Better Auth), type-safe validation, and functional architecture",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|