veloce-ts 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.
- package/CHANGELOG.md +43 -0
- package/LICENSE +21 -0
- package/README.md +442 -0
- package/bin/veloce.ts +2 -0
- package/dist/cjs/src/cli/index.js +425 -0
- package/dist/cjs/src/cli/index.js.map +22 -0
- package/dist/cjs/src/docs/index.js +7 -0
- package/dist/cjs/src/docs/index.js.map +55 -0
- package/dist/cjs/src/errors/index.js +4 -0
- package/dist/cjs/src/errors/index.js.map +12 -0
- package/dist/cjs/src/graphql/index.js +83 -0
- package/dist/cjs/src/graphql/index.js.map +24 -0
- package/dist/cjs/src/index.js +126 -0
- package/dist/cjs/src/index.js.map +108 -0
- package/dist/cjs/src/middleware/index.js +3 -0
- package/dist/cjs/src/middleware/index.js.map +12 -0
- package/dist/cjs/src/plugins/index.js +125 -0
- package/dist/cjs/src/plugins/index.js.map +67 -0
- package/dist/cjs/src/testing/index.js +17 -0
- package/dist/cjs/src/testing/index.js.map +54 -0
- package/dist/cjs/src/types/index.js +3 -0
- package/dist/cjs/src/types/index.js.map +16 -0
- package/dist/cjs/src/validation/index.js +3 -0
- package/dist/cjs/src/validation/index.js.map +19 -0
- package/dist/cjs/src/websocket/index.js +3 -0
- package/dist/cjs/src/websocket/index.js.map +12 -0
- package/dist/esm/chunk-0zxhx5b8.js +7 -0
- package/dist/esm/chunk-0zxhx5b8.js.map +10 -0
- package/dist/esm/chunk-159eqj8q.js +5 -0
- package/dist/esm/chunk-159eqj8q.js.map +12 -0
- package/dist/esm/chunk-1hqjkm44.js +5 -0
- package/dist/esm/chunk-1hqjkm44.js.map +11 -0
- package/dist/esm/chunk-2q6s8v3j.js +6 -0
- package/dist/esm/chunk-2q6s8v3j.js.map +10 -0
- package/dist/esm/chunk-42h6trpf.js +5 -0
- package/dist/esm/chunk-42h6trpf.js.map +9 -0
- package/dist/esm/chunk-82f2j0k2.js +60 -0
- package/dist/esm/chunk-82f2j0k2.js.map +10 -0
- package/dist/esm/chunk-8wrnr45g.js +338 -0
- package/dist/esm/chunk-8wrnr45g.js.map +10 -0
- package/dist/esm/chunk-9p6d0t33.js +5 -0
- package/dist/esm/chunk-9p6d0t33.js.map +10 -0
- package/dist/esm/chunk-awven6dt.js +4 -0
- package/dist/esm/chunk-awven6dt.js.map +16 -0
- package/dist/esm/chunk-gv5n8ddb.js +18 -0
- package/dist/esm/chunk-gv5n8ddb.js.map +10 -0
- package/dist/esm/chunk-pn7z890c.js +72 -0
- package/dist/esm/chunk-pn7z890c.js.map +13 -0
- package/dist/esm/chunk-qfsjy9bg.js +7 -0
- package/dist/esm/chunk-qfsjy9bg.js.map +10 -0
- package/dist/esm/chunk-vkkzgaf7.js +5 -0
- package/dist/esm/chunk-vkkzgaf7.js.map +12 -0
- package/dist/esm/src/cli/index.js +30 -0
- package/dist/esm/src/cli/index.js.map +18 -0
- package/dist/esm/src/docs/index.js +8 -0
- package/dist/esm/src/docs/index.js.map +48 -0
- package/dist/esm/src/errors/index.js +4 -0
- package/dist/esm/src/errors/index.js.map +9 -0
- package/dist/esm/src/graphql/index.js +4 -0
- package/dist/esm/src/graphql/index.js.map +9 -0
- package/dist/esm/src/index.js +4 -0
- package/dist/esm/src/index.js.map +16 -0
- package/dist/esm/src/middleware/index.js +4 -0
- package/dist/esm/src/middleware/index.js.map +9 -0
- package/dist/esm/src/plugins/index.js +42 -0
- package/dist/esm/src/plugins/index.js.map +10 -0
- package/dist/esm/src/testing/index.js +4 -0
- package/dist/esm/src/testing/index.js.map +39 -0
- package/dist/esm/src/types/index.js +4 -0
- package/dist/esm/src/types/index.js.map +9 -0
- package/dist/esm/src/validation/index.js +4 -0
- package/dist/esm/src/validation/index.js.map +9 -0
- package/dist/esm/src/websocket/index.js +4 -0
- package/dist/esm/src/websocket/index.js.map +9 -0
- package/dist/types/adapters/base.d.ts +24 -0
- package/dist/types/adapters/base.d.ts.map +1 -0
- package/dist/types/adapters/express.d.ts +44 -0
- package/dist/types/adapters/express.d.ts.map +1 -0
- package/dist/types/adapters/hono.d.ts +44 -0
- package/dist/types/adapters/hono.d.ts.map +1 -0
- package/dist/types/cli/commands/build.d.ts +3 -0
- package/dist/types/cli/commands/build.d.ts.map +1 -0
- package/dist/types/cli/commands/dev.d.ts +3 -0
- package/dist/types/cli/commands/dev.d.ts.map +1 -0
- package/dist/types/cli/commands/generate.d.ts +3 -0
- package/dist/types/cli/commands/generate.d.ts.map +1 -0
- package/dist/types/cli/commands/new.d.ts +3 -0
- package/dist/types/cli/commands/new.d.ts.map +1 -0
- package/dist/types/cli/index.d.ts +3 -0
- package/dist/types/cli/index.d.ts.map +1 -0
- package/dist/types/core/application.d.ts +268 -0
- package/dist/types/core/application.d.ts.map +1 -0
- package/dist/types/core/compiled-metadata.d.ts +58 -0
- package/dist/types/core/compiled-metadata.d.ts.map +1 -0
- package/dist/types/core/metadata.d.ts +175 -0
- package/dist/types/core/metadata.d.ts.map +1 -0
- package/dist/types/core/plugin.d.ts +63 -0
- package/dist/types/core/plugin.d.ts.map +1 -0
- package/dist/types/core/router-compiler.d.ts +61 -0
- package/dist/types/core/router-compiler.d.ts.map +1 -0
- package/dist/types/decorators/dependencies.d.ts +28 -0
- package/dist/types/decorators/dependencies.d.ts.map +1 -0
- package/dist/types/decorators/docs.d.ts +38 -0
- package/dist/types/decorators/docs.d.ts.map +1 -0
- package/dist/types/decorators/graphql.d.ts +126 -0
- package/dist/types/decorators/graphql.d.ts.map +1 -0
- package/dist/types/decorators/http.d.ts +74 -0
- package/dist/types/decorators/http.d.ts.map +1 -0
- package/dist/types/decorators/middleware.d.ts +30 -0
- package/dist/types/decorators/middleware.d.ts.map +1 -0
- package/dist/types/decorators/params.d.ts +82 -0
- package/dist/types/decorators/params.d.ts.map +1 -0
- package/dist/types/decorators/websocket.d.ts +61 -0
- package/dist/types/decorators/websocket.d.ts.map +1 -0
- package/dist/types/dependencies/container.d.ts +93 -0
- package/dist/types/dependencies/container.d.ts.map +1 -0
- package/dist/types/docs/index.d.ts +3 -0
- package/dist/types/docs/index.d.ts.map +1 -0
- package/dist/types/docs/openapi-generator.d.ts +50 -0
- package/dist/types/docs/openapi-generator.d.ts.map +1 -0
- package/dist/types/docs/zod-to-json-schema.d.ts +46 -0
- package/dist/types/docs/zod-to-json-schema.d.ts.map +1 -0
- package/dist/types/errors/exceptions.d.ts +48 -0
- package/dist/types/errors/exceptions.d.ts.map +1 -0
- package/dist/types/errors/handler.d.ts +61 -0
- package/dist/types/errors/handler.d.ts.map +1 -0
- package/dist/types/errors/index.d.ts +7 -0
- package/dist/types/errors/index.d.ts.map +1 -0
- package/dist/types/graphql/index.d.ts +4 -0
- package/dist/types/graphql/index.d.ts.map +1 -0
- package/dist/types/graphql/plugin.d.ts +60 -0
- package/dist/types/graphql/plugin.d.ts.map +1 -0
- package/dist/types/graphql/schema-builder.d.ts +46 -0
- package/dist/types/graphql/schema-builder.d.ts.map +1 -0
- package/dist/types/graphql/zod-to-graphql.d.ts +22 -0
- package/dist/types/graphql/zod-to-graphql.d.ts.map +1 -0
- package/dist/types/index.d.ts +34 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/middleware/compression.d.ts +7 -0
- package/dist/types/middleware/compression.d.ts.map +1 -0
- package/dist/types/middleware/cors.d.ts +7 -0
- package/dist/types/middleware/cors.d.ts.map +1 -0
- package/dist/types/middleware/index.d.ts +4 -0
- package/dist/types/middleware/index.d.ts.map +1 -0
- package/dist/types/middleware/rate-limit.d.ts +7 -0
- package/dist/types/middleware/rate-limit.d.ts.map +1 -0
- package/dist/types/plugins/index.d.ts +4 -0
- package/dist/types/plugins/index.d.ts.map +1 -0
- package/dist/types/plugins/openapi.d.ts +23 -0
- package/dist/types/plugins/openapi.d.ts.map +1 -0
- package/dist/types/responses/response.d.ts +200 -0
- package/dist/types/responses/response.d.ts.map +1 -0
- package/dist/types/testing/helpers.d.ts +98 -0
- package/dist/types/testing/helpers.d.ts.map +1 -0
- package/dist/types/testing/index.d.ts +4 -0
- package/dist/types/testing/index.d.ts.map +1 -0
- package/dist/types/testing/test-client.d.ts +86 -0
- package/dist/types/testing/test-client.d.ts.map +1 -0
- package/dist/types/types/index.d.ts +232 -0
- package/dist/types/types/index.d.ts.map +1 -0
- package/dist/types/validation/exceptions.d.ts +25 -0
- package/dist/types/validation/exceptions.d.ts.map +1 -0
- package/dist/types/validation/index.d.ts +3 -0
- package/dist/types/validation/index.d.ts.map +1 -0
- package/dist/types/validation/validator.d.ts +54 -0
- package/dist/types/validation/validator.d.ts.map +1 -0
- package/dist/types/websocket/connection.d.ts +51 -0
- package/dist/types/websocket/connection.d.ts.map +1 -0
- package/dist/types/websocket/index.d.ts +4 -0
- package/dist/types/websocket/index.d.ts.map +1 -0
- package/dist/types/websocket/manager.d.ts +82 -0
- package/dist/types/websocket/manager.d.ts.map +1 -0
- package/dist/types/websocket/plugin.d.ts +51 -0
- package/dist/types/websocket/plugin.d.ts.map +1 -0
- package/package.json +149 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["..\\..\\src\\websocket\\connection.ts", "..\\..\\src\\websocket\\manager.ts", "..\\..\\src\\websocket\\plugin.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"// WebSocket connection wrapper\r\nimport type { WebSocketManager } from './manager';\r\n\r\n/**\r\n * WebSocketConnection wraps a native WebSocket with helper methods\r\n * for sending messages, broadcasting, and managing rooms\r\n */\r\nexport class WebSocketConnection {\r\n public readonly id: string;\r\n private _ws: WebSocket | null;\r\n\r\n constructor(\r\n ws: WebSocket,\r\n private manager: WebSocketManager,\r\n id?: string\r\n ) {\r\n this._ws = ws;\r\n this.id = id || crypto.randomUUID();\r\n }\r\n\r\n /**\r\n * Send a message to this specific connection\r\n * @param data - Data to send (will be JSON stringified)\r\n */\r\n send(data: any): void {\r\n if (!this._ws || this._ws.readyState !== WebSocket.OPEN) {\r\n return;\r\n }\r\n\r\n const message = typeof data === 'string' ? data : JSON.stringify(data);\r\n this._ws.send(message);\r\n }\r\n\r\n /**\r\n * Broadcast a message to all connections in a room (or all connections if no room specified)\r\n * @param data - Data to broadcast\r\n * @param room - Optional room name to broadcast to\r\n */\r\n broadcast(data: any, room?: string): void {\r\n this.manager.broadcast(data, room);\r\n }\r\n\r\n /**\r\n * Join a room\r\n * @param room - Room name to join\r\n */\r\n join(room: string): void {\r\n this.manager.joinRoom(this.id, room);\r\n }\r\n\r\n /**\r\n * Leave a room\r\n * @param room - Room name to leave\r\n */\r\n leave(room: string): void {\r\n this.manager.leaveRoom(this.id, room);\r\n }\r\n\r\n /**\r\n * Close the WebSocket connection\r\n * @param code - Optional close code\r\n * @param reason - Optional close reason\r\n */\r\n close(code?: number, reason?: string): void {\r\n if (this._ws && this._ws.readyState === WebSocket.OPEN) {\r\n this._ws.close(code, reason);\r\n }\r\n }\r\n\r\n /**\r\n * Get the native WebSocket instance\r\n */\r\n get native(): WebSocket | null {\r\n return this._ws;\r\n }\r\n\r\n /**\r\n * Check if the connection is open\r\n */\r\n get isOpen(): boolean {\r\n return this._ws !== null && this._ws.readyState === WebSocket.OPEN;\r\n }\r\n\r\n /**\r\n * Internal method to mark connection as closed\r\n */\r\n _markClosed(): void {\r\n this._ws = null;\r\n }\r\n}\r\n",
|
|
6
|
+
"// WebSocket manager for connection tracking and room management\r\nimport type { WebSocketMetadata, Class } from '../types';\r\nimport { WebSocketConnection } from './connection';\r\n\r\n/**\r\n * WebSocketManager handles WebSocket connection lifecycle,\r\n * connection tracking, and room-based broadcasting\r\n */\r\nexport class WebSocketManager {\r\n private connections: Map<string, WebSocketConnection> = new Map();\r\n private rooms: Map<string, Set<string>> = new Map();\r\n private connectionsByRoom: Map<string, Set<WebSocketConnection>> = new Map();\r\n\r\n /**\r\n * Register a new WebSocket connection\r\n * @param ws - Native WebSocket instance\r\n * @param metadata - WebSocket route metadata\r\n * @returns The created WebSocketConnection\r\n */\r\n handleConnection(ws: WebSocket, metadata: WebSocketMetadata): WebSocketConnection {\r\n const connection = new WebSocketConnection(ws, this);\r\n this.connections.set(connection.id, connection);\r\n\r\n // Execute onConnect handler if defined\r\n if (metadata.onConnect) {\r\n this.executeHandler(metadata, metadata.onConnect, connection);\r\n }\r\n\r\n // Set up message handler\r\n ws.addEventListener('message', async (event) => {\r\n await this.handleMessage(event, connection, metadata);\r\n });\r\n\r\n // Set up close handler\r\n ws.addEventListener('close', () => {\r\n this.handleDisconnect(connection, metadata);\r\n });\r\n\r\n // Set up error handler\r\n ws.addEventListener('error', (error) => {\r\n console.error(`WebSocket error for connection ${connection.id}:`, error);\r\n });\r\n\r\n return connection;\r\n }\r\n\r\n /**\r\n * Handle incoming WebSocket message\r\n */\r\n private async handleMessage(\r\n event: MessageEvent,\r\n connection: WebSocketConnection,\r\n metadata: WebSocketMetadata\r\n ): Promise<void> {\r\n if (!metadata.onMessage) {\r\n return;\r\n }\r\n\r\n let data: any;\r\n\r\n try {\r\n // Parse message data\r\n data = typeof event.data === 'string' ? JSON.parse(event.data) : event.data;\r\n\r\n // Validate with schema if provided\r\n if (metadata.messageSchema) {\r\n data = await metadata.messageSchema.parseAsync(data);\r\n }\r\n\r\n // Execute onMessage handler\r\n await this.executeHandler(metadata, metadata.onMessage, connection, data);\r\n } catch (error) {\r\n // Send error back to client without closing connection\r\n connection.send({\r\n error: 'Invalid message format',\r\n details: error instanceof Error ? error.message : 'Unknown error'\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Handle WebSocket disconnection\r\n */\r\n private handleDisconnect(connection: WebSocketConnection, metadata: WebSocketMetadata): void {\r\n // Remove from all rooms\r\n Array.from(this.connectionsByRoom.entries()).forEach(([room, connections]) => {\r\n connections.delete(connection);\r\n if (connections.size === 0) {\r\n this.connectionsByRoom.delete(room);\r\n }\r\n });\r\n\r\n // Remove from rooms tracking\r\n Array.from(this.rooms.entries()).forEach(([room, connectionIds]) => {\r\n connectionIds.delete(connection.id);\r\n if (connectionIds.size === 0) {\r\n this.rooms.delete(room);\r\n }\r\n });\r\n\r\n // Remove from connections map\r\n this.connections.delete(connection.id);\r\n connection._markClosed();\r\n\r\n // Execute onDisconnect handler if defined\r\n if (metadata.onDisconnect) {\r\n this.executeHandler(metadata, metadata.onDisconnect, connection);\r\n }\r\n }\r\n\r\n /**\r\n * Execute a handler method on the target class\r\n */\r\n private async executeHandler(\r\n metadata: WebSocketMetadata,\r\n methodName: string,\r\n connection: WebSocketConnection,\r\n data?: any\r\n ): Promise<void> {\r\n try {\r\n const instance = new metadata.target();\r\n const method = (instance as any)[methodName];\r\n\r\n if (typeof method === 'function') {\r\n if (data !== undefined) {\r\n await method.call(instance, connection, data);\r\n } else {\r\n await method.call(instance, connection);\r\n }\r\n }\r\n } catch (error) {\r\n console.error(`Error executing WebSocket handler ${methodName}:`, error);\r\n }\r\n }\r\n\r\n /**\r\n * Broadcast a message to all connections or connections in a specific room\r\n * @param message - Message to broadcast\r\n * @param room - Optional room name\r\n */\r\n broadcast(message: any, room?: string): void {\r\n const connections = room\r\n ? this.getConnectionsInRoom(room)\r\n : Array.from(this.connections.values());\r\n\r\n const data = typeof message === 'string' ? message : JSON.stringify(message);\r\n\r\n for (const connection of connections) {\r\n if (connection.isOpen) {\r\n connection.send(data);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Add a connection to a room\r\n * @param connectionId - Connection ID\r\n * @param room - Room name\r\n */\r\n joinRoom(connectionId: string, room: string): void {\r\n const connection = this.connections.get(connectionId);\r\n if (!connection) {\r\n return;\r\n }\r\n\r\n // Add to rooms map (connectionId -> room)\r\n if (!this.rooms.has(room)) {\r\n this.rooms.set(room, new Set());\r\n }\r\n this.rooms.get(room)!.add(connectionId);\r\n\r\n // Add to connectionsByRoom map (room -> connections)\r\n if (!this.connectionsByRoom.has(room)) {\r\n this.connectionsByRoom.set(room, new Set());\r\n }\r\n this.connectionsByRoom.get(room)!.add(connection);\r\n }\r\n\r\n /**\r\n * Remove a connection from a room\r\n * @param connectionId - Connection ID\r\n * @param room - Room name\r\n */\r\n leaveRoom(connectionId: string, room: string): void {\r\n const connection = this.connections.get(connectionId);\r\n if (!connection) {\r\n return;\r\n }\r\n\r\n // Remove from rooms map\r\n const roomConnections = this.rooms.get(room);\r\n if (roomConnections) {\r\n roomConnections.delete(connectionId);\r\n if (roomConnections.size === 0) {\r\n this.rooms.delete(room);\r\n }\r\n }\r\n\r\n // Remove from connectionsByRoom map\r\n const connections = this.connectionsByRoom.get(room);\r\n if (connections) {\r\n connections.delete(connection);\r\n if (connections.size === 0) {\r\n this.connectionsByRoom.delete(room);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get all connections in a specific room\r\n * @param room - Room name\r\n * @returns Array of connections in the room\r\n */\r\n private getConnectionsInRoom(room: string): WebSocketConnection[] {\r\n const connections = this.connectionsByRoom.get(room);\r\n return connections ? Array.from(connections) : [];\r\n }\r\n\r\n /**\r\n * Get a connection by ID\r\n * @param connectionId - Connection ID\r\n * @returns The connection or undefined\r\n */\r\n getConnection(connectionId: string): WebSocketConnection | undefined {\r\n return this.connections.get(connectionId);\r\n }\r\n\r\n /**\r\n * Get all active connections\r\n * @returns Array of all connections\r\n */\r\n getAllConnections(): WebSocketConnection[] {\r\n return Array.from(this.connections.values());\r\n }\r\n\r\n /**\r\n * Get the number of active connections\r\n * @returns Number of connections\r\n */\r\n getConnectionCount(): number {\r\n return this.connections.size;\r\n }\r\n\r\n /**\r\n * Get all room names\r\n * @returns Array of room names\r\n */\r\n getRooms(): string[] {\r\n return Array.from(this.rooms.keys());\r\n }\r\n\r\n /**\r\n * Get the number of connections in a room\r\n * @param room - Room name\r\n * @returns Number of connections in the room\r\n */\r\n getRoomSize(room: string): number {\r\n return this.rooms.get(room)?.size || 0;\r\n }\r\n}\r\n",
|
|
7
|
+
"// WebSocket Plugin\r\nimport type { Plugin } from '../core/plugin';\r\nimport type { VeloceTS } from '../core/application';\r\nimport { WebSocketManager } from './manager';\r\n\r\n/**\r\n * WebSocketPlugin adds WebSocket support to FastAPI-TS\r\n * Registers WebSocket routes and handles connection upgrades\r\n */\r\nexport class WebSocketPlugin implements Plugin {\r\n name = 'websocket';\r\n version = '1.0.0';\r\n\r\n private manager: WebSocketManager;\r\n\r\n constructor() {\r\n this.manager = new WebSocketManager();\r\n }\r\n\r\n async install(app: VeloceTS): Promise<void> {\r\n const metadata = app.getMetadata();\r\n const websockets = metadata.getWebSockets();\r\n\r\n // Register each WebSocket handler\r\n for (const ws of websockets) {\r\n this.registerWebSocket(app, ws);\r\n }\r\n }\r\n\r\n /**\r\n * Register a WebSocket route with the application\r\n */\r\n private registerWebSocket(app: VeloceTS, metadata: any): void {\r\n const hono = app.getHono();\r\n\r\n // Register WebSocket upgrade endpoint\r\n hono.get(metadata.path, async (c) => {\r\n // Check if this is a WebSocket upgrade request\r\n const upgrade = c.req.header('upgrade');\r\n \r\n if (upgrade?.toLowerCase() !== 'websocket') {\r\n return c.text('Expected WebSocket upgrade', 426);\r\n }\r\n\r\n // Handle WebSocket upgrade based on runtime\r\n return this.handleUpgrade(c, metadata);\r\n });\r\n }\r\n\r\n /**\r\n * Handle WebSocket upgrade for different runtimes\r\n */\r\n private handleUpgrade(c: any, metadata: any): Response {\r\n // Detect runtime and handle accordingly\r\n if (typeof Bun !== 'undefined') {\r\n return this.handleBunUpgrade(c, metadata);\r\n } else if (typeof (globalThis as any).Deno !== 'undefined') {\r\n return this.handleDenoUpgrade(c, metadata);\r\n } else {\r\n // Node.js or other runtimes\r\n return this.handleNodeUpgrade(c, metadata);\r\n }\r\n }\r\n\r\n /**\r\n * Handle WebSocket upgrade for Bun runtime\r\n */\r\n private handleBunUpgrade(c: any, metadata: any): Response {\r\n const success = (c.env as any)?.upgrade?.(c.req.raw);\r\n \r\n if (!success) {\r\n return c.text('WebSocket upgrade failed', 500);\r\n }\r\n\r\n return new Response(null, { status: 101 });\r\n }\r\n\r\n /**\r\n * Handle WebSocket upgrade for Deno runtime\r\n */\r\n private handleDenoUpgrade(c: any, metadata: any): Response {\r\n const Deno = (globalThis as any).Deno;\r\n const { socket, response } = Deno.upgradeWebSocket(c.req.raw);\r\n \r\n // Set up WebSocket handlers\r\n socket.onopen = () => {\r\n this.manager.handleConnection(socket as any, metadata);\r\n };\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Handle WebSocket upgrade for Node.js runtime\r\n */\r\n private handleNodeUpgrade(c: any, metadata: any): Response {\r\n // For Node.js, we need to handle this differently\r\n // This is a simplified version - in production, you'd use a library like 'ws'\r\n return c.text('WebSocket support requires Bun or Deno runtime', 501);\r\n }\r\n\r\n /**\r\n * Get the WebSocket manager instance\r\n */\r\n getManager(): WebSocketManager {\r\n return this.manager;\r\n }\r\n\r\n /**\r\n * Broadcast a message to all connections or a specific room\r\n */\r\n broadcast(message: any, room?: string): void {\r\n this.manager.broadcast(message, room);\r\n }\r\n\r\n /**\r\n * Get connection count\r\n */\r\n getConnectionCount(): number {\r\n return this.manager.getConnectionCount();\r\n }\r\n\r\n /**\r\n * Get all active rooms\r\n */\r\n getRooms(): string[] {\r\n return this.manager.getRooms();\r\n }\r\n}\r\n"
|
|
8
|
+
],
|
|
9
|
+
"mappings": "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",
|
|
10
|
+
"debugId": "1A24372540374BEE64756E2164756E21",
|
|
11
|
+
"names": []
|
|
12
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import"./chunk-42h6trpf.js";import{existsSync as c}from"fs";import{join as u}from"path";import{rm as m,mkdir as l}from"fs/promises";function B(e){e.command("build").description("Build project for production").option("-m, --minify","Minify output",!1).option("-s, --sourcemap","Generate sourcemaps",!0).option("-o, --outdir <dir>","Output directory","dist").option("-f, --format <format>","Output format (esm, cjs, both)","both").action(async(i)=>{await f(i)})}async function f(e){let i=u(process.cwd(),"src","index.ts");if(!c(i))console.error("Error: src/index.ts not found"),console.error("Make sure you are in a VeloceTS project directory"),process.exit(1);console.log("Building project for production..."),console.log(`Format: ${e.format||"both"}`),console.log(`Minify: ${e.minify?"yes":"no"}`),console.log(`Sourcemap: ${e.sourcemap?"yes":"no"}`);let o=e.outdir||"dist";try{if(c(o))await m(o,{recursive:!0,force:!0});await l(o,{recursive:!0});let t=e.format||"both",s=t==="both"?["esm","cjs"]:[t];for(let r of s)console.log(`
|
|
3
|
+
Building ${r.toUpperCase()}...`),await p(i,o,r,e);console.log(`
|
|
4
|
+
\u2713 Build completed successfully!`),console.log(`
|
|
5
|
+
Output directory: ${o}`)}catch(t){console.error("Build failed:",t),process.exit(1)}}async function p(e,i,o,t){let s=u(i,o);await l(s,{recursive:!0});let r=await Bun.build({entrypoints:[e],outdir:s,target:"bun",format:o==="esm"?"esm":"cjs",minify:t.minify||!1,sourcemap:t.sourcemap!==!1?"external":"none",splitting:o==="esm",external:["hono","zod","reflect-metadata","commander","zod-to-json-schema"]});if(!r.success){console.error(`Failed to build ${o}:`);for(let n of r.logs)console.error(n);throw Error(`Build failed for ${o}`)}console.log(` \u2713 ${o.toUpperCase()} build complete`),console.log(` Files: ${r.outputs.length}`);let a=r.outputs.reduce((n,d)=>n+d.size,0);console.log(` Size: ${(a/1024).toFixed(2)} KB`)}export{B as registerBuildCommand};
|
|
6
|
+
|
|
7
|
+
//# debugId=77FE8158DC8EB3FF64756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["..\\..\\src\\cli\\commands\\build.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { Command } from 'commander';\r\nimport { existsSync } from 'fs';\r\nimport { join } from 'path';\r\nimport { rm, mkdir } from 'fs/promises';\r\n\r\ninterface BuildOptions {\r\n minify?: boolean;\r\n sourcemap?: boolean;\r\n outdir?: string;\r\n format?: 'esm' | 'cjs' | 'both';\r\n}\r\n\r\nexport function registerBuildCommand(program: Command): void {\r\n program\r\n .command('build')\r\n .description('Build project for production')\r\n .option('-m, --minify', 'Minify output', false)\r\n .option('-s, --sourcemap', 'Generate sourcemaps', true)\r\n .option('-o, --outdir <dir>', 'Output directory', 'dist')\r\n .option('-f, --format <format>', 'Output format (esm, cjs, both)', 'both')\r\n .action(async (options: BuildOptions) => {\r\n await buildProject(options);\r\n });\r\n}\r\n\r\nasync function buildProject(options: BuildOptions): Promise<void> {\r\n const entryPoint = join(process.cwd(), 'src', 'index.ts');\r\n\r\n // Check if entry point exists\r\n if (!existsSync(entryPoint)) {\r\n console.error('Error: src/index.ts not found');\r\n console.error('Make sure you are in a VeloceTS project directory');\r\n process.exit(1);\r\n }\r\n\r\n console.log('Building project for production...');\r\n console.log(`Format: ${options.format || 'both'}`);\r\n console.log(`Minify: ${options.minify ? 'yes' : 'no'}`);\r\n console.log(`Sourcemap: ${options.sourcemap ? 'yes' : 'no'}`);\r\n\r\n const outdir = options.outdir || 'dist';\r\n\r\n try {\r\n // Clean output directory\r\n if (existsSync(outdir)) {\r\n await rm(outdir, { recursive: true, force: true });\r\n }\r\n await mkdir(outdir, { recursive: true });\r\n\r\n const format = options.format || 'both';\r\n const formats = format === 'both' ? ['esm', 'cjs'] : [format];\r\n\r\n for (const fmt of formats) {\r\n console.log(`\\nBuilding ${fmt.toUpperCase()}...`);\r\n await buildFormat(entryPoint, outdir, fmt as 'esm' | 'cjs', options);\r\n }\r\n\r\n console.log('\\n✓ Build completed successfully!');\r\n console.log(`\\nOutput directory: ${outdir}`);\r\n } catch (error) {\r\n console.error('Build failed:', error);\r\n process.exit(1);\r\n }\r\n}\r\n\r\nasync function buildFormat(\r\n entryPoint: string,\r\n outdir: string,\r\n format: 'esm' | 'cjs',\r\n options: BuildOptions\r\n): Promise<void> {\r\n const outputDir = join(outdir, format);\r\n await mkdir(outputDir, { recursive: true });\r\n\r\n const buildResult = await Bun.build({\r\n entrypoints: [entryPoint],\r\n outdir: outputDir,\r\n target: 'bun',\r\n format: format === 'esm' ? 'esm' : 'cjs',\r\n minify: options.minify || false,\r\n sourcemap: options.sourcemap !== false ? 'external' : 'none',\r\n splitting: format === 'esm',\r\n external: [\r\n 'hono',\r\n 'zod',\r\n 'reflect-metadata',\r\n 'commander',\r\n 'zod-to-json-schema',\r\n ],\r\n });\r\n\r\n if (!buildResult.success) {\r\n console.error(`Failed to build ${format}:`);\r\n for (const log of buildResult.logs) {\r\n console.error(log);\r\n }\r\n throw new Error(`Build failed for ${format}`);\r\n }\r\n\r\n console.log(` ✓ ${format.toUpperCase()} build complete`);\r\n console.log(` Files: ${buildResult.outputs.length}`);\r\n \r\n const totalSize = buildResult.outputs.reduce((sum, output) => sum + output.size, 0);\r\n console.log(` Size: ${(totalSize / 1024).toFixed(2)} KB`);\r\n}\r\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";4BACA,qBAAS,WACT,eAAS,aACT,aAAS,WAAI,oBASN,SAAS,CAAoB,CAAC,EAAwB,CAC3D,EACG,QAAQ,OAAO,EACf,YAAY,8BAA8B,EAC1C,OAAO,eAAgB,gBAAiB,EAAK,EAC7C,OAAO,kBAAmB,sBAAuB,EAAI,EACrD,OAAO,qBAAsB,mBAAoB,MAAM,EACvD,OAAO,wBAAyB,iCAAkC,MAAM,EACxE,OAAO,MAAO,IAA0B,CACvC,MAAM,EAAa,CAAO,EAC3B,EAGL,eAAe,CAAY,CAAC,EAAsC,CAChE,IAAM,EAAa,EAAK,QAAQ,IAAI,EAAG,MAAO,UAAU,EAGxD,GAAI,CAAC,EAAW,CAAU,EACxB,QAAQ,MAAM,+BAA+B,EAC7C,QAAQ,MAAM,mDAAmD,EACjE,QAAQ,KAAK,CAAC,EAGhB,QAAQ,IAAI,oCAAoC,EAChD,QAAQ,IAAI,WAAW,EAAQ,QAAU,QAAQ,EACjD,QAAQ,IAAI,WAAW,EAAQ,OAAS,MAAQ,MAAM,EACtD,QAAQ,IAAI,cAAc,EAAQ,UAAY,MAAQ,MAAM,EAE5D,IAAM,EAAS,EAAQ,QAAU,OAEjC,GAAI,CAEF,GAAI,EAAW,CAAM,EACnB,MAAM,EAAG,EAAQ,CAAE,UAAW,GAAM,MAAO,EAAK,CAAC,EAEnD,MAAM,EAAM,EAAQ,CAAE,UAAW,EAAK,CAAC,EAEvC,IAAM,EAAS,EAAQ,QAAU,OAC3B,EAAU,IAAW,OAAS,CAAC,MAAO,KAAK,EAAI,CAAC,CAAM,EAE5D,QAAW,KAAO,EAChB,QAAQ,IAAI;AAAA,WAAc,EAAI,YAAY,MAAM,EAChD,MAAM,EAAY,EAAY,EAAQ,EAAsB,CAAO,EAGrE,QAAQ,IAAI;AAAA,qCAAkC,EAC9C,QAAQ,IAAI;AAAA,oBAAuB,GAAQ,EAC3C,MAAO,EAAO,CACd,QAAQ,MAAM,gBAAiB,CAAK,EACpC,QAAQ,KAAK,CAAC,GAIlB,eAAe,CAAW,CACxB,EACA,EACA,EACA,EACe,CACf,IAAM,EAAY,EAAK,EAAQ,CAAM,EACrC,MAAM,EAAM,EAAW,CAAE,UAAW,EAAK,CAAC,EAE1C,IAAM,EAAc,MAAM,IAAI,MAAM,CAClC,YAAa,CAAC,CAAU,EACxB,OAAQ,EACR,OAAQ,MACR,OAAQ,IAAW,MAAQ,MAAQ,MACnC,OAAQ,EAAQ,QAAU,GAC1B,UAAW,EAAQ,YAAc,GAAQ,WAAa,OACtD,UAAW,IAAW,MACtB,SAAU,CACR,OACA,MACA,mBACA,YACA,oBACF,CACF,CAAC,EAED,GAAI,CAAC,EAAY,QAAS,CACxB,QAAQ,MAAM,mBAAmB,IAAS,EAC1C,QAAW,KAAO,EAAY,KAC5B,QAAQ,MAAM,CAAG,EAEnB,MAAU,MAAM,oBAAoB,GAAQ,EAG9C,QAAQ,IAAI,YAAM,EAAO,YAAY,kBAAkB,EACvD,QAAQ,IAAI,cAAc,EAAY,QAAQ,QAAQ,EAEtD,IAAM,EAAY,EAAY,QAAQ,OAAO,CAAC,EAAK,IAAW,EAAM,EAAO,KAAM,CAAC,EAClF,QAAQ,IAAI,cAAc,EAAY,MAAM,QAAQ,CAAC,MAAM",
|
|
8
|
+
"debugId": "77FE8158DC8EB3FF64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
function E($){let{origin:F="*",methods:Q=["GET","POST","PUT","DELETE","PATCH","OPTIONS"],allowedHeaders:Z=["Content-Type","Authorization"],exposedHeaders:S=[],credentials:K=!1,maxAge:j=86400}=$||{};return async(z,U)=>{let N=z.req.header("origin"),P=z.req.method,B=null;if(typeof F==="string")B=F;else if(Array.isArray(F)){if(N&&F.includes(N))B=N}else if(typeof F==="function"){if(N&&F(N))B=N}if(B)z.header("Access-Control-Allow-Origin",B);if(K)z.header("Access-Control-Allow-Credentials","true");if(S.length>0)z.header("Access-Control-Expose-Headers",S.join(", "));if(P==="OPTIONS")return z.header("Access-Control-Allow-Methods",Q.join(", ")),z.header("Access-Control-Allow-Headers",Z.join(", ")),z.header("Access-Control-Max-Age",j.toString()),z.body(null,204);await U()}}function v($){let{windowMs:F=60000,max:Q=100,keyGenerator:Z=(j)=>{return j.req.header("x-forwarded-for")||j.req.header("x-real-ip")||"unknown"}}=$,S=new Map,K=setInterval(()=>{let j=Date.now();for(let[z,U]of S.entries())if(j>U.resetTime)S.delete(z)},F);if(typeof process<"u"&&process.on)process.on("exit",()=>clearInterval(K));return async(j,z)=>{let U=Z(j),N=Date.now(),P=S.get(U);if(!P||N>P.resetTime)S.set(U,{count:1,resetTime:N+F}),j.header("X-RateLimit-Limit",Q.toString()),j.header("X-RateLimit-Remaining",(Q-1).toString()),j.header("X-RateLimit-Reset",new Date(N+F).toISOString()),await z();else if(P.count<Q)P.count++,j.header("X-RateLimit-Limit",Q.toString()),j.header("X-RateLimit-Remaining",(Q-P.count).toString()),j.header("X-RateLimit-Reset",new Date(P.resetTime).toISOString()),await z();else{let B=Math.ceil((P.resetTime-N)/1000);return j.header("X-RateLimit-Limit",Q.toString()),j.header("X-RateLimit-Remaining","0"),j.header("X-RateLimit-Reset",new Date(P.resetTime).toISOString()),j.header("Retry-After",B.toString()),j.json({error:"Too Many Requests",message:`Rate limit exceeded. Please try again in ${B} seconds.`,retryAfter:B},429)}}}function L($){let{threshold:F=1024,level:Q=6}=$||{};return async(Z,S)=>{await S();let K=Z.res;if(!K)return;let j=K.headers.get("content-type")||"",z=K.headers.get("content-length"),U=Z.req.header("accept-encoding")||"";if(!["text/","application/json","application/javascript","application/xml","application/x-www-form-urlencoded"].some((D)=>j.toLowerCase().includes(D)))return;if(z&&parseInt(z)<F)return;if(K.headers.get("content-encoding"))return;let B=await K.arrayBuffer();if(B.byteLength<F)return;let V=null,R=null;if(U.includes("br")&&typeof CompressionStream<"u")try{let D=new CompressionStream("deflate"),_=D.writable.getWriter();_.write(new Uint8Array(B)),_.close();let T=D.readable.getReader(),X=[];while(!0){let{done:J,value:Y}=await T.read();if(J)break;X.push(Y)}let W=X.reduce((J,Y)=>J+Y.length,0),C=new Uint8Array(W),G=0;for(let J of X)C.set(J,G),G+=J.length;V=C,R="deflate"}catch(D){V=null}if(!V&&U.includes("gzip")&&typeof CompressionStream<"u")try{let D=new CompressionStream("gzip"),_=D.writable.getWriter();_.write(new Uint8Array(B)),_.close();let T=D.readable.getReader(),X=[];while(!0){let{done:J,value:Y}=await T.read();if(J)break;X.push(Y)}let W=X.reduce((J,Y)=>J+Y.length,0),C=new Uint8Array(W),G=0;for(let J of X)C.set(J,G),G+=J.length;V=C,R="gzip"}catch(D){V=null}if(V&&R&&V.byteLength<B.byteLength){let D=new Headers(K.headers);return D.set("content-encoding",R),D.set("content-length",V.byteLength.toString()),D.delete("content-length"),new Response(V,{status:K.status,statusText:K.statusText,headers:D})}}}
|
|
3
|
+
export{E as z,v as A,L as B};
|
|
4
|
+
|
|
5
|
+
//# debugId=1A2F93BE4868418064756E2164756E21
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["..\\..\\src\\middleware\\cors.ts", "..\\..\\src\\middleware\\rate-limit.ts", "..\\..\\src\\middleware\\compression.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { Context, Middleware, CorsOptions } from '../types';\r\n\r\n/**\r\n * Create CORS middleware with configurable options\r\n * Handles preflight requests and adds appropriate CORS headers\r\n */\r\nexport function createCorsMiddleware(options?: CorsOptions): Middleware {\r\n const {\r\n origin = '*',\r\n methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],\r\n allowedHeaders = ['Content-Type', 'Authorization'],\r\n exposedHeaders = [],\r\n credentials = false,\r\n maxAge = 86400 // 24 hours default\r\n } = options || {};\r\n\r\n return async (c: Context, next) => {\r\n const requestOrigin = c.req.header('origin');\r\n const requestMethod = c.req.method;\r\n\r\n // Determine if origin is allowed\r\n let allowedOrigin: string | null = null;\r\n\r\n if (typeof origin === 'string') {\r\n allowedOrigin = origin;\r\n } else if (Array.isArray(origin)) {\r\n if (requestOrigin && origin.includes(requestOrigin)) {\r\n allowedOrigin = requestOrigin;\r\n }\r\n } else if (typeof origin === 'function') {\r\n if (requestOrigin && origin(requestOrigin)) {\r\n allowedOrigin = requestOrigin;\r\n }\r\n }\r\n\r\n // Set CORS headers\r\n if (allowedOrigin) {\r\n c.header('Access-Control-Allow-Origin', allowedOrigin);\r\n }\r\n\r\n if (credentials) {\r\n c.header('Access-Control-Allow-Credentials', 'true');\r\n }\r\n\r\n if (exposedHeaders.length > 0) {\r\n c.header('Access-Control-Expose-Headers', exposedHeaders.join(', '));\r\n }\r\n\r\n // Handle preflight requests\r\n if (requestMethod === 'OPTIONS') {\r\n c.header('Access-Control-Allow-Methods', methods.join(', '));\r\n c.header('Access-Control-Allow-Headers', allowedHeaders.join(', '));\r\n c.header('Access-Control-Max-Age', maxAge.toString());\r\n \r\n return c.body(null, 204);\r\n }\r\n\r\n // Continue to next middleware/handler\r\n await next();\r\n };\r\n}\r\n",
|
|
6
|
+
"import type { Context, Middleware, RateLimitOptions } from '../types';\r\n\r\n/**\r\n * Rate limit record for tracking requests\r\n */\r\ninterface RateLimitRecord {\r\n count: number;\r\n resetTime: number;\r\n}\r\n\r\n/**\r\n * Create rate limiting middleware\r\n * Tracks requests per IP/key and returns 429 when limit exceeded\r\n */\r\nexport function createRateLimitMiddleware(options: RateLimitOptions): Middleware {\r\n const {\r\n windowMs = 60000, // 1 minute default\r\n max = 100, // 100 requests per window default\r\n keyGenerator = (c: Context) => {\r\n // Default: use X-Forwarded-For header or fallback to 'unknown'\r\n return c.req.header('x-forwarded-for') || \r\n c.req.header('x-real-ip') || \r\n 'unknown';\r\n }\r\n } = options;\r\n\r\n // In-memory storage for rate limit records\r\n const requests = new Map<string, RateLimitRecord>();\r\n\r\n // Cleanup old entries periodically to prevent memory leaks\r\n const cleanupInterval = setInterval(() => {\r\n const now = Date.now();\r\n for (const [key, record] of requests.entries()) {\r\n if (now > record.resetTime) {\r\n requests.delete(key);\r\n }\r\n }\r\n }, windowMs);\r\n\r\n // Cleanup on process exit (if supported)\r\n if (typeof process !== 'undefined' && process.on) {\r\n process.on('exit', () => clearInterval(cleanupInterval));\r\n }\r\n\r\n return async (c: Context, next) => {\r\n const key = keyGenerator(c);\r\n const now = Date.now();\r\n const record = requests.get(key);\r\n\r\n if (!record || now > record.resetTime) {\r\n // New window - reset counter\r\n requests.set(key, { \r\n count: 1, \r\n resetTime: now + windowMs \r\n });\r\n\r\n // Add rate limit headers\r\n c.header('X-RateLimit-Limit', max.toString());\r\n c.header('X-RateLimit-Remaining', (max - 1).toString());\r\n c.header('X-RateLimit-Reset', new Date(now + windowMs).toISOString());\r\n\r\n await next();\r\n } else if (record.count < max) {\r\n // Within limit - increment counter\r\n record.count++;\r\n\r\n // Add rate limit headers\r\n c.header('X-RateLimit-Limit', max.toString());\r\n c.header('X-RateLimit-Remaining', (max - record.count).toString());\r\n c.header('X-RateLimit-Reset', new Date(record.resetTime).toISOString());\r\n\r\n await next();\r\n } else {\r\n // Rate limit exceeded\r\n const retryAfter = Math.ceil((record.resetTime - now) / 1000);\r\n\r\n c.header('X-RateLimit-Limit', max.toString());\r\n c.header('X-RateLimit-Remaining', '0');\r\n c.header('X-RateLimit-Reset', new Date(record.resetTime).toISOString());\r\n c.header('Retry-After', retryAfter.toString());\r\n\r\n return c.json(\r\n {\r\n error: 'Too Many Requests',\r\n message: `Rate limit exceeded. Please try again in ${retryAfter} seconds.`,\r\n retryAfter\r\n },\r\n 429\r\n );\r\n }\r\n };\r\n}\r\n",
|
|
7
|
+
"import type { Context, Middleware, CompressionOptions } from '../types';\r\n\r\n/**\r\n * Create compression middleware\r\n * Compresses responses with gzip or brotli based on Accept-Encoding header\r\n */\r\nexport function createCompressionMiddleware(options?: CompressionOptions): Middleware {\r\n const {\r\n threshold = 1024, // Only compress responses larger than 1KB\r\n level = 6 // Compression level (1-9 for gzip, 0-11 for brotli)\r\n } = options || {};\r\n\r\n return async (c: Context, next) => {\r\n // Continue to next middleware/handler first\r\n await next();\r\n\r\n // Get the response\r\n const response = c.res;\r\n if (!response) {\r\n return;\r\n }\r\n\r\n // Check if response should be compressed\r\n const contentType = response.headers.get('content-type') || '';\r\n const contentLength = response.headers.get('content-length');\r\n const acceptEncoding = c.req.header('accept-encoding') || '';\r\n\r\n // Skip compression for certain content types\r\n const compressibleTypes = [\r\n 'text/',\r\n 'application/json',\r\n 'application/javascript',\r\n 'application/xml',\r\n 'application/x-www-form-urlencoded'\r\n ];\r\n\r\n const isCompressible = compressibleTypes.some(type => \r\n contentType.toLowerCase().includes(type)\r\n );\r\n\r\n if (!isCompressible) {\r\n return;\r\n }\r\n\r\n // Skip if response is too small\r\n if (contentLength && parseInt(contentLength) < threshold) {\r\n return;\r\n }\r\n\r\n // Skip if already encoded\r\n if (response.headers.get('content-encoding')) {\r\n return;\r\n }\r\n\r\n // Get response body\r\n const body = await response.arrayBuffer();\r\n \r\n // Skip if body is too small\r\n if (body.byteLength < threshold) {\r\n return;\r\n }\r\n\r\n // Determine compression method\r\n let compressed: Uint8Array | null = null;\r\n let encoding: string | null = null;\r\n\r\n // Try brotli first (better compression)\r\n if (acceptEncoding.includes('br') && typeof CompressionStream !== 'undefined') {\r\n try {\r\n const stream = new CompressionStream('deflate');\r\n const writer = stream.writable.getWriter();\r\n writer.write(new Uint8Array(body));\r\n writer.close();\r\n \r\n const reader = stream.readable.getReader();\r\n const chunks: Uint8Array[] = [];\r\n \r\n while (true) {\r\n const { done, value } = await reader.read();\r\n if (done) break;\r\n chunks.push(value);\r\n }\r\n \r\n const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);\r\n const result = new Uint8Array(totalLength);\r\n let offset = 0;\r\n for (const chunk of chunks) {\r\n result.set(chunk, offset);\r\n offset += chunk.length;\r\n }\r\n \r\n compressed = result;\r\n encoding = 'deflate';\r\n } catch (error) {\r\n // Fallback to gzip\r\n compressed = null;\r\n }\r\n }\r\n\r\n // Try gzip if brotli not available or failed\r\n if (!compressed && acceptEncoding.includes('gzip') && typeof CompressionStream !== 'undefined') {\r\n try {\r\n const stream = new CompressionStream('gzip');\r\n const writer = stream.writable.getWriter();\r\n writer.write(new Uint8Array(body));\r\n writer.close();\r\n \r\n const reader = stream.readable.getReader();\r\n const chunks: Uint8Array[] = [];\r\n \r\n while (true) {\r\n const { done, value } = await reader.read();\r\n if (done) break;\r\n chunks.push(value);\r\n }\r\n \r\n const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);\r\n const result = new Uint8Array(totalLength);\r\n let offset = 0;\r\n for (const chunk of chunks) {\r\n result.set(chunk, offset);\r\n offset += chunk.length;\r\n }\r\n \r\n compressed = result;\r\n encoding = 'gzip';\r\n } catch (error) {\r\n // Compression failed, use original\r\n compressed = null;\r\n }\r\n }\r\n\r\n // If compression succeeded and resulted in smaller size, use it\r\n if (compressed && encoding && compressed.byteLength < body.byteLength) {\r\n // Create new response with compressed body\r\n const headers = new Headers(response.headers);\r\n headers.set('content-encoding', encoding);\r\n headers.set('content-length', compressed.byteLength.toString());\r\n headers.delete('content-length'); // Let the runtime set it\r\n \r\n // Update the response\r\n const newResponse = new Response(compressed, {\r\n status: response.status,\r\n statusText: response.statusText,\r\n headers\r\n });\r\n\r\n // Replace the response in context\r\n // Note: This is a workaround since Hono's context doesn't allow direct response replacement\r\n // In practice, this middleware should be used with Hono's compress middleware\r\n return newResponse;\r\n }\r\n };\r\n}\r\n"
|
|
8
|
+
],
|
|
9
|
+
"mappings": "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",
|
|
10
|
+
"debugId": "1A2F93BE4868418064756E2164756E21",
|
|
11
|
+
"names": []
|
|
12
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
class D extends Error{statusCode;details;constructor(k,A,M){super(A);this.statusCode=k;this.details=M;if(this.name="HTTPException",Error.captureStackTrace)Error.captureStackTrace(this,this.constructor)}toJSON(){return{error:this.message,statusCode:this.statusCode,...this.details&&{details:this.details}}}}class F extends D{constructor(k="Not Found",A){super(404,k,A);this.name="NotFoundException"}toJSON(){return{error:this.message,statusCode:this.statusCode,...this.details&&{details:this.details}}}}class G extends D{constructor(k="Unauthorized",A){super(401,k,A);this.name="UnauthorizedException"}toJSON(){return{error:this.message,statusCode:this.statusCode,...this.details&&{details:this.details}}}}class I extends D{constructor(k="Forbidden",A){super(403,k,A);this.name="ForbiddenException"}toJSON(){return{error:this.message,statusCode:this.statusCode,...this.details&&{details:this.details}}}}class K extends D{constructor(k="Bad Request",A){super(400,k,A);this.name="BadRequestException"}toJSON(){return{error:this.message,statusCode:this.statusCode,...this.details&&{details:this.details}}}}class L extends D{zodError;constructor(k){super(422,"Validation failed");this.zodError=k;this.name="ValidationException"}toJSON(){return{error:"Validation Error",statusCode:this.statusCode,details:this.zodError.errors.map((k)=>({path:k.path.join("."),message:k.message,code:k.code}))}}}
|
|
3
|
+
export{D as $,F as aa,G as ba,I as ca,K as da,L as ea};
|
|
4
|
+
|
|
5
|
+
//# debugId=BE2ADDBCCA736E5064756E2164756E21
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["..\\..\\src\\errors\\exceptions.ts", "..\\..\\src\\validation\\exceptions.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\r\n * Base HTTP exception class\r\n * All HTTP exceptions should extend this class\r\n * Provides consistent error response format\r\n */\r\nexport class HTTPException extends Error {\r\n constructor(\r\n public statusCode: number,\r\n message: string,\r\n public details?: any\r\n ) {\r\n super(message);\r\n this.name = 'HTTPException';\r\n \r\n // Maintains proper stack trace for where error was thrown (V8 only)\r\n if (Error.captureStackTrace) {\r\n Error.captureStackTrace(this, this.constructor);\r\n }\r\n }\r\n\r\n /**\r\n * Convert exception to JSON format for HTTP response\r\n * @returns Object with error details\r\n */\r\n toJSON() {\r\n return {\r\n error: this.message,\r\n statusCode: this.statusCode,\r\n ...(this.details && { details: this.details })\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * 404 Not Found exception\r\n * Thrown when a requested resource cannot be found\r\n */\r\nexport class NotFoundException extends HTTPException {\r\n constructor(message: string = 'Not Found', details?: any) {\r\n super(404, message, details);\r\n this.name = 'NotFoundException';\r\n }\r\n\r\n toJSON() {\r\n return {\r\n error: this.message,\r\n statusCode: this.statusCode,\r\n ...(this.details && { details: this.details })\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * 401 Unauthorized exception\r\n * Thrown when authentication is required but not provided or invalid\r\n */\r\nexport class UnauthorizedException extends HTTPException {\r\n constructor(message: string = 'Unauthorized', details?: any) {\r\n super(401, message, details);\r\n this.name = 'UnauthorizedException';\r\n }\r\n\r\n toJSON() {\r\n return {\r\n error: this.message,\r\n statusCode: this.statusCode,\r\n ...(this.details && { details: this.details })\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * 403 Forbidden exception\r\n * Thrown when user is authenticated but doesn't have permission\r\n */\r\nexport class ForbiddenException extends HTTPException {\r\n constructor(message: string = 'Forbidden', details?: any) {\r\n super(403, message, details);\r\n this.name = 'ForbiddenException';\r\n }\r\n\r\n toJSON() {\r\n return {\r\n error: this.message,\r\n statusCode: this.statusCode,\r\n ...(this.details && { details: this.details })\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * 400 Bad Request exception\r\n * Thrown when the request is malformed or invalid\r\n */\r\nexport class BadRequestException extends HTTPException {\r\n constructor(message: string = 'Bad Request', details?: any) {\r\n super(400, message, details);\r\n this.name = 'BadRequestException';\r\n }\r\n\r\n toJSON() {\r\n return {\r\n error: this.message,\r\n statusCode: this.statusCode,\r\n ...(this.details && { details: this.details })\r\n };\r\n }\r\n}\r\n",
|
|
6
|
+
"import { ZodError } from 'zod';\r\nimport { HTTPException } from '../errors/exceptions.js';\r\n\r\n/**\r\n * ValidationException is thrown when Zod validation fails\r\n * Extends HTTPException with 422 Unprocessable Entity status\r\n * Provides detailed validation error information\r\n */\r\nexport class ValidationException extends HTTPException {\r\n constructor(public zodError: ZodError) {\r\n super(422, 'Validation failed');\r\n this.name = 'ValidationException';\r\n }\r\n\r\n /**\r\n * Converts the validation error to a user-friendly JSON format\r\n * @returns Object with error message and detailed validation errors\r\n */\r\n toJSON() {\r\n return {\r\n error: 'Validation Error',\r\n statusCode: this.statusCode,\r\n details: this.zodError.errors.map(err => ({\r\n path: err.path.join('.'),\r\n message: err.message,\r\n code: err.code\r\n }))\r\n };\r\n }\r\n}\r\n"
|
|
7
|
+
],
|
|
8
|
+
"mappings": ";AAKO,MAAM,UAAsB,KAAM,CAE9B,WAEA,QAHT,WAAW,CACF,EACP,EACO,EACP,CACA,MAAM,CAAO,EAJN,kBAEA,eAMP,GAHA,KAAK,KAAO,gBAGR,MAAM,kBACR,MAAM,kBAAkB,KAAM,KAAK,WAAW,EAQlD,MAAM,EAAG,CACP,MAAO,CACL,MAAO,KAAK,QACZ,WAAY,KAAK,cACb,KAAK,SAAW,CAAE,QAAS,KAAK,OAAQ,CAC9C,EAEJ,CAMO,MAAM,UAA0B,CAAc,CACnD,WAAW,CAAC,EAAkB,YAAa,EAAe,CACxD,MAAM,IAAK,EAAS,CAAO,EAC3B,KAAK,KAAO,oBAGd,MAAM,EAAG,CACP,MAAO,CACL,MAAO,KAAK,QACZ,WAAY,KAAK,cACb,KAAK,SAAW,CAAE,QAAS,KAAK,OAAQ,CAC9C,EAEJ,CAMO,MAAM,UAA8B,CAAc,CACvD,WAAW,CAAC,EAAkB,eAAgB,EAAe,CAC3D,MAAM,IAAK,EAAS,CAAO,EAC3B,KAAK,KAAO,wBAGd,MAAM,EAAG,CACP,MAAO,CACL,MAAO,KAAK,QACZ,WAAY,KAAK,cACb,KAAK,SAAW,CAAE,QAAS,KAAK,OAAQ,CAC9C,EAEJ,CAMO,MAAM,UAA2B,CAAc,CACpD,WAAW,CAAC,EAAkB,YAAa,EAAe,CACxD,MAAM,IAAK,EAAS,CAAO,EAC3B,KAAK,KAAO,qBAGd,MAAM,EAAG,CACP,MAAO,CACL,MAAO,KAAK,QACZ,WAAY,KAAK,cACb,KAAK,SAAW,CAAE,QAAS,KAAK,OAAQ,CAC9C,EAEJ,CAMO,MAAM,UAA4B,CAAc,CACrD,WAAW,CAAC,EAAkB,cAAe,EAAe,CAC1D,MAAM,IAAK,EAAS,CAAO,EAC3B,KAAK,KAAO,sBAGd,MAAM,EAAG,CACP,MAAO,CACL,MAAO,KAAK,QACZ,WAAY,KAAK,cACb,KAAK,SAAW,CAAE,QAAS,KAAK,OAAQ,CAC9C,EAEJ,CCnGO,MAAM,UAA4B,CAAc,CAClC,SAAnB,WAAW,CAAQ,EAAoB,CACrC,MAAM,IAAK,mBAAmB,EADb,gBAEjB,KAAK,KAAO,sBAOd,MAAM,EAAG,CACP,MAAO,CACL,MAAO,mBACP,WAAY,KAAK,WACjB,QAAS,KAAK,SAAS,OAAO,IAAI,MAAQ,CACxC,KAAM,EAAI,KAAK,KAAK,GAAG,EACvB,QAAS,EAAI,QACb,KAAM,EAAI,IACZ,EAAE,CACJ,EAEJ",
|
|
9
|
+
"debugId": "BE2ADDBCCA736E5064756E2164756E21",
|
|
10
|
+
"names": []
|
|
11
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{$ as z,ea as A}from"./chunk-1hqjkm44.js";class C{customHandler;isDevelopment;constructor(k){this.customHandler=k,this.isDevelopment=!0}setCustomHandler(k){this.customHandler=k}async handle(k,q){if(this.customHandler)try{return await this.customHandler(k,q)}catch(w){console.error("Custom error handler failed:",w)}if(k instanceof A)return this.handleValidationException(k,q);if(k instanceof z)return this.handleHTTPException(k,q);return this.handleGenericError(k,q)}handleValidationException(k,q){let w=k.toJSON();if(this.isDevelopment)console.error("Validation Error:",{path:q.req.path,method:q.req.method,details:w.details});return q.json(w,k.statusCode)}handleHTTPException(k,q){let w=k.toJSON();if(k.statusCode>=500)console.error("HTTP Exception:",{name:k.name,statusCode:k.statusCode,message:k.message,path:q.req.path,method:q.req.method,...this.isDevelopment&&k.stack?{stack:k.stack}:{}});else if(this.isDevelopment)console.warn("HTTP Exception:",{name:k.name,statusCode:k.statusCode,message:k.message,path:q.req.path,method:q.req.method});return q.json(w,k.statusCode)}handleGenericError(k,q){console.error("Internal Server Error:",{name:k.name,message:k.message,path:q.req.path,method:q.req.method,stack:k.stack});let w={error:"Internal Server Error",statusCode:500};if(this.isDevelopment){if(w.message=k.message,w.name=k.name,k.stack)w.stack=k.stack.split(`
|
|
3
|
+
`).map((B)=>B.trim())}else w.message="An unexpected error occurred";return q.json(w,500)}isDevelopmentMode(){return this.isDevelopment}setDevelopmentMode(k){this.isDevelopment=k}}
|
|
4
|
+
export{C};
|
|
5
|
+
|
|
6
|
+
//# debugId=7416B9C26743D35564756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["..\\..\\src\\errors\\handler.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { Context } from '../types';\r\nimport { HTTPException } from './exceptions.js';\r\nimport { ValidationException } from '../validation/exceptions.js';\r\n\r\n/**\r\n * Custom error handler function type\r\n * Allows users to provide their own error handling logic\r\n */\r\nexport type CustomErrorHandler = (error: Error, c: Context) => Response | Promise<Response>;\r\n\r\n/**\r\n * ErrorHandler processes all errors that occur during request handling\r\n * Provides consistent error responses and handles different error types appropriately\r\n */\r\nexport class ErrorHandler {\r\n private customHandler?: CustomErrorHandler;\r\n private isDevelopment: boolean;\r\n\r\n constructor(customHandler?: CustomErrorHandler) {\r\n this.customHandler = customHandler;\r\n this.isDevelopment = process.env.NODE_ENV !== 'production';\r\n }\r\n\r\n /**\r\n * Set a custom error handler\r\n * @param handler - Custom error handling function\r\n */\r\n setCustomHandler(handler: CustomErrorHandler): void {\r\n this.customHandler = handler;\r\n }\r\n\r\n /**\r\n * Main error handling method\r\n * Processes all error types and returns appropriate HTTP responses\r\n * @param error - The error that occurred\r\n * @param c - Hono context object\r\n * @returns HTTP response with error details\r\n */\r\n async handle(error: Error, c: Context): Promise<Response> {\r\n // If custom handler is provided, use it first\r\n if (this.customHandler) {\r\n try {\r\n return await this.customHandler(error, c);\r\n } catch (customHandlerError) {\r\n // If custom handler fails, fall back to default handling\r\n console.error('Custom error handler failed:', customHandlerError);\r\n }\r\n }\r\n\r\n // Handle ValidationException (422)\r\n if (error instanceof ValidationException) {\r\n return this.handleValidationException(error, c);\r\n }\r\n\r\n // Handle HTTPException and its subclasses\r\n if (error instanceof HTTPException) {\r\n return this.handleHTTPException(error, c);\r\n }\r\n\r\n // Handle generic errors (500)\r\n return this.handleGenericError(error, c);\r\n }\r\n\r\n /**\r\n * Handle validation exceptions (422 Unprocessable Entity)\r\n * @param error - ValidationException instance\r\n * @param c - Hono context\r\n * @returns JSON response with validation error details\r\n */\r\n private handleValidationException(error: ValidationException, c: Context): Response {\r\n const response = error.toJSON();\r\n \r\n // Log validation errors in development\r\n if (this.isDevelopment) {\r\n console.error('Validation Error:', {\r\n path: c.req.path,\r\n method: c.req.method,\r\n details: response.details\r\n });\r\n }\r\n\r\n return c.json(response, error.statusCode as any);\r\n }\r\n\r\n /**\r\n * Handle HTTP exceptions (4xx, 5xx)\r\n * @param error - HTTPException instance\r\n * @param c - Hono context\r\n * @returns JSON response with error details\r\n */\r\n private handleHTTPException(error: HTTPException, c: Context): Response {\r\n const response = error.toJSON();\r\n\r\n // Log HTTP exceptions based on severity\r\n if (error.statusCode >= 500) {\r\n // Server errors - always log\r\n console.error('HTTP Exception:', {\r\n name: error.name,\r\n statusCode: error.statusCode,\r\n message: error.message,\r\n path: c.req.path,\r\n method: c.req.method,\r\n ...(this.isDevelopment && error.stack ? { stack: error.stack } : {})\r\n });\r\n } else if (this.isDevelopment) {\r\n // Client errors - log only in development\r\n console.warn('HTTP Exception:', {\r\n name: error.name,\r\n statusCode: error.statusCode,\r\n message: error.message,\r\n path: c.req.path,\r\n method: c.req.method\r\n });\r\n }\r\n\r\n return c.json(response, error.statusCode as any);\r\n }\r\n\r\n /**\r\n * Handle generic/unexpected errors (500 Internal Server Error)\r\n * Hides internal details in production, shows stack trace in development\r\n * @param error - Generic Error instance\r\n * @param c - Hono context\r\n * @returns JSON response with error details\r\n */\r\n private handleGenericError(error: Error, c: Context): Response {\r\n // Always log generic errors\r\n console.error('Internal Server Error:', {\r\n name: error.name,\r\n message: error.message,\r\n path: c.req.path,\r\n method: c.req.method,\r\n stack: error.stack\r\n });\r\n\r\n // Build response based on environment\r\n const response: any = {\r\n error: 'Internal Server Error',\r\n statusCode: 500\r\n };\r\n\r\n // In development, include error details and stack trace\r\n if (this.isDevelopment) {\r\n response.message = error.message;\r\n response.name = error.name;\r\n \r\n if (error.stack) {\r\n response.stack = error.stack.split('\\n').map(line => line.trim());\r\n }\r\n } else {\r\n // In production, use generic message\r\n response.message = 'An unexpected error occurred';\r\n }\r\n\r\n return c.json(response, 500);\r\n }\r\n\r\n /**\r\n * Check if running in development mode\r\n * @returns true if in development mode\r\n */\r\n isDevelopmentMode(): boolean {\r\n return this.isDevelopment;\r\n }\r\n\r\n /**\r\n * Set development mode manually (useful for testing)\r\n * @param isDev - Whether to enable development mode\r\n */\r\n setDevelopmentMode(isDev: boolean): void {\r\n this.isDevelopment = isDev;\r\n }\r\n}\r\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";gDAcO,MAAM,CAAa,CAChB,cACA,cAER,WAAW,CAAC,EAAoC,CAC9C,KAAK,cAAgB,EACrB,KAAK,cAAgB,GAOvB,gBAAgB,CAAC,EAAmC,CAClD,KAAK,cAAgB,OAUjB,OAAM,CAAC,EAAc,EAA+B,CAExD,GAAI,KAAK,cACP,GAAI,CACF,OAAO,MAAM,KAAK,cAAc,EAAO,CAAC,EACxC,MAAO,EAAoB,CAE3B,QAAQ,MAAM,+BAAgC,CAAkB,EAKpE,GAAI,aAAiB,EACnB,OAAO,KAAK,0BAA0B,EAAO,CAAC,EAIhD,GAAI,aAAiB,EACnB,OAAO,KAAK,oBAAoB,EAAO,CAAC,EAI1C,OAAO,KAAK,mBAAmB,EAAO,CAAC,EASjC,yBAAyB,CAAC,EAA4B,EAAsB,CAClF,IAAM,EAAW,EAAM,OAAO,EAG9B,GAAI,KAAK,cACP,QAAQ,MAAM,oBAAqB,CACjC,KAAM,EAAE,IAAI,KACZ,OAAQ,EAAE,IAAI,OACd,QAAS,EAAS,OACpB,CAAC,EAGH,OAAO,EAAE,KAAK,EAAU,EAAM,UAAiB,EASzC,mBAAmB,CAAC,EAAsB,EAAsB,CACtE,IAAM,EAAW,EAAM,OAAO,EAG9B,GAAI,EAAM,YAAc,IAEtB,QAAQ,MAAM,kBAAmB,CAC/B,KAAM,EAAM,KACZ,WAAY,EAAM,WAClB,QAAS,EAAM,QACf,KAAM,EAAE,IAAI,KACZ,OAAQ,EAAE,IAAI,UACV,KAAK,eAAiB,EAAM,MAAQ,CAAE,MAAO,EAAM,KAAM,EAAI,CAAC,CACpE,CAAC,EACI,QAAI,KAAK,cAEd,QAAQ,KAAK,kBAAmB,CAC9B,KAAM,EAAM,KACZ,WAAY,EAAM,WAClB,QAAS,EAAM,QACf,KAAM,EAAE,IAAI,KACZ,OAAQ,EAAE,IAAI,MAChB,CAAC,EAGH,OAAO,EAAE,KAAK,EAAU,EAAM,UAAiB,EAUzC,kBAAkB,CAAC,EAAc,EAAsB,CAE7D,QAAQ,MAAM,yBAA0B,CACtC,KAAM,EAAM,KACZ,QAAS,EAAM,QACf,KAAM,EAAE,IAAI,KACZ,OAAQ,EAAE,IAAI,OACd,MAAO,EAAM,KACf,CAAC,EAGD,IAAM,EAAgB,CACpB,MAAO,wBACP,WAAY,GACd,EAGA,GAAI,KAAK,eAIP,GAHA,EAAS,QAAU,EAAM,QACzB,EAAS,KAAO,EAAM,KAElB,EAAM,MACR,EAAS,MAAQ,EAAM,MAAM,MAAM;AAAA,CAAI,EAAE,IAAI,KAAQ,EAAK,KAAK,CAAC,EAIlE,OAAS,QAAU,+BAGrB,OAAO,EAAE,KAAK,EAAU,GAAG,EAO7B,iBAAiB,EAAY,CAC3B,OAAO,KAAK,cAOd,kBAAkB,CAAC,EAAsB,CACvC,KAAK,cAAgB,EAEzB",
|
|
8
|
+
"debugId": "7416B9C26743D35564756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
var j=Object.create;var{getPrototypeOf:k,defineProperty:e,getOwnPropertyNames:h,getOwnPropertyDescriptor:l}=Object,i=Object.prototype.hasOwnProperty;var m=(a,b,c)=>{c=a!=null?j(k(a)):{};let d=b||!a||!a.__esModule?e(c,"default",{value:a,enumerable:!0}):c;for(let f of h(a))if(!i.call(d,f))e(d,f,{get:()=>a[f],enumerable:!0});return d},g=new WeakMap,n=(a)=>{var b=g.get(a),c;if(b)return b;if(b=e({},"__esModule",{value:!0}),a&&typeof a==="object"||typeof a==="function")h(a).map((d)=>!i.call(b,d)&&e(b,d,{get:()=>a[d],enumerable:!(c=l(a,d))||c.enumerable}));return g.set(a,b),b},o=(a,b)=>()=>(b||a((b={exports:{}}).exports,b),b.exports);var p=(a,b)=>{for(var c in b)e(a,c,{get:b[c],enumerable:!0,configurable:!0,set:(d)=>b[c]=()=>d})};var q=import.meta.require;
|
|
3
|
+
export{m as ia,n as ja,o as ka,p as la,q as ma};
|
|
4
|
+
|
|
5
|
+
//# debugId=2299D103A4FF343364756E2164756E21
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import"./chunk-42h6trpf.js";import{writeFile as b,mkdir as U}from"fs/promises";import{join as Z}from"path";import{existsSync as k}from"fs";function j(z){let H=z.command("generate").description("Generate code and documentation").alias("g");H.command("openapi").description("Generate OpenAPI specification").option("-o, --output <file>","Output file path","openapi.json").action(async(E)=>{await A(E)}),H.command("client").description("Generate TypeScript client from OpenAPI spec").option("-i, --input <file>","OpenAPI spec file","openapi.json").option("-o, --output <dir>","Output directory","src/client").action(async(E)=>{await w(E)})}async function A(z){console.log("Generating OpenAPI specification...");try{let H=Z(process.cwd(),"src","index.ts");if(!k(H))console.error("Error: src/index.ts not found"),console.error("Make sure you are in a FastAPI-TS project directory"),process.exit(1);let E=await import(H),K=E.default||E.app;if(!K||typeof K.getMetadata!=="function")console.error("Error: Could not find VeloceTS app instance"),console.error("Make sure your src/index.ts exports the app or sets it as default"),process.exit(1);let L=K.getMetadata(),Q=J(L,K),V=Z(process.cwd(),z.output);await b(V,JSON.stringify(Q,null,2)),console.log(`\u2713 OpenAPI spec generated: ${z.output}`)}catch(H){console.error("Failed to generate OpenAPI spec:",H),process.exit(1)}}function J(z,H){let E=z.getRoutes(),K={openapi:"3.0.0",info:{title:H.config?.title||"Veloce API",version:H.config?.version||"1.0.0",description:H.config?.description||"API built with Veloce"},paths:{},components:{schemas:{}}};for(let L of E){let Q=L.path,V=L.method.toLowerCase();if(!K.paths[Q])K.paths[Q]={};K.paths[Q][V]={summary:L.docs?.summary||`${V.toUpperCase()} ${Q}`,description:L.docs?.description,tags:L.docs?.tags||[],parameters:O(L),requestBody:R(L),responses:{"200":{description:"Successful response",content:{"application/json":{schema:{type:"object"}}}}}}}return K}function O(z){let H=[];for(let E of z.parameters||[])if(E.type==="query"||E.type==="param"||E.type==="header")H.push({name:E.name||"unknown",in:E.type==="param"?"path":E.type,required:E.required||!1,schema:{type:"string"}});return H}function R(z){if(!z.parameters?.find((E)=>E.type==="body"))return;return{required:!0,content:{"application/json":{schema:{type:"object"}}}}}async function w(z){console.log("Generating TypeScript client...");try{let H=Z(process.cwd(),z.input);if(!k(H))console.error(`Error: OpenAPI spec not found at ${z.input}`),console.error('Run "veloce generate openapi" first'),process.exit(1);let E=await Bun.file(H).text(),K=JSON.parse(E),L=Z(process.cwd(),z.output);await U(L,{recursive:!0});let Q=B(K),V=Z(L,"client.ts");await b(V,Q);let W=I(K),Y=Z(L,"types.ts");await b(Y,W),console.log(`\u2713 TypeScript client generated in ${z.output}`),console.log(` - ${z.output}/client.ts`),console.log(` - ${z.output}/types.ts`)}catch(H){console.error("Failed to generate client:",H),process.exit(1)}}function B(z){let H=z.servers?.[0]?.url||"http://localhost:3000",E=`// Generated TypeScript client for ${z.info.title}
|
|
3
|
+
// Version: ${z.info.version}
|
|
4
|
+
|
|
5
|
+
import type * as Types from './types';
|
|
6
|
+
|
|
7
|
+
export class APIClient {
|
|
8
|
+
constructor(private baseUrl: string = '${H}') {}
|
|
9
|
+
|
|
10
|
+
private async request<T>(
|
|
11
|
+
method: string,
|
|
12
|
+
path: string,
|
|
13
|
+
options?: {
|
|
14
|
+
params?: Record<string, any>;
|
|
15
|
+
body?: any;
|
|
16
|
+
headers?: Record<string, string>;
|
|
17
|
+
}
|
|
18
|
+
): Promise<T> {
|
|
19
|
+
const url = new URL(path, this.baseUrl);
|
|
20
|
+
|
|
21
|
+
if (options?.params) {
|
|
22
|
+
Object.entries(options.params).forEach(([key, value]) => {
|
|
23
|
+
url.searchParams.append(key, String(value));
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const response = await fetch(url.toString(), {
|
|
28
|
+
method,
|
|
29
|
+
headers: {
|
|
30
|
+
'Content-Type': 'application/json',
|
|
31
|
+
...options?.headers,
|
|
32
|
+
},
|
|
33
|
+
body: options?.body ? JSON.stringify(options.body) : undefined,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
if (!response.ok) {
|
|
37
|
+
throw new Error(\`API request failed: \${response.statusText}\`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return response.json();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
`;for(let[K,L]of Object.entries(z.paths||{}))for(let[Q,V]of Object.entries(L)){let W=q(Q,K,V),Y=D(Q,K,V);E+=Y+`
|
|
44
|
+
`}return E+=`}
|
|
45
|
+
`,E}function q(z,H,E){if(E.operationId)return E.operationId;let K=H.replace(/\{|\}/g,"").replace(/\//g,"_").replace(/^_/,"").replace(/_([a-z])/g,(L,Q)=>Q.toUpperCase());return`${z}${K.charAt(0).toUpperCase()+K.slice(1)}`}function D(z,H,E){let K=q(z,H,E),L=z==="post"||z==="put"||z==="patch",Q=E.parameters?.some((X)=>X.in==="query"),V=E.parameters?.some((X)=>X.in==="path"),W=[],Y=[];if(V){let X=E.parameters.filter((_)=>_.in==="path");Y=X.map((_)=>_.name),W.push(...X.map((_)=>`${_.name}: string`))}if(L)W.push("body: any");if(Q)W.push("params?: Record<string, any>");let G=W.length>0?W.join(", "):"",$=H;for(let X of Y)$=$.replace(`{${X}}`,`\${${X}}`);return` async ${K}(${G}): Promise<any> {
|
|
46
|
+
return this.request('${z.toUpperCase()}', \`${$}\`, {
|
|
47
|
+
${L?"body,":""}
|
|
48
|
+
${Q?"params,":""}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
`}function I(z){let H=`// Generated types for ${z.info.title}
|
|
52
|
+
// Version: ${z.info.version}
|
|
53
|
+
|
|
54
|
+
`;if(z.components?.schemas)for(let[E,K]of Object.entries(z.components.schemas))H+=`export interface ${E} {
|
|
55
|
+
`,H+=T(K),H+=`}
|
|
56
|
+
|
|
57
|
+
`;return H}function T(z,H=" "){let E="";if(z.properties)for(let[K,L]of Object.entries(z.properties)){let Q=L,V=!z.required?.includes(K),W=v(Q);E+=`${H}${K}${V?"?":""}: ${W};
|
|
58
|
+
`}return E}function v(z){if(z.type==="string")return"string";if(z.type==="number"||z.type==="integer")return"number";if(z.type==="boolean")return"boolean";if(z.type==="array")return`${z.items?v(z.items):"any"}[]`;if(z.type==="object")return"Record<string, any>";return"any"}export{j as registerGenerateCommand};
|
|
59
|
+
|
|
60
|
+
//# debugId=E52C16AAC593E76D64756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["..\\..\\src\\cli\\commands\\generate.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { Command } from 'commander';\r\nimport { writeFile, mkdir } from 'fs/promises';\r\nimport { join } from 'path';\r\nimport { existsSync } from 'fs';\r\n\r\nexport function registerGenerateCommand(program: Command): void {\r\n const generateCommand = program\r\n .command('generate')\r\n .description('Generate code and documentation')\r\n .alias('g');\r\n\r\n // Generate OpenAPI spec\r\n generateCommand\r\n .command('openapi')\r\n .description('Generate OpenAPI specification')\r\n .option('-o, --output <file>', 'Output file path', 'openapi.json')\r\n .action(async (options: { output: string }) => {\r\n await generateOpenAPI(options);\r\n });\r\n\r\n // Generate TypeScript client\r\n generateCommand\r\n .command('client')\r\n .description('Generate TypeScript client from OpenAPI spec')\r\n .option('-i, --input <file>', 'OpenAPI spec file', 'openapi.json')\r\n .option('-o, --output <dir>', 'Output directory', 'src/client')\r\n .action(async (options: { input: string; output: string }) => {\r\n await generateClient(options);\r\n });\r\n}\r\n\r\nasync function generateOpenAPI(options: { output: string }): Promise<void> {\r\n console.log('Generating OpenAPI specification...');\r\n\r\n try {\r\n // Import the application to extract metadata\r\n const appPath = join(process.cwd(), 'src', 'index.ts');\r\n\r\n if (!existsSync(appPath)) {\r\n console.error('Error: src/index.ts not found');\r\n console.error('Make sure you are in a FastAPI-TS project directory');\r\n process.exit(1);\r\n }\r\n\r\n // Dynamically import the app\r\n const appModule = await import(appPath);\r\n const app = appModule.default || appModule.app;\r\n\r\n if (!app || typeof app.getMetadata !== 'function') {\r\n console.error('Error: Could not find VeloceTS app instance');\r\n console.error('Make sure your src/index.ts exports the app or sets it as default');\r\n process.exit(1);\r\n }\r\n\r\n // Generate OpenAPI spec from metadata\r\n const metadata = app.getMetadata();\r\n const spec = generateOpenAPISpec(metadata, app);\r\n\r\n // Write to file\r\n const outputPath = join(process.cwd(), options.output);\r\n await writeFile(outputPath, JSON.stringify(spec, null, 2));\r\n\r\n console.log(`✓ OpenAPI spec generated: ${options.output}`);\r\n } catch (error) {\r\n console.error('Failed to generate OpenAPI spec:', error);\r\n process.exit(1);\r\n }\r\n}\r\n\r\nfunction generateOpenAPISpec(metadata: any, app: any): any {\r\n const routes = metadata.getRoutes();\r\n\r\n const spec = {\r\n openapi: '3.0.0',\r\n info: {\r\n title: app.config?.title || 'Veloce API',\r\n version: app.config?.version || '1.0.0',\r\n description: app.config?.description || 'API built with Veloce',\r\n },\r\n paths: {} as Record<string, any>,\r\n components: {\r\n schemas: {},\r\n },\r\n };\r\n\r\n // Build paths from routes\r\n for (const route of routes) {\r\n const path = route.path;\r\n const method = route.method.toLowerCase();\r\n\r\n if (!spec.paths[path]) {\r\n spec.paths[path] = {};\r\n }\r\n\r\n spec.paths[path][method] = {\r\n summary: route.docs?.summary || `${method.toUpperCase()} ${path}`,\r\n description: route.docs?.description,\r\n tags: route.docs?.tags || [],\r\n parameters: extractParameters(route),\r\n requestBody: extractRequestBody(route),\r\n responses: {\r\n '200': {\r\n description: 'Successful response',\r\n content: {\r\n 'application/json': {\r\n schema: { type: 'object' },\r\n },\r\n },\r\n },\r\n },\r\n };\r\n }\r\n\r\n return spec;\r\n}\r\n\r\nfunction extractParameters(route: any): any[] {\r\n const params: any[] = [];\r\n\r\n for (const param of route.parameters || []) {\r\n if (param.type === 'query' || param.type === 'param' || param.type === 'header') {\r\n params.push({\r\n name: param.name || 'unknown',\r\n in: param.type === 'param' ? 'path' : param.type,\r\n required: param.required || false,\r\n schema: { type: 'string' },\r\n });\r\n }\r\n }\r\n\r\n return params;\r\n}\r\n\r\nfunction extractRequestBody(route: any): any | undefined {\r\n const bodyParam = route.parameters?.find((p: any) => p.type === 'body');\r\n\r\n if (!bodyParam) {\r\n return undefined;\r\n }\r\n\r\n return {\r\n required: true,\r\n content: {\r\n 'application/json': {\r\n schema: { type: 'object' },\r\n },\r\n },\r\n };\r\n}\r\n\r\nasync function generateClient(options: { input: string; output: string }): Promise<void> {\r\n console.log('Generating TypeScript client...');\r\n\r\n try {\r\n const specPath = join(process.cwd(), options.input);\r\n\r\n if (!existsSync(specPath)) {\r\n console.error(`Error: OpenAPI spec not found at ${options.input}`);\r\n console.error('Run \"veloce generate openapi\" first');\r\n process.exit(1);\r\n }\r\n\r\n // Read OpenAPI spec\r\n const specFile = await Bun.file(specPath).text();\r\n const spec = JSON.parse(specFile);\r\n\r\n // Create output directory\r\n const outputDir = join(process.cwd(), options.output);\r\n await mkdir(outputDir, { recursive: true });\r\n\r\n // Generate client code\r\n const clientCode = generateClientCode(spec);\r\n\r\n // Write client file\r\n const clientPath = join(outputDir, 'client.ts');\r\n await writeFile(clientPath, clientCode);\r\n\r\n // Generate types file\r\n const typesCode = generateTypesCode(spec);\r\n const typesPath = join(outputDir, 'types.ts');\r\n await writeFile(typesPath, typesCode);\r\n\r\n console.log(`✓ TypeScript client generated in ${options.output}`);\r\n console.log(` - ${options.output}/client.ts`);\r\n console.log(` - ${options.output}/types.ts`);\r\n } catch (error) {\r\n console.error('Failed to generate client:', error);\r\n process.exit(1);\r\n }\r\n}\r\n\r\nfunction generateClientCode(spec: any): string {\r\n const baseUrl = spec.servers?.[0]?.url || 'http://localhost:3000';\r\n\r\n let code = `// Generated TypeScript client for ${spec.info.title}\r\n// Version: ${spec.info.version}\r\n\r\nimport type * as Types from './types';\r\n\r\nexport class APIClient {\r\n constructor(private baseUrl: string = '${baseUrl}') {}\r\n\r\n private async request<T>(\r\n method: string,\r\n path: string,\r\n options?: {\r\n params?: Record<string, any>;\r\n body?: any;\r\n headers?: Record<string, string>;\r\n }\r\n ): Promise<T> {\r\n const url = new URL(path, this.baseUrl);\r\n\r\n if (options?.params) {\r\n Object.entries(options.params).forEach(([key, value]) => {\r\n url.searchParams.append(key, String(value));\r\n });\r\n }\r\n\r\n const response = await fetch(url.toString(), {\r\n method,\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...options?.headers,\r\n },\r\n body: options?.body ? JSON.stringify(options.body) : undefined,\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(\\`API request failed: \\${response.statusText}\\`);\r\n }\r\n\r\n return response.json();\r\n }\r\n\r\n`;\r\n\r\n // Generate methods for each endpoint\r\n for (const [path, methods] of Object.entries(spec.paths || {})) {\r\n for (const [method, operation] of Object.entries(methods as any)) {\r\n const methodName = generateMethodName(method, path, operation);\r\n const methodCode = generateMethodCode(method, path, operation);\r\n code += methodCode + '\\n';\r\n }\r\n }\r\n\r\n code += '}\\n';\r\n\r\n return code;\r\n}\r\n\r\nfunction generateMethodName(method: string, path: string, operation: any): string {\r\n // Use operationId if available, otherwise generate from path\r\n if (operation.operationId) {\r\n return operation.operationId;\r\n }\r\n\r\n // Convert path to camelCase method name\r\n const cleanPath = path\r\n .replace(/\\{|\\}/g, '')\r\n .replace(/\\//g, '_')\r\n .replace(/^_/, '')\r\n .replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());\r\n\r\n return `${method}${cleanPath.charAt(0).toUpperCase() + cleanPath.slice(1)}`;\r\n}\r\n\r\nfunction generateMethodCode(method: string, path: string, operation: any): string {\r\n const methodName = generateMethodName(method, path, operation);\r\n const hasBody = method === 'post' || method === 'put' || method === 'patch';\r\n const hasParams = operation.parameters?.some((p: any) => p.in === 'query');\r\n const hasPathParams = operation.parameters?.some((p: any) => p.in === 'path');\r\n\r\n let params: string[] = [];\r\n let pathParamNames: string[] = [];\r\n\r\n if (hasPathParams) {\r\n const pathParams = operation.parameters.filter((p: any) => p.in === 'path');\r\n pathParamNames = pathParams.map((p: any) => p.name);\r\n params.push(...pathParams.map((p: any) => `${p.name}: string`));\r\n }\r\n\r\n if (hasBody) {\r\n params.push('body: any');\r\n }\r\n\r\n if (hasParams) {\r\n params.push('params?: Record<string, any>');\r\n }\r\n\r\n const paramsStr = params.length > 0 ? params.join(', ') : '';\r\n\r\n // Replace path parameters\r\n let finalPath = path;\r\n for (const paramName of pathParamNames) {\r\n finalPath = finalPath.replace(`{${paramName}}`, `\\${${paramName}}`);\r\n }\r\n\r\n return ` async ${methodName}(${paramsStr}): Promise<any> {\r\n return this.request('${method.toUpperCase()}', \\`${finalPath}\\`, {\r\n ${hasBody ? 'body,' : ''}\r\n ${hasParams ? 'params,' : ''}\r\n });\r\n }\r\n`;\r\n}\r\n\r\nfunction generateTypesCode(spec: any): string {\r\n let code = `// Generated types for ${spec.info.title}\r\n// Version: ${spec.info.version}\r\n\r\n`;\r\n\r\n // Generate types from schemas\r\n if (spec.components?.schemas) {\r\n for (const [name, schema] of Object.entries(spec.components.schemas)) {\r\n code += `export interface ${name} {\\n`;\r\n code += generateInterfaceProperties(schema as any);\r\n code += '}\\n\\n';\r\n }\r\n }\r\n\r\n return code;\r\n}\r\n\r\nfunction generateInterfaceProperties(schema: any, indent: string = ' '): string {\r\n let props = '';\r\n\r\n if (schema.properties) {\r\n for (const [propName, propSchema] of Object.entries(schema.properties)) {\r\n const prop = propSchema as any;\r\n const optional = !schema.required?.includes(propName);\r\n const type = mapJsonSchemaType(prop);\r\n props += `${indent}${propName}${optional ? '?' : ''}: ${type};\\n`;\r\n }\r\n }\r\n\r\n return props;\r\n}\r\n\r\nfunction mapJsonSchemaType(schema: any): string {\r\n if (schema.type === 'string') return 'string';\r\n if (schema.type === 'number' || schema.type === 'integer') return 'number';\r\n if (schema.type === 'boolean') return 'boolean';\r\n if (schema.type === 'array') {\r\n const itemType = schema.items ? mapJsonSchemaType(schema.items) : 'any';\r\n return `${itemType}[]`;\r\n }\r\n if (schema.type === 'object') return 'Record<string, any>';\r\n return 'any';\r\n}\r\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "E52C16AAC593E76D64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|