alepha 0.13.6 → 0.13.8
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 +5 -2
- package/assets/swagger-ui/swagger-ui-bundle.js +1 -1
- package/assets/swagger-ui/swagger-ui-standalone-preset.js +1 -1
- package/assets/swagger-ui/swagger-ui.css +1 -1
- package/dist/api/audits/index.browser.js +116 -0
- package/dist/api/audits/index.browser.js.map +1 -0
- package/dist/api/audits/index.d.ts +1194 -0
- package/dist/api/audits/index.js +674 -0
- package/dist/api/audits/index.js.map +1 -0
- package/dist/{api-files → api/files}/index.browser.js +5 -5
- package/dist/api/files/index.browser.js.map +1 -0
- package/dist/{api-files → api/files}/index.d.ts +16 -9
- package/dist/{api-files → api/files}/index.js +10 -10
- package/dist/api/files/index.js.map +1 -0
- package/dist/{api-jobs → api/jobs}/index.browser.js +5 -5
- package/dist/api/jobs/index.browser.js.map +1 -0
- package/dist/{api-jobs → api/jobs}/index.d.ts +35 -35
- package/dist/{api-jobs → api/jobs}/index.js +9 -9
- package/dist/api/jobs/index.js.map +1 -0
- package/dist/{api-notifications → api/notifications}/index.browser.js +11 -11
- package/dist/api/notifications/index.browser.js.map +1 -0
- package/dist/api/notifications/index.d.ts +327 -0
- package/dist/{api-notifications → api/notifications}/index.js +11 -11
- package/dist/api/notifications/index.js.map +1 -0
- package/dist/api/parameters/index.browser.js +60 -0
- package/dist/api/parameters/index.browser.js.map +1 -0
- package/dist/api/parameters/index.d.ts +761 -0
- package/dist/api/parameters/index.js +877 -0
- package/dist/api/parameters/index.js.map +1 -0
- package/dist/{api-users → api/users}/index.browser.js +6 -6
- package/dist/api/users/index.browser.js.map +1 -0
- package/dist/{api-users → api/users}/index.d.ts +259 -247
- package/dist/{api-users → api/users}/index.js +125 -112
- package/dist/api/users/index.js.map +1 -0
- package/dist/{api-verifications → api/verifications}/index.browser.js +5 -5
- package/dist/api/verifications/index.browser.js.map +1 -0
- package/dist/api/verifications/index.d.ts +248 -0
- package/dist/{api-verifications → api/verifications}/index.js +13 -12
- package/dist/api/verifications/index.js.map +1 -0
- package/dist/bin/index.js +1 -0
- package/dist/bin/index.js.map +1 -1
- package/dist/cache/{index.d.ts → core/index.d.ts} +4 -4
- package/dist/cache/{index.js → core/index.js} +5 -5
- package/dist/cache/core/index.js.map +1 -0
- package/dist/{cache-redis → cache/redis}/index.d.ts +2 -2
- package/dist/{cache-redis → cache/redis}/index.js +2 -2
- package/dist/cache/redis/index.js.map +1 -0
- package/dist/cli/index.d.ts +71 -9
- package/dist/cli/index.js +280 -79
- package/dist/cli/index.js.map +1 -1
- package/dist/command/index.d.ts +63 -2
- package/dist/command/index.js +30 -3
- package/dist/command/index.js.map +1 -1
- package/dist/core/index.browser.js +241 -61
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +170 -90
- package/dist/core/index.js +264 -67
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js +248 -65
- package/dist/core/index.native.js.map +1 -1
- package/dist/email/index.js +15 -10554
- package/dist/email/index.js.map +1 -1
- package/dist/lock/{index.d.ts → core/index.d.ts} +5 -5
- package/dist/lock/{index.js → core/index.js} +5 -5
- package/dist/lock/core/index.js.map +1 -0
- package/dist/{lock-redis → lock/redis}/index.d.ts +2 -2
- package/dist/{lock-redis → lock/redis}/index.js +2 -2
- package/dist/lock/redis/index.js.map +1 -0
- package/dist/logger/index.d.ts +4 -4
- package/dist/logger/index.js +77 -72
- package/dist/logger/index.js.map +1 -1
- package/dist/orm/index.d.ts +5 -1
- package/dist/orm/index.js +24 -7
- package/dist/orm/index.js.map +1 -1
- package/dist/queue/core/index.d.ts +548 -0
- package/dist/queue/core/index.js +391 -0
- package/dist/queue/core/index.js.map +1 -0
- package/dist/queue/redis/index.d.ts +28 -0
- package/dist/queue/redis/index.js +43 -0
- package/dist/queue/redis/index.js.map +1 -0
- package/dist/scheduler/index.d.ts +7 -7
- package/dist/scheduler/index.js +1 -393
- package/dist/scheduler/index.js.map +1 -1
- package/dist/security/index.d.ts +1 -1
- package/dist/security/index.js +2 -1413
- package/dist/security/index.js.map +1 -1
- package/dist/{server-auth → server/auth}/index.browser.js +6 -6
- package/dist/server/auth/index.browser.js.map +1 -0
- package/dist/{server-auth → server/auth}/index.d.ts +175 -164
- package/dist/server/auth/index.js +742 -0
- package/dist/server/auth/index.js.map +1 -0
- package/dist/{server-cache → server/cache}/index.d.ts +2 -2
- package/dist/{server-cache → server/cache}/index.js +2 -2
- package/dist/server/cache/index.js.map +1 -0
- package/dist/{server-compress → server/compress}/index.d.ts +2 -2
- package/dist/{server-compress → server/compress}/index.js +2 -2
- package/dist/server/compress/index.js.map +1 -0
- package/dist/{server-cookies → server/cookies}/index.browser.js +3 -3
- package/dist/server/cookies/index.browser.js.map +1 -0
- package/dist/{server-cookies → server/cookies}/index.d.ts +4 -4
- package/dist/{server-cookies → server/cookies}/index.js +9 -5
- package/dist/server/cookies/index.js.map +1 -0
- package/dist/server/{index.browser.js → core/index.browser.js} +14 -14
- package/dist/server/core/index.browser.js.map +1 -0
- package/dist/server/{index.d.ts → core/index.d.ts} +46 -37
- package/dist/server/{index.js → core/index.js} +47 -33
- package/dist/server/core/index.js.map +1 -0
- package/dist/{server-cors → server/cors}/index.d.ts +3 -3
- package/dist/{server-cors → server/cors}/index.js +3 -3
- package/dist/server/cors/index.js.map +1 -0
- package/dist/{server-health → server/health}/index.d.ts +3 -3
- package/dist/{server-health → server/health}/index.js +3 -3
- package/dist/server/health/index.js.map +1 -0
- package/dist/{server-helmet → server/helmet}/index.d.ts +2 -2
- package/dist/{server-helmet → server/helmet}/index.js +2 -2
- package/dist/server/helmet/index.js.map +1 -0
- package/dist/{server-links → server/links}/index.browser.js +5 -5
- package/dist/server/links/index.browser.js.map +1 -0
- package/dist/{server-links → server/links}/index.d.ts +40 -40
- package/dist/{server-links → server/links}/index.js +7 -7
- package/dist/server/links/index.js.map +1 -0
- package/dist/{server-metrics → server/metrics}/index.d.ts +2 -2
- package/dist/server/metrics/index.js +74 -0
- package/dist/server/metrics/index.js.map +1 -0
- package/dist/{server-multipart → server/multipart}/index.d.ts +2 -2
- package/dist/{server-multipart → server/multipart}/index.js +2 -2
- package/dist/server/multipart/index.js.map +1 -0
- package/dist/{server-proxy → server/proxy}/index.d.ts +3 -3
- package/dist/{server-proxy → server/proxy}/index.js +3 -3
- package/dist/server/proxy/index.js.map +1 -0
- package/dist/{server-rate-limit → server/rate-limit}/index.d.ts +4 -4
- package/dist/{server-rate-limit → server/rate-limit}/index.js +4 -4
- package/dist/server/rate-limit/index.js.map +1 -0
- package/dist/{server-security → server/security}/index.browser.js +1 -1
- package/dist/server/security/index.browser.js.map +1 -0
- package/dist/{server-security → server/security}/index.d.ts +4 -4
- package/dist/{server-security → server/security}/index.js +4 -4
- package/dist/server/security/index.js.map +1 -0
- package/dist/{server-static → server/static}/index.d.ts +3 -3
- package/dist/{server-static → server/static}/index.js +3 -3
- package/dist/server/static/index.js.map +1 -0
- package/dist/{server-swagger → server/swagger}/index.d.ts +3 -3
- package/dist/{server-swagger → server/swagger}/index.js +4 -4
- package/dist/server/swagger/index.js.map +1 -0
- package/dist/thread/index.js +2 -2
- package/dist/thread/index.js.map +1 -1
- package/dist/topic/{index.d.ts → core/index.d.ts} +6 -6
- package/dist/topic/{index.js → core/index.js} +6 -6
- package/dist/topic/core/index.js.map +1 -0
- package/dist/{topic-redis → topic/redis}/index.d.ts +2 -2
- package/dist/{topic-redis → topic/redis}/index.js +2 -2
- package/dist/topic/redis/index.js.map +1 -0
- package/dist/vite/index.d.ts +13 -2
- package/dist/vite/index.js +114 -50
- package/dist/vite/index.js.map +1 -1
- package/dist/websocket/index.browser.js +3 -3
- package/dist/websocket/index.browser.js.map +1 -1
- package/dist/websocket/index.js +4 -4
- package/dist/websocket/index.js.map +1 -1
- package/package.json +160 -156
- package/src/api/audits/controllers/AuditController.ts +186 -0
- package/src/api/audits/entities/audits.ts +132 -0
- package/src/api/audits/index.browser.ts +18 -0
- package/src/api/audits/index.ts +58 -0
- package/src/api/audits/primitives/$audit.ts +159 -0
- package/src/api/audits/schemas/auditQuerySchema.ts +23 -0
- package/src/api/audits/schemas/auditResourceSchema.ts +9 -0
- package/src/api/audits/schemas/createAuditSchema.ts +27 -0
- package/src/api/audits/services/AuditService.ts +412 -0
- package/src/{api-files → api/files}/index.ts +1 -0
- package/src/api/parameters/controllers/ConfigController.ts +324 -0
- package/src/api/parameters/entities/parameters.ts +113 -0
- package/src/api/parameters/index.ts +60 -0
- package/src/api/parameters/primitives/$config.ts +351 -0
- package/src/api/parameters/schedulers/ConfigActivationScheduler.ts +30 -0
- package/src/api/parameters/services/ConfigStore.ts +491 -0
- package/src/{api-users → api/users}/atoms/realmAuthSettingsAtom.ts +19 -0
- package/src/{api-users → api/users}/controllers/UserRealmController.ts +0 -2
- package/src/{api-users → api/users}/index.ts +2 -0
- package/src/{api-users → api/users}/primitives/$userRealm.ts +18 -3
- package/src/{api-users → api/users}/providers/UserRealmProvider.ts +12 -10
- package/src/{api-users → api/users}/services/RegistrationService.ts +2 -1
- package/src/{api-users → api/users}/services/SessionService.ts +4 -0
- package/src/{api-users → api/users}/services/UserService.ts +3 -0
- package/src/{api-verifications → api/verifications}/index.ts +9 -1
- package/src/bin/index.ts +1 -0
- package/src/cli/apps/AlephaPackageBuilderCli.ts +73 -48
- package/src/cli/assets/appRouterTs.ts +1 -1
- package/src/cli/assets/biomeJson.ts +2 -2
- package/src/cli/assets/dummySpecTs.ts +7 -0
- package/src/cli/assets/editorconfig.ts +13 -0
- package/src/cli/assets/indexHtml.ts +1 -1
- package/src/cli/assets/mainBrowserTs.ts +1 -1
- package/src/cli/assets/mainTs.ts +14 -0
- package/src/cli/assets/viteConfigTs.ts +1 -1
- package/src/cli/commands/BiomeCommands.ts +2 -0
- package/src/cli/commands/CoreCommands.ts +38 -15
- package/src/cli/commands/VerifyCommands.ts +6 -2
- package/src/cli/commands/ViteCommands.ts +28 -18
- package/src/cli/services/AlephaCliUtils.ts +243 -37
- package/src/command/helpers/Asker.ts +0 -1
- package/src/command/primitives/$command.ts +67 -0
- package/src/command/providers/CliProvider.ts +39 -8
- package/src/core/Alepha.ts +40 -30
- package/src/core/helpers/jsonSchemaToTypeBox.ts +307 -0
- package/src/core/index.shared.ts +1 -0
- package/src/core/index.ts +30 -3
- package/src/core/providers/EventManager.ts +1 -1
- package/src/core/providers/SchemaValidator.ts +1 -1
- package/src/core/providers/StateManager.ts +23 -12
- package/src/core/providers/TypeProvider.ts +26 -34
- package/src/logger/index.ts +8 -6
- package/src/logger/primitives/$logger.ts +1 -1
- package/src/logger/providers/{SimpleFormatterProvider.ts → PrettyFormatterProvider.ts} +10 -1
- package/src/orm/index.ts +6 -0
- package/src/orm/services/PgRelationManager.ts +2 -2
- package/src/orm/services/PostgresModelBuilder.ts +11 -7
- package/src/orm/services/Repository.ts +16 -7
- package/src/orm/services/SqliteModelBuilder.ts +10 -0
- package/src/queue/{index.ts → core/index.ts} +2 -3
- package/src/queue/{primitives → core/primitives}/$queue.ts +17 -162
- package/src/queue/core/providers/MemoryQueueProvider.ts +19 -0
- package/src/queue/core/providers/QueueProvider.ts +23 -0
- package/src/queue/core/providers/WorkerProvider.ts +244 -0
- package/src/queue/redis/providers/RedisQueueProvider.ts +31 -0
- package/src/{server-auth → server/auth}/primitives/$auth.ts +7 -0
- package/src/{server-auth → server/auth}/providers/ServerAuthProvider.ts +51 -8
- package/src/{server-cookies → server/cookies}/index.ts +2 -1
- package/src/server/{index.ts → core/index.ts} +7 -0
- package/src/server/{primitives → core/primitives}/$action.ts +10 -1
- package/src/server/{providers → core/providers}/ServerBodyParserProvider.ts +11 -5
- package/src/server/{providers → core/providers}/ServerRouterProvider.ts +13 -7
- package/src/{server-rate-limit → server/rate-limit}/index.ts +1 -1
- package/src/{server-swagger → server/swagger}/providers/ServerSwaggerProvider.ts +1 -0
- package/src/thread/primitives/$thread.ts +2 -2
- package/src/vite/index.ts +0 -2
- package/src/vite/tasks/buildServer.ts +3 -4
- package/src/vite/tasks/copyAssets.ts +32 -8
- package/src/vite/tasks/generateCloudflare.ts +35 -19
- package/src/vite/tasks/generateDocker.ts +18 -4
- package/src/vite/tasks/generateSitemap.ts +5 -7
- package/src/vite/tasks/generateVercel.ts +76 -41
- package/src/vite/tasks/runAlepha.ts +16 -1
- package/src/websocket/providers/NodeWebSocketServerProvider.ts +3 -11
- package/src/websocket/services/WebSocketClient.ts +3 -3
- package/dist/api-files/index.browser.js.map +0 -1
- package/dist/api-files/index.js.map +0 -1
- package/dist/api-jobs/index.browser.js.map +0 -1
- package/dist/api-jobs/index.js.map +0 -1
- package/dist/api-notifications/index.browser.js.map +0 -1
- package/dist/api-notifications/index.d.ts +0 -327
- package/dist/api-notifications/index.js.map +0 -1
- package/dist/api-parameters/index.browser.js +0 -29
- package/dist/api-parameters/index.browser.js.map +0 -1
- package/dist/api-parameters/index.d.ts +0 -83
- package/dist/api-parameters/index.js +0 -63
- package/dist/api-parameters/index.js.map +0 -1
- package/dist/api-users/index.browser.js.map +0 -1
- package/dist/api-users/index.js.map +0 -1
- package/dist/api-verifications/index.browser.js.map +0 -1
- package/dist/api-verifications/index.d.ts +0 -229
- package/dist/api-verifications/index.js.map +0 -1
- package/dist/cache/index.js.map +0 -1
- package/dist/cache-redis/index.js.map +0 -1
- package/dist/cli/dist-BlfFtOk2.js +0 -2770
- package/dist/cli/dist-BlfFtOk2.js.map +0 -1
- package/dist/lock/index.js.map +0 -1
- package/dist/lock-redis/index.js.map +0 -1
- package/dist/queue/index.d.ts +0 -1265
- package/dist/queue/index.js +0 -1037
- package/dist/queue/index.js.map +0 -1
- package/dist/queue-redis/index.d.ts +0 -82
- package/dist/queue-redis/index.js +0 -872
- package/dist/queue-redis/index.js.map +0 -1
- package/dist/server/index.browser.js.map +0 -1
- package/dist/server/index.js.map +0 -1
- package/dist/server-auth/index.browser.js.map +0 -1
- package/dist/server-auth/index.js +0 -1943
- package/dist/server-auth/index.js.map +0 -1
- package/dist/server-cache/index.js.map +0 -1
- package/dist/server-compress/index.js.map +0 -1
- package/dist/server-cookies/index.browser.js.map +0 -1
- package/dist/server-cookies/index.js.map +0 -1
- package/dist/server-cors/index.js.map +0 -1
- package/dist/server-health/index.js.map +0 -1
- package/dist/server-helmet/index.js.map +0 -1
- package/dist/server-links/index.browser.js.map +0 -1
- package/dist/server-links/index.js.map +0 -1
- package/dist/server-metrics/index.js +0 -4532
- package/dist/server-metrics/index.js.map +0 -1
- package/dist/server-multipart/index.js.map +0 -1
- package/dist/server-proxy/index.js.map +0 -1
- package/dist/server-rate-limit/index.js.map +0 -1
- package/dist/server-security/index.browser.js.map +0 -1
- package/dist/server-security/index.js.map +0 -1
- package/dist/server-static/index.js.map +0 -1
- package/dist/server-swagger/index.js.map +0 -1
- package/dist/topic/index.js.map +0 -1
- package/dist/topic-redis/index.js.map +0 -1
- package/src/api-parameters/controllers/ParameterController.ts +0 -45
- package/src/api-parameters/entities/parameters.ts +0 -30
- package/src/api-parameters/index.ts +0 -21
- package/src/api-parameters/primitives/$config.ts +0 -79
- package/src/api-parameters/services/ParameterStore.ts +0 -23
- package/src/queue/interfaces/QueueJob.ts +0 -459
- package/src/queue/providers/MemoryQueueProvider.ts +0 -850
- package/src/queue/providers/QueueProvider.ts +0 -319
- package/src/queue/providers/WorkerProvider.ts +0 -344
- package/src/queue-redis/providers/RedisQueueProvider.ts +0 -1209
- /package/src/{api-files → api/files}/controllers/FileController.ts +0 -0
- /package/src/{api-files → api/files}/controllers/StorageStatsController.ts +0 -0
- /package/src/{api-files → api/files}/entities/files.ts +0 -0
- /package/src/{api-files → api/files}/index.browser.ts +0 -0
- /package/src/{api-files → api/files}/jobs/FileJobs.ts +0 -0
- /package/src/{api-files → api/files}/schemas/fileQuerySchema.ts +0 -0
- /package/src/{api-files → api/files}/schemas/fileResourceSchema.ts +0 -0
- /package/src/{api-files → api/files}/schemas/storageStatsSchema.ts +0 -0
- /package/src/{api-files → api/files}/services/FileService.ts +0 -0
- /package/src/{api-jobs → api/jobs}/controllers/JobController.ts +0 -0
- /package/src/{api-jobs → api/jobs}/entities/jobExecutions.ts +0 -0
- /package/src/{api-jobs → api/jobs}/index.browser.ts +0 -0
- /package/src/{api-jobs → api/jobs}/index.ts +0 -0
- /package/src/{api-jobs → api/jobs}/primitives/$job.ts +0 -0
- /package/src/{api-jobs → api/jobs}/providers/JobProvider.ts +0 -0
- /package/src/{api-jobs → api/jobs}/schemas/jobExecutionQuerySchema.ts +0 -0
- /package/src/{api-jobs → api/jobs}/schemas/jobExecutionResourceSchema.ts +0 -0
- /package/src/{api-jobs → api/jobs}/schemas/triggerJobSchema.ts +0 -0
- /package/src/{api-jobs → api/jobs}/services/JobService.ts +0 -0
- /package/src/{api-notifications → api/notifications}/controllers/NotificationController.ts +0 -0
- /package/src/{api-notifications → api/notifications}/entities/notifications.ts +0 -0
- /package/src/{api-notifications → api/notifications}/index.browser.ts +0 -0
- /package/src/{api-notifications → api/notifications}/index.ts +0 -0
- /package/src/{api-notifications → api/notifications}/jobs/NotificationJobs.ts +0 -0
- /package/src/{api-notifications → api/notifications}/primitives/$notification.ts +0 -0
- /package/src/{api-notifications → api/notifications}/queues/NotificationQueues.ts +0 -0
- /package/src/{api-notifications → api/notifications}/schemas/notificationContactPreferencesSchema.ts +0 -0
- /package/src/{api-notifications → api/notifications}/schemas/notificationContactSchema.ts +0 -0
- /package/src/{api-notifications → api/notifications}/schemas/notificationCreateSchema.ts +0 -0
- /package/src/{api-notifications → api/notifications}/schemas/notificationQuerySchema.ts +0 -0
- /package/src/{api-notifications → api/notifications}/services/NotificationSenderService.ts +0 -0
- /package/src/{api-notifications → api/notifications}/services/NotificationService.ts +0 -0
- /package/src/{api-parameters → api/parameters}/index.browser.ts +0 -0
- /package/src/{api-users → api/users}/controllers/IdentityController.ts +0 -0
- /package/src/{api-users → api/users}/controllers/SessionController.ts +0 -0
- /package/src/{api-users → api/users}/controllers/UserController.ts +0 -0
- /package/src/{api-users → api/users}/entities/identities.ts +0 -0
- /package/src/{api-users → api/users}/entities/sessions.ts +0 -0
- /package/src/{api-users → api/users}/entities/users.ts +0 -0
- /package/src/{api-users → api/users}/index.browser.ts +0 -0
- /package/src/{api-users → api/users}/notifications/UserNotifications.ts +0 -0
- /package/src/{api-users → api/users}/schemas/completePasswordResetRequestSchema.ts +0 -0
- /package/src/{api-users → api/users}/schemas/completeRegistrationRequestSchema.ts +0 -0
- /package/src/{api-users → api/users}/schemas/createUserSchema.ts +0 -0
- /package/src/{api-users → api/users}/schemas/identityQuerySchema.ts +0 -0
- /package/src/{api-users → api/users}/schemas/identityResourceSchema.ts +0 -0
- /package/src/{api-users → api/users}/schemas/loginSchema.ts +0 -0
- /package/src/{api-users → api/users}/schemas/passwordResetIntentResponseSchema.ts +0 -0
- /package/src/{api-users → api/users}/schemas/registerQuerySchema.ts +0 -0
- /package/src/{api-users → api/users}/schemas/registerRequestSchema.ts +0 -0
- /package/src/{api-users → api/users}/schemas/registerResponseSchema.ts +0 -0
- /package/src/{api-users → api/users}/schemas/registerSchema.ts +0 -0
- /package/src/{api-users → api/users}/schemas/registrationIntentResponseSchema.ts +0 -0
- /package/src/{api-users → api/users}/schemas/resetPasswordSchema.ts +0 -0
- /package/src/{api-users → api/users}/schemas/sessionQuerySchema.ts +0 -0
- /package/src/{api-users → api/users}/schemas/sessionResourceSchema.ts +0 -0
- /package/src/{api-users → api/users}/schemas/updateUserSchema.ts +0 -0
- /package/src/{api-users → api/users}/schemas/userQuerySchema.ts +0 -0
- /package/src/{api-users → api/users}/schemas/userRealmConfigSchema.ts +0 -0
- /package/src/{api-users → api/users}/schemas/userResourceSchema.ts +0 -0
- /package/src/{api-users → api/users}/services/CredentialService.ts +0 -0
- /package/src/{api-users → api/users}/services/IdentityService.ts +0 -0
- /package/src/{api-users → api/users}/services/SessionCrudService.ts +0 -0
- /package/src/{api-verifications → api/verifications}/controllers/VerificationController.ts +0 -0
- /package/src/{api-verifications → api/verifications}/entities/verifications.ts +0 -0
- /package/src/{api-verifications → api/verifications}/index.browser.ts +0 -0
- /package/src/{api-verifications → api/verifications}/jobs/VerificationJobs.ts +0 -0
- /package/src/{api-verifications → api/verifications}/parameters/VerificationParameters.ts +0 -0
- /package/src/{api-verifications → api/verifications}/schemas/requestVerificationCodeResponseSchema.ts +0 -0
- /package/src/{api-verifications → api/verifications}/schemas/validateVerificationCodeResponseSchema.ts +0 -0
- /package/src/{api-verifications → api/verifications}/schemas/verificationSettingsSchema.ts +0 -0
- /package/src/{api-verifications → api/verifications}/schemas/verificationTypeEnumSchema.ts +0 -0
- /package/src/{api-verifications → api/verifications}/services/VerificationService.ts +0 -0
- /package/src/cache/{errors → core/errors}/CacheError.ts +0 -0
- /package/src/cache/{index.ts → core/index.ts} +0 -0
- /package/src/cache/{primitives → core/primitives}/$cache.ts +0 -0
- /package/src/cache/{providers → core/providers}/CacheProvider.ts +0 -0
- /package/src/cache/{providers → core/providers}/MemoryCacheProvider.ts +0 -0
- /package/src/{cache-redis → cache/redis}/index.ts +0 -0
- /package/src/{cache-redis → cache/redis}/providers/RedisCacheProvider.ts +0 -0
- /package/src/lock/{index.ts → core/index.ts} +0 -0
- /package/src/lock/{primitives → core/primitives}/$lock.ts +0 -0
- /package/src/lock/{providers → core/providers}/LockProvider.ts +0 -0
- /package/src/lock/{providers → core/providers}/LockTopicProvider.ts +0 -0
- /package/src/lock/{providers → core/providers}/MemoryLockProvider.ts +0 -0
- /package/src/{lock-redis → lock/redis}/index.ts +0 -0
- /package/src/{lock-redis → lock/redis}/providers/RedisLockProvider.ts +0 -0
- /package/src/queue/{primitives → core/primitives}/$consumer.ts +0 -0
- /package/src/{queue-redis → queue/redis}/index.ts +0 -0
- /package/src/{server-auth → server/auth}/constants/routes.ts +0 -0
- /package/src/{server-auth → server/auth}/index.browser.ts +0 -0
- /package/src/{server-auth → server/auth}/index.shared.ts +0 -0
- /package/src/{server-auth → server/auth}/index.ts +0 -0
- /package/src/{server-auth → server/auth}/primitives/$authApple.ts +0 -0
- /package/src/{server-auth → server/auth}/primitives/$authCredentials.ts +0 -0
- /package/src/{server-auth → server/auth}/primitives/$authGithub.ts +0 -0
- /package/src/{server-auth → server/auth}/primitives/$authGoogle.ts +0 -0
- /package/src/{server-auth → server/auth}/schemas/authenticationProviderSchema.ts +0 -0
- /package/src/{server-auth → server/auth}/schemas/tokenResponseSchema.ts +0 -0
- /package/src/{server-auth → server/auth}/schemas/tokensSchema.ts +0 -0
- /package/src/{server-auth → server/auth}/schemas/userinfoResponseSchema.ts +0 -0
- /package/src/{server-cache → server/cache}/index.ts +0 -0
- /package/src/{server-cache → server/cache}/providers/ServerCacheProvider.ts +0 -0
- /package/src/{server-compress → server/compress}/index.ts +0 -0
- /package/src/{server-compress → server/compress}/providers/ServerCompressProvider.ts +0 -0
- /package/src/{server-cookies → server/cookies}/index.browser.ts +0 -0
- /package/src/{server-cookies → server/cookies}/primitives/$cookie.browser.ts +0 -0
- /package/src/{server-cookies → server/cookies}/primitives/$cookie.ts +0 -0
- /package/src/{server-cookies → server/cookies}/providers/ServerCookiesProvider.ts +0 -0
- /package/src/{server-cookies → server/cookies}/services/CookieParser.ts +0 -0
- /package/src/server/{constants → core/constants}/routeMethods.ts +0 -0
- /package/src/server/{errors → core/errors}/BadRequestError.ts +0 -0
- /package/src/server/{errors → core/errors}/ConflictError.ts +0 -0
- /package/src/server/{errors → core/errors}/ForbiddenError.ts +0 -0
- /package/src/server/{errors → core/errors}/HttpError.ts +0 -0
- /package/src/server/{errors → core/errors}/NotFoundError.ts +0 -0
- /package/src/server/{errors → core/errors}/UnauthorizedError.ts +0 -0
- /package/src/server/{errors → core/errors}/ValidationError.ts +0 -0
- /package/src/server/{helpers → core/helpers}/ServerReply.ts +0 -0
- /package/src/server/{helpers → core/helpers}/isMultipart.ts +0 -0
- /package/src/server/{index.browser.ts → core/index.browser.ts} +0 -0
- /package/src/server/{index.shared.ts → core/index.shared.ts} +0 -0
- /package/src/server/{interfaces → core/interfaces}/ServerRequest.ts +0 -0
- /package/src/server/{primitives → core/primitives}/$route.ts +0 -0
- /package/src/server/{providers → core/providers}/BunHttpServerProvider.ts +0 -0
- /package/src/server/{providers → core/providers}/NodeHttpServerProvider.ts +0 -0
- /package/src/server/{providers → core/providers}/ServerLoggerProvider.ts +0 -0
- /package/src/server/{providers → core/providers}/ServerNotReadyProvider.ts +0 -0
- /package/src/server/{providers → core/providers}/ServerProvider.ts +0 -0
- /package/src/server/{providers → core/providers}/ServerTimingProvider.ts +0 -0
- /package/src/server/{schemas → core/schemas}/errorSchema.ts +0 -0
- /package/src/server/{schemas → core/schemas}/okSchema.ts +0 -0
- /package/src/server/{services → core/services}/HttpClient.ts +0 -0
- /package/src/server/{services → core/services}/ServerRequestParser.ts +0 -0
- /package/src/server/{services → core/services}/UserAgentParser.ts +0 -0
- /package/src/{server-cors → server/cors}/index.ts +0 -0
- /package/src/{server-cors → server/cors}/primitives/$cors.ts +0 -0
- /package/src/{server-cors → server/cors}/providers/ServerCorsProvider.ts +0 -0
- /package/src/{server-health → server/health}/index.ts +0 -0
- /package/src/{server-health → server/health}/providers/ServerHealthProvider.ts +0 -0
- /package/src/{server-health → server/health}/schemas/healthSchema.ts +0 -0
- /package/src/{server-helmet → server/helmet}/index.ts +0 -0
- /package/src/{server-helmet → server/helmet}/providers/ServerHelmetProvider.ts +0 -0
- /package/src/{server-links → server/links}/index.browser.ts +0 -0
- /package/src/{server-links → server/links}/index.ts +0 -0
- /package/src/{server-links → server/links}/primitives/$client.ts +0 -0
- /package/src/{server-links → server/links}/primitives/$remote.ts +0 -0
- /package/src/{server-links → server/links}/providers/LinkProvider.ts +0 -0
- /package/src/{server-links → server/links}/providers/RemotePrimitiveProvider.ts +0 -0
- /package/src/{server-links → server/links}/providers/ServerLinksProvider.ts +0 -0
- /package/src/{server-links → server/links}/schemas/apiLinksResponseSchema.ts +0 -0
- /package/src/{server-metrics → server/metrics}/index.ts +0 -0
- /package/src/{server-metrics → server/metrics}/providers/ServerMetricsProvider.ts +0 -0
- /package/src/{server-multipart → server/multipart}/index.ts +0 -0
- /package/src/{server-multipart → server/multipart}/providers/ServerMultipartProvider.ts +0 -0
- /package/src/{server-proxy → server/proxy}/index.ts +0 -0
- /package/src/{server-proxy → server/proxy}/primitives/$proxy.ts +0 -0
- /package/src/{server-proxy → server/proxy}/providers/ServerProxyProvider.ts +0 -0
- /package/src/{server-rate-limit → server/rate-limit}/primitives/$rateLimit.ts +0 -0
- /package/src/{server-rate-limit → server/rate-limit}/providers/ServerRateLimitProvider.ts +0 -0
- /package/src/{server-security → server/security}/index.browser.ts +0 -0
- /package/src/{server-security → server/security}/index.ts +0 -0
- /package/src/{server-security → server/security}/primitives/$basicAuth.ts +0 -0
- /package/src/{server-security → server/security}/providers/ServerBasicAuthProvider.ts +0 -0
- /package/src/{server-security → server/security}/providers/ServerSecurityProvider.ts +0 -0
- /package/src/{server-static → server/static}/index.ts +0 -0
- /package/src/{server-static → server/static}/primitives/$serve.ts +0 -0
- /package/src/{server-static → server/static}/providers/ServerStaticProvider.ts +0 -0
- /package/src/{server-swagger → server/swagger}/index.ts +0 -0
- /package/src/{server-swagger → server/swagger}/primitives/$swagger.ts +0 -0
- /package/src/topic/{errors → core/errors}/TopicTimeoutError.ts +0 -0
- /package/src/topic/{index.ts → core/index.ts} +0 -0
- /package/src/topic/{primitives → core/primitives}/$subscriber.ts +0 -0
- /package/src/topic/{primitives → core/primitives}/$topic.ts +0 -0
- /package/src/topic/{providers → core/providers}/MemoryTopicProvider.ts +0 -0
- /package/src/topic/{providers → core/providers}/TopicProvider.ts +0 -0
- /package/src/{topic-redis → topic/redis}/index.ts +0 -0
- /package/src/{topic-redis → topic/redis}/providers/RedisTopicProvider.ts +0 -0
|
@@ -8,7 +8,7 @@ import { $cache } from "alepha/cache";
|
|
|
8
8
|
import { createServer } from "node:http";
|
|
9
9
|
import { createBrotliDecompress, createGunzip, createInflate } from "node:zlib";
|
|
10
10
|
|
|
11
|
-
//#region ../../src/server/helpers/isMultipart.ts
|
|
11
|
+
//#region ../../src/server/core/helpers/isMultipart.ts
|
|
12
12
|
/**
|
|
13
13
|
* Checks if the route has multipart/form-data request body.
|
|
14
14
|
*/
|
|
@@ -22,7 +22,7 @@ const isMultipart = (options) => {
|
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
//#endregion
|
|
25
|
-
//#region ../../src/server/helpers/ServerReply.ts
|
|
25
|
+
//#region ../../src/server/core/helpers/ServerReply.ts
|
|
26
26
|
/**
|
|
27
27
|
* Helper for building server replies.
|
|
28
28
|
*/
|
|
@@ -61,7 +61,7 @@ var ServerReply = class {
|
|
|
61
61
|
};
|
|
62
62
|
|
|
63
63
|
//#endregion
|
|
64
|
-
//#region ../../src/server/errors/HttpError.ts
|
|
64
|
+
//#region ../../src/server/core/errors/HttpError.ts
|
|
65
65
|
const isHttpError = (error, status) => {
|
|
66
66
|
if (!(!!error && typeof error === "object" && "message" in error && typeof error.message === "string" && "status" in error && typeof error.status === "number")) return false;
|
|
67
67
|
if (status) return error.status === status;
|
|
@@ -122,7 +122,7 @@ const errorNameByStatus = {
|
|
|
122
122
|
};
|
|
123
123
|
|
|
124
124
|
//#endregion
|
|
125
|
-
//#region ../../src/server/errors/ValidationError.ts
|
|
125
|
+
//#region ../../src/server/core/errors/ValidationError.ts
|
|
126
126
|
var ValidationError = class extends HttpError {
|
|
127
127
|
constructor(message = "Validation has failed", cause) {
|
|
128
128
|
super({
|
|
@@ -133,7 +133,7 @@ var ValidationError = class extends HttpError {
|
|
|
133
133
|
};
|
|
134
134
|
|
|
135
135
|
//#endregion
|
|
136
|
-
//#region ../../src/server/services/UserAgentParser.ts
|
|
136
|
+
//#region ../../src/server/core/services/UserAgentParser.ts
|
|
137
137
|
/**
|
|
138
138
|
* Simple User-Agent parser to detect OS, browser, and device type.
|
|
139
139
|
* This parser is not exhaustive and may not cover all edge cases.
|
|
@@ -205,7 +205,7 @@ var UserAgentParser = class {
|
|
|
205
205
|
};
|
|
206
206
|
|
|
207
207
|
//#endregion
|
|
208
|
-
//#region ../../src/server/services/ServerRequestParser.ts
|
|
208
|
+
//#region ../../src/server/core/services/ServerRequestParser.ts
|
|
209
209
|
var ServerRequestParser = class {
|
|
210
210
|
alepha = $inject(Alepha);
|
|
211
211
|
userAgentParser = $inject(UserAgentParser);
|
|
@@ -245,7 +245,7 @@ var ServerRequestParser = class {
|
|
|
245
245
|
};
|
|
246
246
|
|
|
247
247
|
//#endregion
|
|
248
|
-
//#region ../../src/server/providers/ServerTimingProvider.ts
|
|
248
|
+
//#region ../../src/server/core/providers/ServerTimingProvider.ts
|
|
249
249
|
var ServerTimingProvider = class {
|
|
250
250
|
log = $logger();
|
|
251
251
|
alepha = $inject(Alepha);
|
|
@@ -315,7 +315,7 @@ var ServerTimingProvider = class {
|
|
|
315
315
|
};
|
|
316
316
|
|
|
317
317
|
//#endregion
|
|
318
|
-
//#region ../../src/server/providers/ServerRouterProvider.ts
|
|
318
|
+
//#region ../../src/server/core/providers/ServerRouterProvider.ts
|
|
319
319
|
/**
|
|
320
320
|
* Main router for all routes on the server side.
|
|
321
321
|
*
|
|
@@ -510,7 +510,9 @@ var ServerRouterProvider = class extends RouterProvider {
|
|
|
510
510
|
} catch (error) {
|
|
511
511
|
throw new ValidationError("Invalid request header", error);
|
|
512
512
|
}
|
|
513
|
-
if (route.schema?.body)
|
|
513
|
+
if (route.schema?.body) if (t.schema.isString(route.schema.body)) {
|
|
514
|
+
if (typeof request.body !== "string") throw new ValidationError("Request body is not a string");
|
|
515
|
+
} else try {
|
|
514
516
|
request.body = this.alepha.codec.decode(route.schema.body, request.body);
|
|
515
517
|
} catch (error) {
|
|
516
518
|
throw new ValidationError("Invalid request body", error);
|
|
@@ -519,7 +521,7 @@ var ServerRouterProvider = class extends RouterProvider {
|
|
|
519
521
|
};
|
|
520
522
|
|
|
521
523
|
//#endregion
|
|
522
|
-
//#region ../../src/server/providers/ServerProvider.ts
|
|
524
|
+
//#region ../../src/server/core/providers/ServerProvider.ts
|
|
523
525
|
/**
|
|
524
526
|
* Base server provider to handle incoming requests and route them.
|
|
525
527
|
*
|
|
@@ -703,7 +705,7 @@ var ServerProvider = class {
|
|
|
703
705
|
};
|
|
704
706
|
|
|
705
707
|
//#endregion
|
|
706
|
-
//#region ../../src/server/schemas/errorSchema.ts
|
|
708
|
+
//#region ../../src/server/core/schemas/errorSchema.ts
|
|
707
709
|
const errorSchema = t.object({
|
|
708
710
|
error: t.text({ description: "HTTP error name" }),
|
|
709
711
|
status: t.integer({ description: "HTTP status code" }),
|
|
@@ -729,7 +731,7 @@ const errorSchema = t.object({
|
|
|
729
731
|
});
|
|
730
732
|
|
|
731
733
|
//#endregion
|
|
732
|
-
//#region ../../src/server/services/HttpClient.ts
|
|
734
|
+
//#region ../../src/server/core/services/HttpClient.ts
|
|
733
735
|
var HttpClient = class {
|
|
734
736
|
log = $logger();
|
|
735
737
|
alepha = $inject(Alepha);
|
|
@@ -941,7 +943,7 @@ var HttpClient = class {
|
|
|
941
943
|
};
|
|
942
944
|
|
|
943
945
|
//#endregion
|
|
944
|
-
//#region ../../src/server/primitives/$action.ts
|
|
946
|
+
//#region ../../src/server/core/primitives/$action.ts
|
|
945
947
|
/**
|
|
946
948
|
* Creates a server action primitive for defining type-safe HTTP endpoints.
|
|
947
949
|
*
|
|
@@ -957,7 +959,16 @@ var HttpClient = class {
|
|
|
957
959
|
* - Automatic content-type handling (JSON, form-data, plain text)
|
|
958
960
|
*
|
|
959
961
|
* **URL Generation**
|
|
960
|
-
*
|
|
962
|
+
*
|
|
963
|
+
* **Important:** All `$action` paths are automatically prefixed with `/api`.
|
|
964
|
+
*
|
|
965
|
+
* ```ts
|
|
966
|
+
* $action({ path: "/users" }) // → GET /api/users
|
|
967
|
+
* $action({ path: "/users/:id" }) // → GET /api/users/:id
|
|
968
|
+
* $action({ path: "/hello" }) // → GET /api/hello
|
|
969
|
+
* ```
|
|
970
|
+
*
|
|
971
|
+
* This prefix is configurable via the `SERVER_API_PREFIX` environment variable.
|
|
961
972
|
* HTTP method defaults to GET, or POST if body schema is provided.
|
|
962
973
|
*
|
|
963
974
|
* **Common Use Cases**
|
|
@@ -1137,7 +1148,7 @@ var ActionPrimitive = class extends Primitive {
|
|
|
1137
1148
|
$action[KIND] = ActionPrimitive;
|
|
1138
1149
|
|
|
1139
1150
|
//#endregion
|
|
1140
|
-
//#region ../../src/server/primitives/$route.ts
|
|
1151
|
+
//#region ../../src/server/core/primitives/$route.ts
|
|
1141
1152
|
/**
|
|
1142
1153
|
* Create a basic endpoint.
|
|
1143
1154
|
*
|
|
@@ -1158,7 +1169,7 @@ var RoutePrimitive = class extends Primitive {
|
|
|
1158
1169
|
$route[KIND] = RoutePrimitive;
|
|
1159
1170
|
|
|
1160
1171
|
//#endregion
|
|
1161
|
-
//#region ../../src/server/providers/BunHttpServerProvider.ts
|
|
1172
|
+
//#region ../../src/server/core/providers/BunHttpServerProvider.ts
|
|
1162
1173
|
const envSchema$2 = t.object({
|
|
1163
1174
|
SERVER_PORT: t.integer({
|
|
1164
1175
|
default: 3e3,
|
|
@@ -1255,7 +1266,7 @@ var BunHttpServerProvider = class extends ServerProvider {
|
|
|
1255
1266
|
};
|
|
1256
1267
|
|
|
1257
1268
|
//#endregion
|
|
1258
|
-
//#region ../../src/server/providers/NodeHttpServerProvider.ts
|
|
1269
|
+
//#region ../../src/server/core/providers/NodeHttpServerProvider.ts
|
|
1259
1270
|
const envSchema$1 = t.object({
|
|
1260
1271
|
SERVER_PORT: t.integer({
|
|
1261
1272
|
default: 3e3,
|
|
@@ -1338,7 +1349,7 @@ var NodeHttpServerProvider = class extends ServerProvider {
|
|
|
1338
1349
|
};
|
|
1339
1350
|
|
|
1340
1351
|
//#endregion
|
|
1341
|
-
//#region ../../src/server/providers/ServerBodyParserProvider.ts
|
|
1352
|
+
//#region ../../src/server/core/providers/ServerBodyParserProvider.ts
|
|
1342
1353
|
const envSchema = t.object({
|
|
1343
1354
|
SERVER_BODY_PARSER_INFLATE: t.boolean({
|
|
1344
1355
|
default: true,
|
|
@@ -1363,7 +1374,7 @@ var ServerBodyParserProvider = class {
|
|
|
1363
1374
|
else if (request.raw.node?.req) stream = ReadableStream$1.from(request.raw.node.req);
|
|
1364
1375
|
if (!stream) return;
|
|
1365
1376
|
if (route.schema?.body) try {
|
|
1366
|
-
const body = await this.parse(stream, request.headers);
|
|
1377
|
+
const body = await this.parse(stream, request.headers, route.schema.body);
|
|
1367
1378
|
if (body) request.body = body;
|
|
1368
1379
|
} catch (error) {
|
|
1369
1380
|
if (error instanceof HttpError) throw error;
|
|
@@ -1374,12 +1385,12 @@ var ServerBodyParserProvider = class {
|
|
|
1374
1385
|
}
|
|
1375
1386
|
}
|
|
1376
1387
|
});
|
|
1377
|
-
async parse(stream, headers) {
|
|
1388
|
+
async parse(stream, headers, schema) {
|
|
1378
1389
|
const contentType = headers["content-type"];
|
|
1379
1390
|
const contentEncoding = headers["content-encoding"];
|
|
1380
1391
|
if (!contentType) return void 0;
|
|
1392
|
+
if (contentType.startsWith("text/plain") || t.schema.isString(schema)) return this.parseText(stream, contentEncoding);
|
|
1381
1393
|
if (contentType.startsWith("application/json")) return this.parseJson(stream, contentEncoding);
|
|
1382
|
-
if (contentType.startsWith("text/plain")) return this.parseText(stream, contentEncoding);
|
|
1383
1394
|
if (contentType.startsWith("application/x-www-form-urlencoded")) return this.parseUrlEncoded(stream, contentEncoding);
|
|
1384
1395
|
}
|
|
1385
1396
|
async parseText(stream, contentEncoding) {
|
|
@@ -1453,7 +1464,7 @@ var ServerBodyParserProvider = class {
|
|
|
1453
1464
|
};
|
|
1454
1465
|
|
|
1455
1466
|
//#endregion
|
|
1456
|
-
//#region ../../src/server/providers/ServerLoggerProvider.ts
|
|
1467
|
+
//#region ../../src/server/core/providers/ServerLoggerProvider.ts
|
|
1457
1468
|
var ServerLoggerProvider = class {
|
|
1458
1469
|
log = $logger();
|
|
1459
1470
|
alepha = $inject(Alepha);
|
|
@@ -1499,7 +1510,7 @@ var ServerLoggerProvider = class {
|
|
|
1499
1510
|
};
|
|
1500
1511
|
|
|
1501
1512
|
//#endregion
|
|
1502
|
-
//#region ../../src/server/providers/ServerNotReadyProvider.ts
|
|
1513
|
+
//#region ../../src/server/core/providers/ServerNotReadyProvider.ts
|
|
1503
1514
|
/**
|
|
1504
1515
|
* On every request, this provider checks if the server is ready.
|
|
1505
1516
|
*
|
|
@@ -1524,7 +1535,7 @@ var ServerNotReadyProvider = class {
|
|
|
1524
1535
|
};
|
|
1525
1536
|
|
|
1526
1537
|
//#endregion
|
|
1527
|
-
//#region ../../src/server/constants/routeMethods.ts
|
|
1538
|
+
//#region ../../src/server/core/constants/routeMethods.ts
|
|
1528
1539
|
const routeMethods = [
|
|
1529
1540
|
"GET",
|
|
1530
1541
|
"POST",
|
|
@@ -1538,7 +1549,7 @@ const routeMethods = [
|
|
|
1538
1549
|
];
|
|
1539
1550
|
|
|
1540
1551
|
//#endregion
|
|
1541
|
-
//#region ../../src/server/errors/BadRequestError.ts
|
|
1552
|
+
//#region ../../src/server/core/errors/BadRequestError.ts
|
|
1542
1553
|
var BadRequestError = class extends HttpError {
|
|
1543
1554
|
constructor(message = "Invalid request body", cause) {
|
|
1544
1555
|
super({
|
|
@@ -1549,7 +1560,7 @@ var BadRequestError = class extends HttpError {
|
|
|
1549
1560
|
};
|
|
1550
1561
|
|
|
1551
1562
|
//#endregion
|
|
1552
|
-
//#region ../../src/server/errors/ConflictError.ts
|
|
1563
|
+
//#region ../../src/server/core/errors/ConflictError.ts
|
|
1553
1564
|
var ConflictError = class extends HttpError {
|
|
1554
1565
|
constructor(message = "Entity already exists", cause) {
|
|
1555
1566
|
super({
|
|
@@ -1560,7 +1571,7 @@ var ConflictError = class extends HttpError {
|
|
|
1560
1571
|
};
|
|
1561
1572
|
|
|
1562
1573
|
//#endregion
|
|
1563
|
-
//#region ../../src/server/errors/ForbiddenError.ts
|
|
1574
|
+
//#region ../../src/server/core/errors/ForbiddenError.ts
|
|
1564
1575
|
var ForbiddenError = class extends HttpError {
|
|
1565
1576
|
constructor(message = "No permission to access this resource", cause) {
|
|
1566
1577
|
super({
|
|
@@ -1571,7 +1582,7 @@ var ForbiddenError = class extends HttpError {
|
|
|
1571
1582
|
};
|
|
1572
1583
|
|
|
1573
1584
|
//#endregion
|
|
1574
|
-
//#region ../../src/server/errors/NotFoundError.ts
|
|
1585
|
+
//#region ../../src/server/core/errors/NotFoundError.ts
|
|
1575
1586
|
var NotFoundError = class extends HttpError {
|
|
1576
1587
|
constructor(message = "Resource not found", cause) {
|
|
1577
1588
|
super({
|
|
@@ -1582,7 +1593,7 @@ var NotFoundError = class extends HttpError {
|
|
|
1582
1593
|
};
|
|
1583
1594
|
|
|
1584
1595
|
//#endregion
|
|
1585
|
-
//#region ../../src/server/errors/UnauthorizedError.ts
|
|
1596
|
+
//#region ../../src/server/core/errors/UnauthorizedError.ts
|
|
1586
1597
|
var UnauthorizedError = class extends HttpError {
|
|
1587
1598
|
name = "UnauthorizedError";
|
|
1588
1599
|
constructor(message = "Not allowed to access this resource", cause) {
|
|
@@ -1594,7 +1605,7 @@ var UnauthorizedError = class extends HttpError {
|
|
|
1594
1605
|
};
|
|
1595
1606
|
|
|
1596
1607
|
//#endregion
|
|
1597
|
-
//#region ../../src/server/schemas/okSchema.ts
|
|
1608
|
+
//#region ../../src/server/core/schemas/okSchema.ts
|
|
1598
1609
|
const okSchema = t.object({
|
|
1599
1610
|
ok: t.boolean({ description: "True when operation succeed" }),
|
|
1600
1611
|
id: t.optional(t.union([t.text(), t.integer()])),
|
|
@@ -1605,7 +1616,7 @@ const okSchema = t.object({
|
|
|
1605
1616
|
});
|
|
1606
1617
|
|
|
1607
1618
|
//#endregion
|
|
1608
|
-
//#region ../../src/server/index.ts
|
|
1619
|
+
//#region ../../src/server/core/index.ts
|
|
1609
1620
|
/**
|
|
1610
1621
|
* Provides high-performance HTTP server capabilities with declarative routing and action primitives.
|
|
1611
1622
|
*
|
|
@@ -1628,7 +1639,10 @@ const AlephaServer = $module({
|
|
|
1628
1639
|
ServerLoggerProvider,
|
|
1629
1640
|
ServerNotReadyProvider,
|
|
1630
1641
|
ServerTimingProvider,
|
|
1631
|
-
HttpClient
|
|
1642
|
+
HttpClient,
|
|
1643
|
+
UserAgentParser,
|
|
1644
|
+
ServerRequestParser,
|
|
1645
|
+
ServerRouterProvider
|
|
1632
1646
|
],
|
|
1633
1647
|
register: (alepha) => {
|
|
1634
1648
|
if (!alepha.isServerless() && !alepha.isViteDev()) if (alepha.isBun()) alepha.with({
|
|
@@ -1650,5 +1664,5 @@ const AlephaServer = $module({
|
|
|
1650
1664
|
});
|
|
1651
1665
|
|
|
1652
1666
|
//#endregion
|
|
1653
|
-
export { $action, $route, ActionPrimitive, AlephaServer, BadRequestError, BunHttpServerProvider, ConflictError, ForbiddenError, HttpClient, HttpError, NodeHttpServerProvider, NotFoundError, RoutePrimitive, ServerLoggerProvider, ServerNotReadyProvider, ServerProvider, ServerReply, ServerRouterProvider, ServerTimingProvider, UnauthorizedError, ValidationError, errorNameByStatus, errorSchema, isHttpError, isMultipart, okSchema, routeMethods };
|
|
1667
|
+
export { $action, $route, ActionPrimitive, AlephaServer, BadRequestError, BunHttpServerProvider, ConflictError, ForbiddenError, HttpClient, HttpError, NodeHttpServerProvider, NotFoundError, RoutePrimitive, ServerLoggerProvider, ServerNotReadyProvider, ServerProvider, ServerReply, ServerRouterProvider, ServerTimingProvider, UnauthorizedError, UserAgentParser, ValidationError, errorNameByStatus, errorSchema, isHttpError, isMultipart, okSchema, routeMethods };
|
|
1654
1668
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["properties: Record<string, any>","json: Record<string, unknown>","errorNameByStatus: Record<number, string>","os: UserAgentInfo[\"os\"]","browser: UserAgentInfo[\"browser\"]","device: UserAgentInfo[\"device\"]","NodeWebStream","NodeStream","query: Record<string, any>","request: ServerRequestData","headers: Record<string, string>","request: RequestInit","headers: Record<string, string>","fetchResponse: FetchResponse","options","envSchema","serverActionRequest: Partial<ServerRequest>","response: any","envSchema","envSchema","stream: ReadableStream | undefined","WebStream","result: Record<string, string>","chunks: Uint8Array[]","data: Record<string, string>"],"sources":["../../../src/server/core/helpers/isMultipart.ts","../../../src/server/core/helpers/ServerReply.ts","../../../src/server/core/errors/HttpError.ts","../../../src/server/core/errors/ValidationError.ts","../../../src/server/core/services/UserAgentParser.ts","../../../src/server/core/services/ServerRequestParser.ts","../../../src/server/core/providers/ServerTimingProvider.ts","../../../src/server/core/providers/ServerRouterProvider.ts","../../../src/server/core/providers/ServerProvider.ts","../../../src/server/core/schemas/errorSchema.ts","../../../src/server/core/services/HttpClient.ts","../../../src/server/core/primitives/$action.ts","../../../src/server/core/primitives/$route.ts","../../../src/server/core/providers/BunHttpServerProvider.ts","../../../src/server/core/providers/NodeHttpServerProvider.ts","../../../src/server/core/providers/ServerBodyParserProvider.ts","../../../src/server/core/providers/ServerLoggerProvider.ts","../../../src/server/core/providers/ServerNotReadyProvider.ts","../../../src/server/core/constants/routeMethods.ts","../../../src/server/core/errors/BadRequestError.ts","../../../src/server/core/errors/ConflictError.ts","../../../src/server/core/errors/ForbiddenError.ts","../../../src/server/core/errors/NotFoundError.ts","../../../src/server/core/errors/UnauthorizedError.ts","../../../src/server/core/schemas/okSchema.ts","../../../src/server/core/index.ts"],"sourcesContent":["import type { RequestConfigSchema } from \"../interfaces/ServerRequest.ts\";\n\n/**\n * Checks if the route has multipart/form-data request body.\n */\nexport const isMultipart = (options: {\n schema?: RequestConfigSchema;\n requestBodyType?: string;\n}): boolean => {\n if (options.requestBodyType === \"multipart/form-data\") {\n return true;\n }\n\n if (options.schema?.body && \"properties\" in options.schema.body) {\n const properties: Record<string, any> = options.schema.body.properties;\n for (const key in properties) {\n if (properties[key].format === \"binary\") {\n return true;\n }\n }\n }\n\n return false;\n};\n","/**\n * Helper for building server replies.\n */\nexport class ServerReply {\n // TODO: make it private\n public headers: Record<string, string> & {\n \"set-cookie\"?: string[];\n } = {};\n\n public status?: number; // default 200, or 204 (no content)\n\n public body?: any;\n\n /**\n * Redirect to a given URL with optional status code (default 302).\n */\n public redirect(url: string, status: number = 302): void {\n this.status = status;\n this.headers.location = url;\n }\n\n // TODO: check if status / header is already set and throw an error if so (for allow to override with force flag)\n\n /**\n * Set the response status code.\n */\n public setStatus(status: number): this {\n this.status = status;\n return this;\n }\n\n /**\n * Set a response header.\n */\n public setHeader(name: string, value: string): this {\n this.headers[name.toLowerCase()] = value;\n return this;\n }\n\n /**\n * Set the response body.\n */\n public setBody(body: any): this {\n this.body = body;\n return this;\n }\n}\n","import { AlephaError } from \"alepha\";\nimport type { ErrorSchema } from \"../schemas/errorSchema.ts\";\n\nexport const isHttpError = (\n error: unknown,\n status?: number,\n): error is HttpErrorLike => {\n const isError =\n !!error &&\n typeof error === \"object\" &&\n \"message\" in error &&\n typeof error.message === \"string\" &&\n \"status\" in error &&\n typeof error.status === \"number\";\n\n if (!isError) {\n return false;\n }\n\n if (status) {\n return (error as HttpErrorLike).status === status;\n }\n\n return true;\n};\n\nexport class HttpError extends AlephaError {\n public name = \"HttpError\";\n\n static is = isHttpError;\n\n static toJSON(error: HttpError): ErrorSchema {\n const json: Record<string, unknown> = {\n error: error.error,\n status: error.status,\n message: error.message,\n };\n\n if (error.details) json.details = error.details;\n if (error.requestId) json.requestId = error.requestId;\n if (error.reason) json.cause = error.reason;\n\n return json as ErrorSchema;\n }\n\n public readonly error: string;\n public readonly status: number;\n\n public readonly requestId?: string;\n public readonly details?: string;\n public readonly reason?: {\n name: string;\n message: string;\n };\n\n constructor(options: Partial<ErrorSchema>, cause?: unknown) {\n super(options.message, {\n cause,\n });\n\n this.status = options.status ?? 500;\n this.details = options.details;\n this.requestId = options.requestId;\n\n if (typeof options.cause === \"object\") {\n this.reason = {\n name: (options.cause as { name: string }).name,\n message: (options.cause as { message: string }).message,\n };\n } else if (cause instanceof Error) {\n this.reason = {\n name: cause.name,\n message: cause.message,\n };\n }\n\n if (this.constructor.name === \"HttpError\") {\n this.error =\n options.error ?? errorNameByStatus[this.status] ?? \"HttpError\";\n } else {\n this.error = this.constructor.name;\n }\n }\n}\n\nexport const errorNameByStatus: Record<number, string> = {\n 400: \"BadRequestError\",\n 401: \"UnauthorizedError\",\n 403: \"ForbiddenError\",\n 404: \"NotFoundError\",\n 405: \"MethodNotAllowedError\",\n 409: \"ConflictError\",\n 410: \"GoneError\",\n 413: \"PayloadTooLargeError\",\n 415: \"UnsupportedMediaTypeError\",\n 429: \"TooManyRequestsError\",\n 500: \"InternalServerError\",\n 501: \"NotImplementedError\",\n 502: \"BadGatewayError\",\n 503: \"ServiceUnavailableError\",\n 504: \"GatewayTimeoutError\",\n};\n\nexport interface HttpErrorLike extends Error {\n status: number;\n}\n","import { HttpError } from \"./HttpError.ts\";\n\nexport class ValidationError extends HttpError {\n constructor(message = \"Validation has failed\", cause?: unknown) {\n super(\n {\n message,\n status: 400,\n },\n cause,\n );\n }\n}\n","export interface UserAgentInfo {\n os:\n | \"Windows\"\n | \"Android\"\n | \"Ubuntu\"\n | \"MacOS\"\n | \"iOS\"\n | \"Linux\"\n | \"FreeBSD\"\n | \"OpenBSD\"\n | \"ChromeOS\"\n | \"BlackBerry\"\n | \"Symbian\"\n | \"Windows Phone\";\n browser:\n | \"Chrome\"\n | \"Firefox\"\n | \"Safari\"\n | \"Edge\"\n | \"Opera\"\n | \"Internet Explorer\"\n | \"Brave\"\n | \"Vivaldi\"\n | \"Samsung Browser\"\n | \"UC Browser\"\n | \"Yandex\";\n device: \"MOBILE\" | \"DESKTOP\" | \"TABLET\";\n}\n\n/**\n * Simple User-Agent parser to detect OS, browser, and device type.\n * This parser is not exhaustive and may not cover all edge cases.\n *\n * Use result for non\n */\nexport class UserAgentParser {\n public parse(userAgent: string = \"\"): UserAgentInfo {\n const ua = userAgent.toLowerCase();\n\n // Default values\n let os: UserAgentInfo[\"os\"] = \"Windows\";\n let browser: UserAgentInfo[\"browser\"] = \"Chrome\";\n let device: UserAgentInfo[\"device\"] = \"DESKTOP\";\n\n // Detect OS - Order matters for specificity\n if (ua.includes(\"windows phone\")) {\n os = \"Windows Phone\";\n } else if (ua.includes(\"windows\")) {\n os = \"Windows\";\n } else if (ua.includes(\"android\")) {\n os = \"Android\";\n } else if (\n ua.includes(\"iphone\") ||\n ua.includes(\"ipad\") ||\n ua.includes(\"ipod\") ||\n (ua.includes(\"ios\") && !ua.includes(\"android\"))\n ) {\n os = \"iOS\";\n } else if (\n ua.includes(\"mac os\") ||\n ua.includes(\"macos\") ||\n ua.includes(\"macintosh\")\n ) {\n os = \"MacOS\";\n } else if (ua.includes(\"cros\") || ua.includes(\"chromeos\")) {\n os = \"ChromeOS\";\n } else if (ua.includes(\"ubuntu\")) {\n os = \"Ubuntu\";\n } else if (ua.includes(\"freebsd\")) {\n os = \"FreeBSD\";\n } else if (ua.includes(\"openbsd\")) {\n os = \"OpenBSD\";\n } else if (ua.includes(\"blackberry\") || ua.includes(\"bb10\")) {\n os = \"BlackBerry\";\n } else if (ua.includes(\"symbian\") || ua.includes(\"symbos\")) {\n os = \"Symbian\";\n } else if (ua.includes(\"linux\") || ua.includes(\"x11\")) {\n os = \"Linux\";\n }\n\n // Detect Browser/browser - Order matters, check most specific first\n if (ua.includes(\"yabrowser\") || ua.includes(\"yandex\")) {\n browser = \"Yandex\";\n } else if (ua.includes(\"brave\")) {\n browser = \"Brave\";\n } else if (ua.includes(\"vivaldi\")) {\n browser = \"Vivaldi\";\n } else if (ua.includes(\"samsungbrowser\") || ua.includes(\"samsung\")) {\n browser = \"Samsung Browser\";\n } else if (ua.includes(\"ucbrowser\") || ua.includes(\"uc browser\")) {\n browser = \"UC Browser\";\n } else if (\n ua.includes(\"opera\") ||\n ua.includes(\"opr/\") ||\n ua.includes(\"opios\")\n ) {\n browser = \"Opera\";\n } else if (\n ua.includes(\"edg/\") ||\n ua.includes(\"edge\") ||\n ua.includes(\"edgios\")\n ) {\n browser = \"Edge\";\n } else if (ua.includes(\"firefox\") && !ua.includes(\"seamonkey\")) {\n browser = \"Firefox\";\n } else if (ua.includes(\"trident\") || ua.includes(\"msie\")) {\n browser = \"Internet Explorer\";\n } else if (\n ua.includes(\"safari\") &&\n !ua.includes(\"chrome\") &&\n !ua.includes(\"chromium\")\n ) {\n browser = \"Safari\";\n } else if (\n ua.includes(\"chrome\") ||\n ua.includes(\"chromium\") ||\n ua.includes(\"crios\")\n ) {\n browser = \"Chrome\";\n }\n\n // Detect Device Type\n const mobileKeywords = [\n \"mobile\",\n \"android\",\n \"iphone\",\n \"ipod\",\n \"blackberry\",\n \"windows phone\",\n \"opera mini\",\n \"iemobile\",\n \"mobile safari\",\n \"nokia\",\n \"symbian\",\n ];\n\n const tabletKeywords = [\n \"ipad\",\n \"tablet\",\n \"kindle\",\n \"silk\",\n \"gt-p\",\n \"sm-t\",\n \"nexus 7\",\n \"nexus 10\",\n ];\n\n const isTablet = tabletKeywords.some((keyword) => ua.includes(keyword));\n const isMobile = mobileKeywords.some((keyword) => ua.includes(keyword));\n\n if (isTablet) {\n device = \"TABLET\";\n } else if (isMobile) {\n device = \"MOBILE\";\n } else {\n device = \"DESKTOP\";\n }\n\n return { os, browser, device };\n }\n}\n","import { $inject, Alepha } from \"alepha\";\nimport { ServerReply } from \"../helpers/ServerReply.ts\";\nimport type {\n ServerRequest,\n ServerRequestData,\n} from \"../interfaces/ServerRequest.ts\";\nimport { UserAgentParser } from \"./UserAgentParser.ts\";\n\nexport class ServerRequestParser {\n protected readonly alepha = $inject(Alepha);\n protected readonly userAgentParser = $inject(UserAgentParser);\n\n public createServerRequest(rawRequest: ServerRequestData): ServerRequest {\n const self = this;\n return {\n method: rawRequest.method,\n url: rawRequest.url,\n raw: rawRequest.raw,\n headers: rawRequest.headers,\n query: rawRequest.query,\n params: rawRequest.params,\n // body will be filled by body parser middleware\n body: null,\n metadata: {},\n requestId: this.getRequestId(rawRequest) || crypto.randomUUID(),\n reply: this.alepha.inject(ServerReply, { lifetime: \"transient\" }),\n get ip() {\n return self.getRequestIp(rawRequest);\n },\n get userAgent() {\n return self.getRequestUserAgent(rawRequest);\n },\n } as ServerRequest;\n }\n\n public getRequestId(request: ServerRequestData): string | undefined {\n return request.headers[\"x-request-id\"];\n }\n\n public getRequestUserAgent(request: ServerRequestData) {\n return this.userAgentParser.parse(request.headers[\"user-agent\"]);\n }\n\n public getRequestIp(request: ServerRequestData): string | undefined {\n // check for the 'x-forwarded-for' header first, which is commonly used\n // in proxy setups to forward the original client's IP address.\n\n // https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For\n\n const forwardedFor = request.headers[\"x-forwarded-for\"];\n if (forwardedFor) {\n // The 'x-forwarded-for' header can contain multiple IPs, so we take the first one.\n return Array.isArray(forwardedFor)\n ? forwardedFor[0]\n : forwardedFor.split(\",\")[0].trim();\n }\n\n const xRealIP = request.headers[\"x-real-ip\"];\n if (xRealIP) {\n return Array.isArray(xRealIP) ? xRealIP[0] : xRealIP;\n }\n }\n}\n","import { $hook, $inject, Alepha } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport type { ServerRequest } from \"../interfaces/ServerRequest.ts\";\n\ntype TimingMap = Record<string, [number, number]>;\n\nexport class ServerTimingProvider {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n\n public options = {\n prefix: this.alepha.env.APP_NAME\n ? `${this.alepha.env.APP_NAME.toLowerCase()}-`\n : \"\",\n disabled: this.alepha.isProduction(),\n };\n\n public readonly onRequest = $hook({\n priority: \"first\",\n on: \"server:onRequest\",\n handler: async ({ request }) => {\n if (this.options.disabled) {\n return;\n }\n\n request.metadata.timing = {};\n request.metadata.timing[this.handlerName] = [Date.now()];\n },\n });\n\n public readonly onResponse = $hook({\n priority: \"last\",\n on: \"server:onResponse\",\n handler: async ({ request }) => {\n if (this.options.disabled) {\n return;\n }\n\n if (request.metadata.timing) {\n this.setDuration(this.handlerName, request.metadata.timing);\n\n let timingHeader = \"\";\n\n for (const [name, [start, duration]] of Object.entries(\n request.metadata.timing as TimingMap,\n )) {\n if (typeof start !== \"number\" || typeof duration !== \"number\") {\n this.log.warn(\n `Invalid timing for '${name}': [${start}, ${duration}]`,\n );\n continue;\n }\n\n const formattedName =\n this.options.prefix + name.replace(/[^a-zA-Z0-9-]/g, \"-\");\n timingHeader += `${formattedName};dur=${duration}, `;\n }\n\n if (request.reply.headers[\"Server-Timing\"]) {\n request.reply.headers[\"Server-Timing\"] += `, ${timingHeader}`;\n } else {\n request.reply.headers[\"Server-Timing\"] = timingHeader;\n }\n }\n },\n });\n\n protected get handlerName() {\n return `request`;\n }\n\n public beginTiming(name: string): void {\n if (this.options.disabled) {\n return;\n }\n\n const request = this.alepha.context.get<ServerRequest>(\"request\");\n if (!request) {\n return;\n }\n\n request.metadata ??= {};\n request.metadata.timing ??= {};\n request.metadata.timing[name] = [Date.now()];\n }\n\n public endTiming(name: string): void {\n if (this.options.disabled) {\n return;\n }\n\n const request = this.alepha.context.get<ServerRequest>(\"request\");\n if (!request) {\n return;\n }\n\n if (!request.metadata?.timing || !(name in request.metadata.timing)) {\n this.log.warn(`No timing found for '${name}'.`);\n return;\n }\n\n const start = request.metadata.timing[name]?.[0];\n if (typeof start !== \"number\") {\n this.log.warn(`Invalid timing start for '${name}': ${start}`);\n return;\n }\n\n this.setDuration(name, request.metadata.timing);\n }\n\n protected setDuration(name: string, timing: TimingMap): void {\n timing[name] = [timing[name][0], Date.now() - timing[name][0]];\n }\n}\n","import { Readable as NodeStream } from \"node:stream\";\nimport { ReadableStream as NodeWebStream } from \"node:stream/web\";\nimport { $inject, Alepha, isFileLike, isTypeFile, isUUID, t } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { RouterProvider } from \"alepha/router\";\nimport type { RouteMethod } from \"../constants/routeMethods.ts\";\nimport { errorNameByStatus, HttpError } from \"../errors/HttpError.ts\";\nimport { ValidationError } from \"../errors/ValidationError.ts\";\nimport type { ServerReply } from \"../helpers/ServerReply.ts\";\nimport type {\n RequestConfigSchema,\n ResponseKind,\n ServerRequest,\n ServerRequestConfig,\n ServerRoute,\n ServerRouteMatcher,\n} from \"../interfaces/ServerRequest.ts\";\nimport { ServerRequestParser } from \"../services/ServerRequestParser.ts\";\nimport { ServerTimingProvider } from \"./ServerTimingProvider.ts\";\n\n/**\n * Main router for all routes on the server side.\n *\n * - $route => generic route\n * - $action => action route (for API calls)\n * - $page => React route (for SSR)\n */\nexport class ServerRouterProvider extends RouterProvider<ServerRouteMatcher> {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly routes: ServerRoute[] = [];\n protected readonly serverTimingProvider = $inject(ServerTimingProvider);\n protected readonly serverRequestParser = $inject(ServerRequestParser);\n\n /**\n * Get all registered routes, optionally filtered by a pattern.\n *\n * Pattern accept simple wildcard '*' at the end.\n * Example: '/api/*' will match all routes starting with '/api/' but '/api/' will match only that exact route.\n */\n public getRoutes(pattern?: string): ServerRoute[] {\n if (pattern) {\n if (pattern.endsWith(\"*\")) {\n const basePattern = pattern.slice(0, -1);\n return this.routes.filter((route) =>\n route.path.startsWith(basePattern),\n );\n } else {\n return this.routes.filter((route) => route.path === pattern);\n }\n }\n return this.routes;\n }\n\n public createRoute<TConfig extends RequestConfigSchema = RequestConfigSchema>(\n route: ServerRoute<TConfig>,\n ): void {\n route.method ??= \"GET\";\n route.method = route.method.toUpperCase() as RouteMethod;\n\n this.routes.push(route);\n\n const path = `/${route.method}/${route.path}`.replace(/\\/+/g, \"/\");\n const responseKind = this.getResponseType(route.schema);\n\n this.log.trace(`Create route ${path}`);\n\n this.push({\n path,\n handler: (rawRequest) => {\n const request =\n this.serverRequestParser.createServerRequest(rawRequest);\n\n return this.alepha.context.run(\n () => this.processRequest(request, route, responseKind),\n {\n context: this.getContextId(rawRequest.headers),\n },\n );\n },\n });\n }\n\n protected getContextId(headers: Record<string, string>): string {\n const contextId = headers[\"x-request-id\"] || headers[\"x-correlation-id\"];\n // TODO: check if it's not overkill, just checking length might be enough?\n // some cloud providers generate non-UUID request ids\n if (isUUID(contextId)) {\n return contextId;\n }\n\n return crypto.randomUUID();\n }\n\n protected async processRequest(\n request: ServerRequest,\n route: ServerRoute,\n responseKind: ResponseKind,\n ) {\n await this.runRouteHandler(route, request, responseKind).catch((error) => {\n return this.errorHandler(route, request, error as Error);\n });\n\n await this.alepha.events.emit(\n \"server:onSend\",\n {\n request,\n route,\n },\n {\n catch: true, // avoid unhandled rejection\n },\n );\n\n // create response\n const response = {\n status: request.reply.status ?? (request.reply.body ? 200 : 204),\n headers: request.reply.headers,\n body: request.reply.body as any,\n };\n\n await this.alepha.events.emit(\n \"server:onResponse\",\n {\n request,\n route,\n response,\n },\n {\n catch: true, // avoid unhandled rejection\n },\n );\n\n return response;\n }\n\n protected async runRouteHandler(\n route: ServerRoute,\n request: ServerRequest,\n responseKind: ResponseKind,\n ) {\n // there are some built-in hooks that are called before the request is handled\n // - ServerBodyParserProvider (parse body)\n // - ServerSecurityProvider (build user from headers)\n // - ServerLoggerProvider (log request)\n\n await this.alepha.events.emit(\n \"server:onRequest\", // this hook will fill request.user and request.cookies\n {\n request,\n route,\n },\n {\n log: false,\n },\n );\n\n if (\n request.reply.body ||\n (request.reply.status && request.reply.status >= 200)\n ) {\n // if the body is already set, we can skip the handler\n // this is useful for middlewares that set the body\n return;\n }\n\n // request is ready to be used -> inject to context\n this.alepha.context.set<ServerRequest>(\"request\", request as ServerRequest);\n\n // validate request\n this.serverTimingProvider.beginTiming(\"validateRequest\");\n try {\n this.validateRequest(route, request);\n } finally {\n this.serverTimingProvider.endTiming(\"validateRequest\");\n }\n\n // call the handler only if the body is not set yet\n this.serverTimingProvider.beginTiming(\"runHandler\");\n try {\n const result = await route.handler(request);\n if (result) {\n request.reply.body = result;\n }\n } finally {\n this.serverTimingProvider.endTiming(\"runHandler\");\n }\n\n // serialize response\n this.serverTimingProvider.beginTiming(\"serializeResponse\");\n try {\n this.serializeResponse(route, request.reply, responseKind);\n } finally {\n this.serverTimingProvider.endTiming(\"serializeResponse\");\n }\n }\n\n public serializeResponse(\n route: ServerRoute,\n reply: ServerReply,\n responseKind: ResponseKind,\n ): void {\n if (responseKind === \"json\" && route.schema?.response) {\n reply.headers[\"content-type\"] = \"application/json\";\n reply.body = this.alepha.codec.encode(route.schema.response, reply.body, {\n as: \"string\",\n });\n return;\n }\n\n if (responseKind === \"file\") {\n if (!isFileLike(reply.body)) {\n throw new HttpError({\n status: 500,\n message: \"Invalid response body - not a file\",\n });\n }\n reply.headers[\"content-type\"] = reply.body.type;\n reply.headers[\"content-disposition\"] =\n `attachment; filename=\"${reply.body.name.replaceAll('\"', \"\")}\"`;\n reply.body = reply.body.stream();\n return;\n }\n\n if (responseKind === \"text\") {\n reply.body = String(reply.body);\n if (reply.body.startsWith(\"<!DOCTYPE html>\")) {\n reply.headers[\"content-type\"] ??= \"text/html; charset=UTF-8\";\n } else {\n reply.headers[\"content-type\"] ??= \"text/plain\";\n }\n return;\n }\n\n if (reply.body == null || responseKind === \"void\") {\n delete reply.headers[\"content-type\"];\n reply.body = undefined;\n return;\n }\n\n if (Buffer.isBuffer(reply.body)) {\n reply.headers[\"content-type\"] ??= \"application/octet-stream\";\n return;\n }\n\n if (\n reply.body instanceof NodeWebStream ||\n reply.body instanceof NodeStream\n ) {\n // set content-type to application/octet-stream if not set\n reply.headers[\"content-type\"] ??= \"application/octet-stream\";\n return;\n }\n\n reply.headers[\"content-type\"] ??= \"text/plain\";\n reply.body = String(reply.body);\n return;\n }\n\n protected getResponseType(schema?: RequestConfigSchema): ResponseKind {\n if (schema?.response) {\n if (\n t.schema.isObject(schema.response) ||\n t.schema.isRecord(schema.response) ||\n t.schema.isArray(schema.response)\n ) {\n return \"json\";\n }\n\n if (\n t.schema.isString(schema.response) ||\n t.schema.isInteger(schema.response) ||\n t.schema.isNumber(schema.response) ||\n t.schema.isBoolean(schema.response)\n ) {\n return \"text\";\n }\n\n if (isTypeFile(schema.response)) {\n return \"file\";\n }\n\n if (t.schema.isVoid(schema.response)) {\n return \"void\";\n }\n }\n\n return \"any\";\n }\n\n protected async errorHandler(\n route: ServerRoute,\n request: ServerRequest,\n error: Error,\n ) {\n // reset body, which is probably invalid,\n // it can be filled by server:onError hook or by the default handler below\n request.reply.body = null;\n\n await this.alepha.events.emit(\n \"server:onError\",\n {\n request,\n route,\n error,\n },\n {\n log: false,\n },\n );\n\n if (!request.reply.body && !request.reply.status) {\n if (error instanceof HttpError) {\n request.reply.status = error.status;\n request.reply.headers[\"content-type\"] = \"application/json\";\n request.reply.body = JSON.stringify({\n ...HttpError.toJSON(error),\n requestId: request.requestId,\n });\n } else {\n if (\n \"status\" in error &&\n typeof error.status === \"number\" &&\n !!errorNameByStatus[error.status]\n ) {\n request.reply.status = error.status;\n request.reply.headers[\"content-type\"] = \"application/json\";\n request.reply.body = JSON.stringify({\n status: error.status,\n error: errorNameByStatus[error.status],\n message: (error as Error).message,\n requestId: request.requestId,\n });\n return;\n }\n\n request.reply.status = 500;\n request.reply.headers[\"content-type\"] = \"application/json\";\n request.reply.body = JSON.stringify({\n status: 500,\n error: \"InternalServerError\",\n message: (error as Error).message,\n requestId: request.requestId,\n });\n }\n }\n }\n\n public validateRequest(\n route: { schema?: RequestConfigSchema },\n request: ServerRequestConfig,\n ) {\n if (route.schema?.params) {\n try {\n request.params = this.alepha.codec.validate(\n route.schema.params,\n request.params,\n ) as any;\n } catch (error) {\n throw new ValidationError(\"Invalid request params\", error);\n }\n }\n\n if (route.schema?.query) {\n try {\n // we parse one by one to use the TypeBox coercion (e.g., number from string)\n const query: Record<string, any> = {};\n for (const key in route.schema.query.properties) {\n if (request.query[key] != null) {\n query[key] = this.alepha.codec.decode(\n route.schema.query.properties[key],\n request.query[key],\n );\n }\n }\n request.query = query;\n } catch (error) {\n throw new ValidationError(\"Invalid request query\", error);\n }\n }\n\n if (route.schema?.headers) {\n try {\n request.headers = this.alepha.codec.validate(\n route.schema.headers,\n request.headers,\n ) as any;\n } catch (error) {\n throw new ValidationError(\"Invalid request header\", error);\n }\n }\n\n if (route.schema?.body) {\n if (t.schema.isString(route.schema.body)) {\n if (typeof request.body !== \"string\") {\n throw new ValidationError(\"Request body is not a string\");\n }\n } else {\n try {\n request.body = this.alepha.codec.decode(\n route.schema.body,\n request.body,\n );\n } catch (error) {\n throw new ValidationError(\"Invalid request body\", error);\n }\n }\n }\n }\n}\n","import { Readable } from \"node:stream\";\nimport { $hook, $inject, Alepha } from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport type { Route } from \"alepha/router\";\nimport type { RouteMethod } from \"../constants/routeMethods.ts\";\nimport type {\n NodeRequestEvent,\n ServerRequestData,\n WebRequestEvent,\n} from \"../interfaces/ServerRequest.ts\";\nimport { ServerRouterProvider } from \"./ServerRouterProvider.ts\";\n\n/**\n * Base server provider to handle incoming requests and route them.\n *\n * This is the default implementation for serverless environments.\n *\n * ServerProvider supports both Node.js HTTP requests and Web (Fetch API) requests.\n */\nexport class ServerProvider {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n protected readonly router = $inject(ServerRouterProvider);\n\n protected readonly internalServerErrorMessage = \"Internal Server Error\";\n\n public get hostname(): string {\n return \"\"; // no hostname in serverless mode\n }\n\n /**\n * When a Node.js HTTP request is received from outside. (Vercel, AWS Lambda, etc.)\n */\n protected readonly onNodeRequest = $hook({\n on: \"node:request\",\n handler: (ev) => this.handleNodeRequest(ev),\n });\n\n /**\n * When a Web (Fetch API) request is received from outside. (Netlify, Cloudflare Workers, etc.)\n */\n protected readonly onWebRequest = $hook({\n on: \"web:request\",\n handler: (ev) => {\n return this.handleWebRequest(ev);\n },\n });\n\n /**\n * Handle Node.js HTTP request event.\n *\n * Technically, we just convert Node.js request to Web Standard Request.\n */\n public async handleNodeRequest(\n nodeRequestEvent: NodeRequestEvent,\n ): Promise<void> {\n const { req, res } = nodeRequestEvent;\n const { route, params } = this.router.match(`/${req.method}${req.url}`);\n\n if (this.isViteNotFound(req.url, route, params)) {\n return;\n }\n\n if (!route) {\n // if no route is found, return basic 404\n // note: you should not use this in production, use a custom 404 page instead by adding a route /*\n res.writeHead(404, { \"content-type\": \"text/plain\" });\n res.end(\"Not Found\");\n return;\n }\n\n const headers = (req.headers ?? {}) as Record<string, string>;\n const proto = headers[\"x-forwarded-proto\"] === \"https\" ? \"https\" : \"http\";\n const url = new URL(`${proto}://${headers.host}${req.url}`);\n const query = Object.fromEntries(url.searchParams.entries());\n const method = (req.method?.toUpperCase() ?? \"GET\") as RouteMethod;\n\n const request: ServerRequestData = {\n method,\n url,\n headers,\n params: params ?? {},\n query,\n raw: { node: nodeRequestEvent },\n };\n\n const response = await route.handler(request).catch(() => {\n return {\n status: 500,\n headers: { \"content-type\": \"text/plain\" },\n body: this.internalServerErrorMessage,\n };\n });\n\n // empty body - just send status & headers\n if (!response.body) {\n res.writeHead(response.status, response.headers).end();\n return;\n }\n\n // if response.body is string or buffer\n if (typeof response.body === \"string\" || Buffer.isBuffer(response.body)) {\n res.writeHead(response.status, response.headers).end(response.body);\n return;\n }\n\n // if response.body is node stream\n if (response.body instanceof Readable) {\n res.writeHead(response.status, response.headers);\n response.body.pipe(res);\n return;\n }\n\n // if response.body is web stream\n if (response.body instanceof ReadableStream) {\n res.writeHead(response.status, response.headers);\n try {\n for await (const chunk of response.body) {\n res.write(chunk);\n }\n } catch (error) {\n this.log.error(\"Error piping proxy response stream\", error);\n } finally {\n res.end();\n }\n return;\n }\n\n // not supported response body type\n\n this.log.error(\"Unknown response body type:\", typeof response.body);\n res.writeHead(500, { \"content-type\": \"text/plain\" });\n res.end(this.internalServerErrorMessage);\n }\n\n /**\n * Handle Web (Fetch API) request event.\n */\n public async handleWebRequest(ev: WebRequestEvent): Promise<void> {\n const req = ev.req;\n const url = new URL(req.url);\n const { route, params } = this.router.match(\n `/${req.method}${url.pathname}`,\n );\n\n if (this.isViteNotFound(req.url, route, params)) {\n return;\n }\n\n if (!route) {\n // if no route is found, return basic 404\n // note: you should not use this in production, use a custom 404 page instead by adding a route /*\n ev.res = new Response(\"Not Found\", {\n status: 404,\n headers: { \"content-type\": \"text/plain\" },\n });\n return;\n }\n\n const headers: Record<string, string> = {};\n\n req.headers.forEach((value, key) => {\n headers[key] = value;\n });\n\n const query = Object.fromEntries(url.searchParams.entries());\n const method = (req.method.toUpperCase() ?? \"GET\") as RouteMethod;\n const request: ServerRequestData = {\n method,\n url,\n headers,\n params: params || {},\n query,\n raw: { web: ev },\n };\n\n const response = await route.handler(request).catch(() => {\n return {\n status: 500,\n headers: { \"content-type\": \"text/plain\" },\n body: this.internalServerErrorMessage,\n };\n });\n\n // empty body - just send status & headers\n if (!response.body) {\n ev.res = new Response(null, {\n status: response.status,\n headers: response.headers,\n });\n return;\n }\n\n // if response.body is string or buffer\n if (typeof response.body === \"string\") {\n ev.res = new Response(response.body, {\n status: response.status,\n headers: response.headers,\n });\n return;\n }\n\n if (Buffer.isBuffer(response.body)) {\n ev.res = new Response(response.body.buffer as ArrayBuffer, {\n status: response.status,\n headers: response.headers,\n });\n return;\n }\n\n // if response.body is node stream\n if (response.body instanceof Readable) {\n ev.res = new Response(Readable.toWeb(response.body) as ReadableStream, {\n status: response.status,\n headers: response.headers,\n });\n return;\n }\n\n // if response.body is web stream\n if (response.body instanceof ReadableStream) {\n ev.res = new Response(response.body, {\n status: response.status,\n headers: response.headers,\n });\n return;\n }\n\n // not supported response body type\n this.log.error(`Unknown response body type: ${typeof response.body}`);\n ev.res = new Response(this.internalServerErrorMessage, {\n status: 500,\n headers: { \"content-type\": \"text/plain\" },\n });\n }\n\n /**\n * Helper for Vite development mode to let Vite handle (or not) 404.\n */\n protected isViteNotFound(\n url?: string,\n route?: Route,\n params?: Record<string, string>,\n ): boolean {\n if (this.alepha.isViteDev()) {\n if (!route) {\n return true;\n }\n\n url = url?.split(\"?\")[0];\n\n if (!!params?.[\"*\"] && `/${params?.[\"*\"]}` === url) {\n return true;\n }\n }\n\n return false;\n }\n}\n","import { type Static, t } from \"alepha\";\n\nexport const errorSchema = t.object(\n {\n error: t.text({ description: \"HTTP error name\" }),\n status: t.integer({\n description: \"HTTP status code\",\n }),\n message: t.text({\n description: \"Short text which describe the error\",\n size: \"rich\",\n }),\n details: t.optional(\n t.text({\n description: \"Detailed description of the error\",\n size: \"rich\",\n }),\n ),\n requestId: t.optional(t.text()),\n cause: t.optional(\n t.object({\n name: t.text(),\n message: t.text({\n description: \"Cause Error message\",\n size: \"rich\",\n }),\n }),\n ),\n },\n {\n title: \"HttpError\",\n description: \"Generic response after a failed operation\",\n },\n);\n\nexport type ErrorSchema = Static<typeof errorSchema>;\n","import {\n $inject,\n Alepha,\n type FileLike,\n isFileLike,\n type Static,\n type TObject,\n type TSchema,\n} from \"alepha\";\nimport { $cache } from \"alepha/cache\";\nimport type { DurationLike } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport { HttpError } from \"../errors/HttpError.ts\";\nimport { isMultipart } from \"../helpers/isMultipart.ts\";\nimport type {\n ServerRequestConfigEntry,\n TRequestBody,\n TResponseBody,\n} from \"../interfaces/ServerRequest.ts\";\nimport type { ClientRequestOptions } from \"../primitives/$action.ts\";\nimport { errorSchema } from \"../schemas/errorSchema.ts\";\n\nexport class HttpClient {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n\n public readonly cache = $cache<HttpClientCache>();\n\n protected readonly pendingRequests: HttpClientPendingRequests = {};\n\n public async fetchAction(args: FetchActionArgs): Promise<FetchResponse> {\n const route = args.action; // our link to fetch\n const options = args.options ?? {}; // fetch standard options, cache, etc.\n const config = args.config ?? {}; // params, query, body, etc.\n const host = args.host ?? \"\"; // remote host, e.g. \"https://api.example.com\" or empty (for browser)\n\n const request: RequestInit = {\n ...options.request,\n };\n\n const method = route.method;\n const headers: Record<string, string> = {};\n const url = this.url(host, route, config);\n\n await this.alepha.events.emit(\"client:onRequest\", {\n route,\n config,\n options,\n headers,\n request,\n });\n\n request.method ??= method;\n\n await this.body(request, headers, route, config);\n\n request.headers = {\n ...config.headers,\n ...Object.fromEntries(new Headers(request.headers).entries()),\n ...headers,\n };\n\n return await this.fetch(url, {\n ...request,\n schema: route.schema,\n ...options,\n });\n }\n\n public async fetch<T extends TSchema>(\n url: string,\n request: RequestInitWithOptions<T> = {}, // standard options\n ): Promise<FetchResponse<Static<T>>> {\n const options = {\n cache: request.localCache,\n schema: request.schema?.response,\n key: request.key,\n };\n\n request.method ??= \"GET\";\n\n this.log.trace(\"Request\", {\n url,\n method: request.method,\n body: request.body,\n headers: request.headers,\n options,\n });\n\n // Only add automatic ETag if user didn't explicitly provide headers\n const cached = await this.cache.get(url);\n if (cached && request.method === \"GET\") {\n if (cached.etag) {\n request.headers = new Headers(request.headers);\n if (!request.headers.has(\"if-none-match\")) {\n request.headers.set(\"if-none-match\", cached.etag);\n }\n } else {\n return {\n data: cached.data as Static<T>,\n status: 200,\n statusText: \"OK\",\n headers: new Headers(),\n };\n }\n }\n\n await this.alepha.events.emit(\"client:beforeFetch\", {\n url,\n options,\n request,\n });\n\n // make a key for the request\n // this will be used to check if the request is already pending\n const key =\n options.key ??\n JSON.stringify({\n url,\n method: request.method,\n body: request.body,\n });\n\n const existing = this.pendingRequests[key];\n if (existing) {\n this.log.info(\"Request already pending\", key);\n return existing;\n }\n\n this.pendingRequests[key] = fetch(url, request)\n .then(async (response) => {\n this.log.debug(\"Response\", {\n url,\n status: response.status,\n });\n\n const fetchResponse: FetchResponse = {\n data: await this.responseData(response, options),\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n raw: response,\n };\n\n if (request.method === \"GET\") {\n if (options.cache) {\n await this.cache.set(\n url,\n { data: fetchResponse.data },\n typeof options.cache === \"boolean\" ? undefined : options.cache,\n );\n } else if (!this.alepha.isBrowser()) {\n // only cache etag on server, browser can handle etag itself\n const etag = response.headers.get(\"etag\") ?? undefined;\n if (etag) {\n await this.cache.set(url, { data: fetchResponse.data, etag });\n }\n }\n }\n\n return fetchResponse;\n })\n .finally(() => {\n delete this.pendingRequests[key];\n });\n\n return this.pendingRequests[key];\n }\n\n protected url(\n host: string,\n action: HttpAction,\n args: ServerRequestConfigEntry,\n ) {\n let url = host;\n\n if (action.prefix) {\n url += action.prefix;\n }\n\n url += action.path;\n url = this.pathVariables(url, action, args);\n url = this.queryParams(url, action, args);\n\n return url;\n }\n\n protected async body(\n init: RequestInit,\n headers: Record<string, string>,\n action: HttpAction,\n args: ServerRequestConfigEntry = {},\n ) {\n const hasHeader =\n typeof init.headers === \"object\" &&\n \"content-type\" in init.headers &&\n init.headers[\"content-type\"] === \"multipart/form-data\";\n\n if (hasHeader || isMultipart(action)) {\n if (typeof init.headers === \"object\" && \"content-type\" in init.headers) {\n delete init.headers[\"content-type\"]; // fetch() will fill this for us\n }\n\n const formData = new FormData();\n\n for (const [key, value] of Object.entries(args.body ?? {})) {\n if (typeof value === \"string\") {\n formData.append(key, value);\n continue;\n }\n if (value instanceof Blob) {\n formData.append(key, value);\n continue;\n }\n if (isFileLike(value)) {\n // FileLike must be transformed to WebFile\n formData.append(\n key,\n new File([await value.arrayBuffer()], value.name, {\n type: value.type,\n }),\n );\n }\n }\n\n init.body = formData;\n\n return;\n }\n\n if (!init.body && action.schema?.body) {\n headers[\"content-type\"] = \"application/json\";\n init.body = this.alepha.codec.encode(action.schema?.body, args.body, {\n as: \"string\",\n });\n }\n }\n\n protected async responseData(\n response: Response,\n options: FetchOptions,\n ): Promise<any> {\n if (response.status === 304) {\n let cacheKey = response.url;\n if (typeof window !== \"undefined\") {\n cacheKey = cacheKey.replace(window.location.origin, \"\");\n }\n\n const cached = await this.cache.get(cacheKey);\n if (cached) {\n return cached.data;\n }\n\n // if no cached data (etag-only routes), return empty string\n return \"\";\n }\n\n if (response.status === 204) {\n return;\n }\n\n if (this.isMaybeFile(response)) {\n return this.createFileLike(response);\n }\n\n if (response.headers.get(\"Content-Type\")?.startsWith(\"text/\")) {\n return await response.text();\n }\n\n if (response.headers.get(\"Content-Type\") === \"application/json\") {\n const json = await response.json();\n\n if (response.status >= 400) {\n const jsonError = this.alepha.codec.decode(errorSchema, json);\n const error = new HttpError(jsonError);\n\n await this.alepha.events.emit(\"client:onError\", {\n error,\n });\n\n throw error;\n }\n\n if (options.schema) {\n return this.alepha.codec.decode(options.schema, json);\n }\n\n return json;\n }\n\n if (response.status >= 400) {\n const error = new HttpError({\n status: response.status,\n message: `An error occurred while fetching the resource. (${response.statusText})`,\n });\n\n await this.alepha.events.emit(\"client:onError\", {\n error,\n });\n\n throw error;\n }\n\n return response;\n }\n\n protected isMaybeFile(response: Response): boolean {\n const contentType = response.headers.get(\"Content-Type\");\n if (!contentType) {\n return false;\n }\n\n if (response.headers.get(\"Content-Disposition\")?.includes(\"attachment\")) {\n return true; // If Content-Disposition indicates an attachment, treat it as a file\n }\n\n return (\n contentType.startsWith(\"application/octet-stream\") ||\n contentType.startsWith(\"application/pdf\") ||\n contentType.startsWith(\"application/zip\") ||\n contentType.startsWith(\"image/\") ||\n contentType.startsWith(\"video/\") ||\n contentType.startsWith(\"audio/\")\n );\n }\n\n protected createFileLike(response: Response, defaultFileName = \"\"): FileLike {\n const match = (response.headers.get(\"Content-Disposition\") ?? \"\").match(\n /filename=\"(.+)\"/,\n );\n return {\n name: match?.[1] ? match[1] : defaultFileName,\n type: response.headers.get(\"Content-Type\") ?? \"application/octet-stream\",\n size: Number(response.headers.get(\"Content-Length\") ?? 0),\n lastModified: Date.now(),\n stream: () => {\n throw new Error(\"Not implemented\");\n },\n arrayBuffer: async () => {\n return await response.arrayBuffer();\n },\n text: async () => {\n return await response.text();\n },\n };\n }\n\n public pathVariables(\n url: string,\n action: { schema?: { params?: TObject } },\n args: ServerRequestConfigEntry = {},\n ): string {\n if (typeof args.params === \"object\") {\n const params = action.schema?.params\n ? (this.alepha.codec.decode(\n action.schema.params,\n args.params,\n ) as Record<string, any>)\n : args.params;\n\n for (const key of Object.keys(params)) {\n url = url.replace(`:${key}`, params[key]);\n url = url.replace(`{${key}}`, params[key]);\n }\n }\n\n return url;\n }\n\n public queryParams(\n url: string,\n action: { schema?: { query?: TObject } },\n args: ServerRequestConfigEntry = {},\n ): string {\n if (typeof args.query === \"object\") {\n const query = action.schema?.query\n ? this.alepha.codec.decode(action.schema.query, args.query ?? {})\n : args.query;\n\n for (const key of Object.keys(query)) {\n if (query[key] === undefined) {\n delete query[key];\n }\n if (typeof query[key] === \"object\") {\n query[key] = JSON.stringify(query[key]);\n }\n }\n\n return `${url}?${new URLSearchParams(\n query as Record<string, string>,\n ).toString()}`;\n }\n return url;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface FetchOptions<T extends TSchema = TSchema> {\n /**\n * Key to identify the request in the pending requests.\n */\n key?: string;\n\n /**\n * The schema to validate the response against.\n */\n schema?: {\n response?: T;\n };\n\n /**\n * Built-in cache options.\n */\n localCache?: boolean | number | DurationLike;\n}\n\nexport type RequestInitWithOptions<T extends TSchema = TSchema> = RequestInit &\n FetchOptions<T>;\n\nexport interface FetchResponse<T = any> {\n data: T;\n status: number;\n statusText: string;\n headers: Headers;\n raw?: Response;\n}\n\nexport type HttpClientPendingRequests = Record<\n string,\n Promise<any> | undefined\n>;\n\ninterface HttpClientCache {\n data: any;\n etag?: string;\n}\n\nexport interface FetchActionArgs {\n action: HttpAction;\n host?: string;\n config?: ServerRequestConfigEntry;\n options?: ClientRequestOptions;\n}\n\nexport interface HttpAction {\n method?: string;\n prefix?: string;\n path: string;\n requestBodyType?: string;\n schema?: {\n params?: TObject;\n query?: TObject;\n body?: TRequestBody;\n response?: TResponseBody;\n };\n}\n","import {\n $env,\n $inject,\n type Async,\n createPrimitive,\n isTypeFile,\n KIND,\n Primitive,\n type Static,\n type TObject,\n type TSchema,\n t,\n} from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport type { RouteMethod } from \"../constants/routeMethods.ts\";\nimport { isMultipart } from \"../helpers/isMultipart.ts\";\nimport { ServerReply } from \"../helpers/ServerReply.ts\";\nimport type {\n RequestConfigSchema,\n ServerRequest,\n ServerResponseBody,\n ServerRoute,\n} from \"../interfaces/ServerRequest.ts\";\nimport { ServerProvider } from \"../providers/ServerProvider.ts\";\nimport { ServerRouterProvider } from \"../providers/ServerRouterProvider.ts\";\nimport {\n type FetchOptions,\n type FetchResponse,\n HttpClient,\n} from \"../services/HttpClient.ts\";\n\n/**\n * Creates a server action primitive for defining type-safe HTTP endpoints.\n *\n * Server actions are the core building blocks for REST APIs in Alepha, providing declarative\n * HTTP endpoints with full type safety, automatic validation, and OpenAPI documentation.\n *\n * **Key Features**\n * - Full TypeScript inference for request/response types\n * - Automatic schema validation using TypeBox\n * - Convention-based URL generation with customizable paths\n * - Direct invocation (`run()`) or HTTP requests (`fetch()`)\n * - Built-in authentication and authorization support\n * - Automatic content-type handling (JSON, form-data, plain text)\n *\n * **URL Generation**\n *\n * **Important:** All `$action` paths are automatically prefixed with `/api`.\n *\n * ```ts\n * $action({ path: \"/users\" }) // → GET /api/users\n * $action({ path: \"/users/:id\" }) // → GET /api/users/:id\n * $action({ path: \"/hello\" }) // → GET /api/hello\n * ```\n *\n * This prefix is configurable via the `SERVER_API_PREFIX` environment variable.\n * HTTP method defaults to GET, or POST if body schema is provided.\n *\n * **Common Use Cases**\n * - CRUD operations with type safety\n * - File upload and download endpoints\n * - Microservice communication\n *\n * @example\n * ```ts\n * class UserController {\n * getUsers = $action({\n * path: \"/users\",\n * schema: {\n * query: t.object({\n * page: t.optional(t.number({ default: 1 })),\n * limit: t.optional(t.number({ default: 10 }))\n * }),\n * response: t.object({\n * users: t.array(t.object({\n * id: t.text(),\n * name: t.text(),\n * email: t.text()\n * })),\n * total: t.number()\n * })\n * },\n * handler: async ({ query }) => {\n * const users = await this.userService.findUsers(query);\n * return { users: users.items, total: users.total };\n * }\n * });\n *\n * createUser = $action({\n * method: \"POST\",\n * path: \"/users\",\n * schema: {\n * body: t.object({\n * name: t.text(),\n * email: t.text({ format: \"email\" })\n * }),\n * response: t.object({ id: t.text(), name: t.text() })\n * },\n * handler: async ({ body }) => {\n * return await this.userService.create(body);\n * }\n * });\n * }\n * ```\n */\nexport const $action = <TConfig extends RequestConfigSchema>(\n options: ActionPrimitiveOptions<TConfig>,\n): ActionPrimitiveFn<TConfig> => {\n const instance = createPrimitive(ActionPrimitive<TConfig>, options);\n const fn = (\n config?: ClientRequestEntry<TConfig>,\n options?: ClientRequestOptions,\n ) => {\n return instance.run(config, options);\n };\n Object.defineProperty(fn, \"name\", {\n get(): string {\n return instance.options.name || instance.config.propertyKey;\n },\n });\n return Object.setPrototypeOf(fn, instance) as ActionPrimitiveFn<TConfig>;\n};\n\n// ----------------------------------------------------------------------------------------------------------\n\nexport interface ActionPrimitiveOptions<TConfig extends RequestConfigSchema>\n extends Omit<ServerRoute, \"handler\" | \"path\" | \"schema\" | \"mapParams\"> {\n /**\n * Name of the action.\n *\n * - It will be used to generate the route path if `path` is not provided.\n * - It will be used to generate the permission name if `security` is enabled.\n */\n name?: string;\n\n /**\n * Group actions together.\n *\n * - If not provided, the service name containing the route will be used.\n * - It will be used as Tag for documentation purposes.\n * - It will be used for permission name generation if `security` is enabled.\n *\n * @example\n * ```ts\n * // group = \"MyController\"\n * class MyController {\n * \thello = $action({ handler: () => \"Hello World\" });\n * }\n *\n * // group = \"users\"\n * class MyOtherController {\n * group = \"users\";\n * a1 = $action({ handler: () => \"Action 1\", group: this.group });\n * a2 = $action({ handler: () => \"Action 2\", group: this.group });\n * }\n * ```\n */\n group?: string;\n\n /**\n * Pathname of the route. If not provided, property key is used.\n */\n path?: string;\n\n /**\n * The route method.\n *\n * - If not provided, it will be set to \"GET\" by default.\n * - If not provider and a body is provided, it will be set to \"POST\".\n *\n * Wildcard methods are not supported for now. (e.g. \"ALL\", \"ANY\", etc.)\n */\n method?: RouteMethod;\n\n /**\n * The config schema of the route.\n * - body: The request body schema.\n * - params: Path variables schema.\n * - query: The request query-params schema.\n * - response: The response schema.\n */\n schema?: TConfig;\n\n /**\n * A short description of the action. Used for documentation purposes.\n */\n description?: string;\n\n /**\n * Disable the route. Useful with env variables do disable one specific route.\n * Route won't be available in the API but can still be called locally!\n */\n disabled?: boolean;\n\n /**\n * Main route handler. This is where the route logic is implemented.\n */\n handler: ServerActionHandler<TConfig>;\n}\n\n// ----------------------------------------------------------------------------------------------------------\n\nconst envSchema = t.object({\n SERVER_API_PREFIX: t.text({\n description: \"Prefix for all API routes (e.g. $action).\",\n default: \"/api\",\n }),\n});\n\nexport class ActionPrimitive<\n TConfig extends RequestConfigSchema,\n> extends Primitive<ActionPrimitiveOptions<TConfig>> {\n protected readonly log = $logger();\n protected readonly env = $env(envSchema);\n protected readonly httpClient = $inject(HttpClient);\n protected readonly serverProvider = $inject(ServerProvider);\n protected readonly serverRouterProvider = $inject(ServerRouterProvider);\n\n protected onInit() {\n if (this.options.disabled) {\n this.log.debug(\n `Action '${this.name}' is disabled. It won't be available in the API.`,\n );\n return;\n }\n this.serverRouterProvider.createRoute(this.route);\n }\n\n public get prefix() {\n return this.env.SERVER_API_PREFIX;\n }\n\n public get route(): ServerRoute {\n return {\n ...(this.options as any), // TODO: fix schema.header mapping\n method: this.method,\n path: `${this.prefix}${this.path}`,\n } as ServerRoute;\n }\n\n /**\n * Returns the name of the action.\n */\n public get name(): string {\n return this.options.name || this.config.propertyKey;\n }\n\n /**\n * Returns the group of the action. (e.g. \"orders\", \"admin\", etc.)\n */\n public get group(): string {\n return this.options.group || this.config.service.name;\n }\n\n /**\n * Returns the HTTP method of the action.\n */\n public get method(): RouteMethod {\n return this.options.method || (this.options.schema?.body ? \"POST\" : \"GET\");\n }\n\n /**\n * Returns the path of the action.\n *\n * Path is prefixed by `/api` by default.\n */\n public get path(): string {\n if (this.options.path) {\n return this.options.path;\n }\n\n let path = `/${this.name}`;\n\n if (this.options.schema?.params) {\n for (const [key] of Object.entries(\n this.options.schema.params.properties,\n )) {\n path += `/:${key}`;\n }\n }\n\n return path;\n }\n\n public get schema(): TConfig | undefined {\n return this.options.schema;\n }\n\n public getBodyContentType(): string | undefined {\n if (this.options.schema?.body) {\n // TODO: move to `alepha.server.multipart` module ?\n if (isMultipart(this.options)) {\n return \"multipart/form-data\";\n }\n\n if (t.schema.isString(this.options.schema.body)) {\n // if body is a string, we assume it's plain text\n return \"text/plain\";\n }\n\n if (\n t.schema.isObject(this.options.schema.body) ||\n t.schema.isArray(this.options.schema.body) ||\n t.schema.isRecord(this.options.schema.body)\n )\n // if body is an object or array, we assume it's JSON\n return \"application/json\";\n }\n }\n\n /**\n * Call the action handler directly.\n * There is no HTTP layer involved.\n */\n public async run(\n config?: ClientRequestEntry<TConfig>,\n options: ClientRequestOptions = {}, // most of the options are ignored here\n ): Promise<ClientRequestResponse<TConfig>> {\n const handler = this.options.handler;\n const {\n body,\n params = {},\n query = {},\n headers = {},\n } = (config ?? {}) as ClientRequestEntryContainer<RequestConfigSchema>;\n const reply = new ServerReply();\n const method = this.method;\n\n // we use localhost as the base URL for the action\n const url = new URL(`http://localhost${this.path ?? \"\"}`);\n\n const serverActionRequest: Partial<ServerRequest> = {\n method,\n url,\n body,\n params,\n query,\n headers,\n reply,\n metadata: {},\n };\n\n await this.alepha.events.emit(\"action:onRequest\", {\n action: this,\n request: serverActionRequest as ServerRequest,\n options,\n });\n\n if (serverActionRequest.reply?.body) {\n return serverActionRequest.reply.body as ClientRequestResponse<TConfig>;\n }\n\n if (serverActionRequest.query && this.options.schema?.query) {\n serverActionRequest.query = this.alepha.codec.encode(\n this.options.schema.query,\n serverActionRequest.query,\n );\n }\n\n if (serverActionRequest.headers && this.options.schema?.headers) {\n serverActionRequest.headers = this.alepha.codec.encode(\n this.options.schema.headers,\n serverActionRequest.headers,\n ) as Record<string, any>;\n }\n\n if (serverActionRequest.body && this.options.schema?.body) {\n serverActionRequest.body = this.alepha.codec.encode(\n this.options.schema.body,\n serverActionRequest.body,\n ) as unknown;\n }\n\n if (serverActionRequest.params && this.options.schema?.params) {\n serverActionRequest.params = this.alepha.codec.encode(\n this.options.schema.params,\n serverActionRequest.params,\n ) as Record<string, any>;\n }\n\n this.serverRouterProvider.validateRequest(\n this.options,\n serverActionRequest as ServerRequest,\n );\n\n let response: any = await handler(\n serverActionRequest as ServerActionRequest<TConfig>,\n );\n\n // we validate response just to remove undeclared properties from response\n if (\n this.options.schema?.response &&\n // skip validation if response is expected as file\n !isTypeFile(this.options.schema.response)\n ) {\n response = this.alepha.codec.validate(\n this.options.schema.response,\n response,\n );\n }\n\n await this.alepha.events.emit(\"action:onResponse\", {\n action: this,\n request: serverActionRequest as ServerRequest,\n options,\n response,\n });\n\n return response;\n }\n\n /**\n * Works like `run`, but always fetches (http request) the route.\n */\n public fetch(\n config?: ClientRequestEntry<TConfig>,\n options?: ClientRequestOptions,\n ): Promise<FetchResponse<ClientRequestResponse<TConfig>>> {\n return this.httpClient.fetchAction({\n host: this.serverProvider.hostname, // that's the trick, we just use the server hostname\n action: this,\n config,\n options,\n });\n }\n}\n\nexport interface ActionPrimitiveFn<TConfig extends RequestConfigSchema>\n extends ActionPrimitive<TConfig> {\n (\n config?: ClientRequestEntry<TConfig>,\n options?: ClientRequestOptions,\n ): Promise<ClientRequestResponse<TConfig>>;\n}\n\n$action[KIND] = ActionPrimitive;\n\n// ----------------------------------------------------------------------------------------------------------\n\nexport type ClientRequestEntry<\n TConfig extends RequestConfigSchema,\n T = ClientRequestEntryContainer<TConfig>,\n> = {\n [K in keyof T as T[K] extends undefined ? never : K]: T[K];\n};\n\nexport type ClientRequestEntryContainer<TConfig extends RequestConfigSchema> = {\n body: TConfig[\"body\"] extends TObject ? Static<TConfig[\"body\"]> : undefined;\n\n params: TConfig[\"params\"] extends TObject\n ? Static<TConfig[\"params\"]>\n : undefined;\n\n headers?: TConfig[\"headers\"] extends TObject\n ? Static<TConfig[\"headers\"]>\n : undefined;\n\n query?: TConfig[\"query\"] extends TObject\n ? Partial<Static<TConfig[\"query\"]>>\n : undefined;\n};\n\nexport interface ClientRequestOptions extends FetchOptions {\n /**\n * Standard request fetch options.\n */\n request?: RequestInit;\n}\n\nexport type ClientRequestResponse<TConfig extends RequestConfigSchema> =\n TConfig[\"response\"] extends TSchema ? Static<TConfig[\"response\"]> : any;\n\n/**\n * Specific handler for server actions.\n */\nexport type ServerActionHandler<\n TConfig extends RequestConfigSchema = RequestConfigSchema,\n> = (\n request: ServerActionRequest<TConfig>,\n) => Async<ServerResponseBody<TConfig>>;\n\n/**\n * Server Action Request Interface\n *\n * Can be extended with module augmentation to add custom properties (like `user` in Server Security).\n *\n * This is NOT Server Request, but a specific type for actions.\n */\nexport interface ServerActionRequest<TConfig extends RequestConfigSchema>\n extends ServerRequest<TConfig> {}\n","import { $inject, createPrimitive, KIND, Primitive } from \"alepha\";\nimport type {\n RequestConfigSchema,\n ServerRoute,\n} from \"../interfaces/ServerRequest.ts\";\nimport { ServerRouterProvider } from \"../providers/ServerRouterProvider.ts\";\n\n/**\n * Create a basic endpoint.\n *\n * It's a low level primitive. You probably want to use `$action` instead.\n *\n * @see {@link $action}\n * @see {@link $page}\n */\nexport const $route = <TConfig extends RequestConfigSchema>(\n options: RoutePrimitiveOptions<TConfig>,\n): RoutePrimitive<TConfig> => {\n return createPrimitive(RoutePrimitive<TConfig>, options);\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface RoutePrimitiveOptions<\n TConfig extends RequestConfigSchema = RequestConfigSchema,\n> extends ServerRoute<TConfig> {}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class RoutePrimitive<\n TConfig extends RequestConfigSchema,\n> extends Primitive<RoutePrimitiveOptions<TConfig>> {\n protected readonly serverRouterProvider = $inject(ServerRouterProvider);\n\n protected onInit() {\n this.serverRouterProvider.createRoute(this.options);\n }\n}\n\n$route[KIND] = RoutePrimitive;\n","import { $env, $hook, $inject, Alepha, type Static, t } from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport { ServerProvider } from \"./ServerProvider.ts\";\nimport { ServerRouterProvider } from \"./ServerRouterProvider.ts\";\n\nconst envSchema = t.object({\n SERVER_PORT: t.integer({\n default: 3000,\n min: 0,\n max: 65535,\n description: \"Set 0 to listen on a random port.\",\n }),\n SERVER_HOST: t.text({\n default: \"localhost\",\n description: \"Set 0.0.0.0 to listen on all interfaces.\",\n }),\n});\n\ndeclare module \"alepha\" {\n interface Env extends Partial<Static<typeof envSchema>> {}\n}\n\n// Type declaration for Bun global (only when running in Bun runtime)\ndeclare const Bun: any;\n\nexport class BunHttpServerProvider extends ServerProvider {\n protected readonly alepha = $inject(Alepha);\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n protected readonly log = $logger();\n protected readonly env = $env(envSchema);\n protected readonly router = $inject(ServerRouterProvider);\n\n protected bunServer?: ReturnType<typeof Bun.serve>;\n\n public get hostname(): string {\n if (this.bunServer) {\n return `http://${this.bunServer.hostname}:${this.bunServer.port}`;\n }\n return `http://${this.env.SERVER_HOST}:${this.env.SERVER_PORT}`;\n }\n\n public readonly start = $hook({\n on: \"start\",\n handler: async () => {\n await this.listen();\n },\n });\n\n protected readonly stop = $hook({\n on: \"stop\",\n handler: async () => {\n if (this.alepha.isProduction()) {\n await this.close();\n return;\n }\n\n // do not await in development & test\n this.close().catch(() => {});\n },\n });\n\n protected async listen() {\n let port = this.env.SERVER_PORT;\n\n // for testing, use a random port if port is 3000 (default)\n if (this.alepha.isTest() && port === 3000) {\n port = 0;\n }\n\n try {\n this.bunServer = Bun.serve({\n port,\n hostname: this.env.SERVER_HOST,\n fetch: async (request: Request) => {\n this.log.trace(`Incoming Bun request -> ${request.url}`);\n\n // Create WebRequestEvent for handleWebRequest\n const webRequestEvent = {\n req: request,\n res: undefined as Response | undefined,\n };\n\n try {\n await this.handleWebRequest(webRequestEvent);\n\n if (!webRequestEvent.res) {\n // No response set, return 500\n return new Response(\"Internal Server Error\", {\n status: 500,\n headers: { \"content-type\": \"text/plain\" },\n });\n }\n\n return webRequestEvent.res;\n } catch (err) {\n this.log.error(\"Error handling request\", err);\n return new Response(\"Internal Server Error\", {\n status: 500,\n headers: { \"content-type\": \"text/plain\" },\n });\n }\n },\n error: (error: Error) => {\n this.log.error(\"Bun server error\", error);\n return new Response(\"Internal Server Error\", {\n status: 500,\n headers: { \"content-type\": \"text/plain\" },\n });\n },\n });\n\n this.log.info(`Server listening on ${this.hostname}`);\n } catch (err) {\n this.log.error(\"Failed to start Bun server\", err);\n throw err;\n }\n }\n\n protected async close() {\n if (!this.bunServer) {\n return;\n }\n\n try {\n // Bun's server.stop() returns a promise that resolves when all connections are closed\n const stopPromise = this.bunServer.stop();\n\n // Race between stop completion and timeout\n await Promise.race([this.dateTimeProvider.wait(10000), stopPromise]);\n\n this.bunServer = undefined;\n this.log.info(\"Server closed\");\n } catch (err) {\n this.log.error(\"Error closing Bun server\", err);\n throw err;\n }\n }\n}\n","import {\n createServer,\n type IncomingMessage,\n type Server,\n type ServerResponse,\n} from \"node:http\";\nimport { $env, $hook, $inject, Alepha, type Static, t } from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport { ServerProvider } from \"./ServerProvider.ts\";\nimport { ServerRouterProvider } from \"./ServerRouterProvider.ts\";\n\nconst envSchema = t.object({\n SERVER_PORT: t.integer({\n default: 3000,\n min: 0,\n max: 65535,\n description: \"Set 0 to listen on a random port.\",\n }),\n SERVER_HOST: t.text({\n default: \"localhost\",\n description: \"Set 0.0.0.0 to listen on all interfaces.\",\n }),\n});\n\ndeclare module \"alepha\" {\n interface Env extends Partial<Static<typeof envSchema>> {}\n}\n\nexport class NodeHttpServerProvider extends ServerProvider {\n protected readonly alepha = $inject(Alepha);\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n protected readonly log = $logger();\n protected readonly env = $env(envSchema);\n protected readonly router = $inject(ServerRouterProvider);\n\n public get hostname(): string {\n if (this.server.listening) {\n const address = this.server.address();\n if (typeof address === \"object\" && address !== null) {\n return `http://${this.env.SERVER_HOST}:${address.port}`;\n }\n }\n return `http://${this.env.SERVER_HOST}:${this.env.SERVER_PORT}`;\n }\n\n public readonly server = this.createHttpServer((req, res) => {\n this.log.trace(`Incoming Node.js message -> ${req.url}`);\n this.handleNodeRequest({ req, res }).catch((err) => {\n this.log.error(\"Error handling request\", err);\n res.statusCode = 500;\n res.end(\"Internal Server Error\");\n });\n });\n\n public readonly start = $hook({\n on: \"start\",\n handler: async () => {\n await this.listen();\n this.alepha.store.set(\"alepha.node.server\", this.server);\n },\n });\n\n protected createHttpServer(\n func: (req: IncomingMessage, res: ServerResponse) => void,\n ): Server {\n return createServer(\n {\n // nov 25 - keep connections alive for better performance, cuz we http/1.1 by default\n keepAlive: this.alepha.isProduction(),\n },\n func,\n );\n }\n\n protected readonly stop = $hook({\n on: \"stop\",\n handler: async () => {\n if (this.alepha.isProduction()) {\n await this.close();\n return;\n }\n\n // do not await in development & test\n this.close().catch(() => {});\n },\n });\n\n protected async listen() {\n let port = this.env.SERVER_PORT;\n\n // for testing, use a random port if port is 3000 (default)\n if (this.alepha.isTest() && port === 3000) {\n port = 0;\n }\n\n await new Promise<void>((resolve, reject) => {\n this.server?.listen(port, this.env.SERVER_HOST, () => {\n this.log.info(`Server listening on ${this.hostname}`);\n resolve();\n });\n\n this.server?.on(\"error\", (err) => {\n reject(err);\n });\n });\n }\n\n protected async close() {\n const promise = new Promise<void>((resolve, reject) => {\n this.server?.close((err) => {\n if (err) {\n reject(err);\n } else {\n resolve();\n }\n });\n });\n\n await Promise.race([this.dateTimeProvider.wait(2000), promise]);\n\n this.log.info(\"Server closed\");\n }\n}\n","import { ReadableStream as WebStream } from \"node:stream/web\";\nimport { createBrotliDecompress, createGunzip, createInflate } from \"node:zlib\";\nimport type { TSchema } from \"alepha\";\nimport { $env, $hook, $inject, Alepha, t } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { HttpError } from \"../errors/HttpError.ts\";\n\nconst envSchema = t.object({\n SERVER_BODY_PARSER_INFLATE: t.boolean({\n default: true,\n description: \"Enable decompression of request body.\",\n }),\n SERVER_BODY_PARSER_LIMIT: t.integer({\n default: 100_000, // 100KB\n min: 0,\n description: \"Maximum size of request body in bytes.\",\n }),\n});\n\nexport class ServerBodyParserProvider {\n protected readonly env = $env(envSchema);\n protected readonly alepha = $inject(Alepha);\n protected readonly log = $logger();\n\n public readonly onRequest = $hook({\n on: \"server:onRequest\",\n handler: async ({ route, request }) => {\n if (request.body) {\n return; // already parsed\n }\n\n let stream: ReadableStream | undefined;\n\n if (request.raw.web?.req.body) {\n stream = request.raw.web.req.body;\n } else if (request.raw.node?.req) {\n // convert Node.js IncomingMessage to Web ReadableStream\n // TODO: check performance impact, it's better to directly read from Node stream!\n stream = WebStream.from(request.raw.node.req) as ReadableStream;\n }\n\n if (!stream) {\n return;\n }\n\n if (route.schema?.body) {\n try {\n const body = await this.parse(\n stream,\n request.headers,\n route.schema.body,\n );\n if (body) {\n request.body = body;\n }\n } catch (error) {\n if (error instanceof HttpError) {\n throw error;\n }\n\n throw new HttpError(\n {\n status: 400,\n message: \"Failed to parse request body\",\n },\n error,\n );\n }\n }\n },\n });\n\n public async parse(\n stream: ReadableStream,\n headers: Record<string, string>,\n schema: TSchema,\n ): Promise<object | string | undefined> {\n const contentType = headers[\"content-type\"];\n const contentEncoding = headers[\"content-encoding\"];\n\n if (!contentType) return undefined;\n\n if (contentType.startsWith(\"text/plain\") || t.schema.isString(schema)) {\n return this.parseText(stream, contentEncoding);\n }\n\n if (contentType.startsWith(\"application/json\")) {\n return this.parseJson(stream, contentEncoding);\n }\n\n if (contentType.startsWith(\"application/x-www-form-urlencoded\")) {\n return this.parseUrlEncoded(stream, contentEncoding);\n }\n\n return undefined;\n }\n\n public async parseText(\n stream: ReadableStream,\n contentEncoding?: string,\n ): Promise<string> {\n const buffer = await this.streamToBuffer(stream);\n const bufferInflated = await this.maybeDecompress(buffer, contentEncoding);\n return bufferInflated.toString(\"utf-8\");\n }\n\n public async parseUrlEncoded(\n stream: ReadableStream,\n contentEncoding?: string,\n ): Promise<object> {\n const text = await this.parseText(stream, contentEncoding);\n const params = new URLSearchParams(text);\n const result: Record<string, string> = {};\n for (const [key, value] of params.entries()) {\n result[key] = value;\n }\n\n return result;\n }\n\n public async parseJson(\n stream: ReadableStream,\n contentEncoding?: string,\n ): Promise<object> {\n const text = await this.parseText(stream, contentEncoding);\n return JSON.parse(text);\n }\n\n protected async maybeDecompress(\n buffer: Buffer,\n encoding: string | undefined,\n ): Promise<Buffer> {\n if (!this.env.SERVER_BODY_PARSER_INFLATE && encoding) {\n throw new HttpError({\n status: 415,\n message: `Content-Encoding ${encoding} not allowed`,\n });\n }\n\n switch (encoding) {\n case \"gzip\":\n return new Promise((res, rej) =>\n createGunzip()\n .end(buffer, () => {})\n .on(\"data\", res)\n .on(\"error\", rej),\n );\n case \"deflate\":\n return new Promise((res, rej) =>\n createInflate()\n .end(buffer, () => {})\n .on(\"data\", res)\n .on(\"error\", rej),\n );\n case \"br\":\n return new Promise((res, rej) =>\n createBrotliDecompress()\n .end(buffer, () => {})\n .on(\"data\", res)\n .on(\"error\", rej),\n );\n case undefined:\n case \"identity\":\n return buffer;\n default:\n throw new Error(`Unsupported Content-Encoding: ${encoding}`);\n }\n }\n\n /**\n * Convert Web ReadableStream to Buffer, with a size limit.\n *\n * TODO: move to alepha/file FileUtils\n */\n protected async streamToBuffer(stream: ReadableStream): Promise<Buffer> {\n const chunks: Uint8Array[] = [];\n let totalLength = 0;\n\n const reader = stream.getReader();\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) {\n break;\n }\n\n if (value) {\n totalLength += value.length;\n\n if (totalLength > this.env.SERVER_BODY_PARSER_LIMIT) {\n this.log.error(\n `Body size limit exceeded: ${totalLength} > ${this.env.SERVER_BODY_PARSER_LIMIT}`,\n );\n\n await reader.cancel(); // Cancel the stream\n\n throw new HttpError({\n status: 413,\n message: `Request body size limit exceeded`,\n });\n }\n\n chunks.push(value);\n }\n }\n\n // Combine all chunks into a single Buffer\n const combinedLength = chunks.reduce(\n (sum, chunk) => sum + chunk.length,\n 0,\n );\n const combined = new Uint8Array(combinedLength);\n let offset = 0;\n\n for (const chunk of chunks) {\n combined.set(chunk, offset);\n offset += chunk.length;\n }\n\n return Buffer.from(combined);\n } catch (error) {\n // Make sure to release the reader lock\n reader.releaseLock();\n throw error;\n }\n }\n}\n","import { $hook, $inject, Alepha } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\n\nexport class ServerLoggerProvider {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n\n public readonly onRequest = $hook({\n on: \"server:onRequest\",\n priority: \"first\",\n handler: ({ route, request }) => {\n if (!route.silent) {\n request.metadata.now = Date.now();\n\n const data: Record<string, string> = {\n method: request.method,\n path: request.url.pathname,\n };\n\n if (this.alepha.isProduction()) {\n data.agent = request.headers[\"user-agent\"];\n const ip = request.ip;\n if (ip) {\n data.ip = ip;\n }\n }\n\n this.log.info(\"Incoming request\", data);\n }\n },\n });\n\n public readonly onError = $hook({\n on: \"server:onError\",\n priority: \"last\",\n handler: ({ error }) => {\n this.log.error(\"Request has failed\", error);\n },\n });\n\n public readonly onResponse = $hook({\n on: \"server:onResponse\",\n priority: \"last\",\n handler: ({ route, request, response }) => {\n if (!route.silent) {\n const ms = Date.now() - request.metadata.now;\n this.log.info(\"Request completed\", { status: response.status, ms });\n }\n },\n });\n}\n","import { $hook, $inject, Alepha } from \"alepha\";\nimport { HttpError } from \"../errors/HttpError.ts\";\n\n/**\n * On every request, this provider checks if the server is ready.\n *\n * If the server is not ready, it responds with a 503 status code and a message indicating that the server is not ready yet.\n *\n * The response also includes a `Retry-After` header indicating that the client should retry after 5 seconds.\n */\nexport class ServerNotReadyProvider {\n protected readonly alepha = $inject(Alepha);\n\n public readonly onRequest = $hook({\n on: \"server:onRequest\",\n priority: \"first\",\n handler: ({ request: { reply } }) => {\n if (this.alepha.isReady()) {\n return;\n }\n\n reply.headers[\"Retry-After\"] = \"5\"; // Retry after 5 seconds\n\n throw new HttpError({\n status: 503,\n message: \"Server is not ready yet. Please try again later.\",\n });\n },\n });\n}\n","export const routeMethods = [\n // list of supported http methods\n \"GET\",\n \"POST\",\n \"PUT\",\n \"PATCH\",\n \"DELETE\",\n \"HEAD\",\n \"OPTIONS\",\n \"CONNECT\",\n \"TRACE\",\n] as const;\n\nexport type RouteMethod = (typeof routeMethods)[number];\n","import { HttpError } from \"./HttpError.ts\";\n\nexport class BadRequestError extends HttpError {\n constructor(message = \"Invalid request body\", cause?: unknown) {\n super(\n {\n message,\n status: 400,\n },\n cause,\n );\n }\n}\n","import { HttpError } from \"./HttpError.ts\";\n\nexport class ConflictError extends HttpError {\n constructor(message = \"Entity already exists\", cause?: unknown) {\n super(\n {\n message,\n status: 409,\n },\n cause,\n );\n }\n}\n","import { HttpError } from \"./HttpError.ts\";\n\nexport class ForbiddenError extends HttpError {\n constructor(\n message = \"No permission to access this resource\",\n cause?: unknown,\n ) {\n super(\n {\n message,\n status: 403,\n },\n cause,\n );\n }\n}\n","import { HttpError } from \"./HttpError.ts\";\n\nexport class NotFoundError extends HttpError {\n constructor(message = \"Resource not found\", cause?: unknown) {\n super(\n {\n message,\n status: 404,\n },\n cause,\n );\n }\n}\n","import { HttpError } from \"./HttpError.ts\";\n\nexport class UnauthorizedError extends HttpError {\n readonly name = \"UnauthorizedError\";\n\n constructor(\n message = \"Not allowed to access this resource\",\n cause?: unknown,\n ) {\n super(\n {\n message,\n status: 401,\n },\n cause,\n );\n }\n}\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\n\nexport const okSchema = t.object(\n {\n ok: t.boolean({ description: \"True when operation succeed\" }),\n id: t.optional(t.union([t.text(), t.integer()])),\n count: t.optional(\n t.number({ description: \"Number of resources affected\" }),\n ),\n },\n {\n title: \"Ok\",\n description: \"Generic response after a successful operation on a resource\",\n },\n);\n\nexport type Ok = Static<typeof okSchema>;\n","import type { Server } from \"node:http\";\nimport { $module, type Alepha, type PrimitiveFactoryLike } from \"alepha\";\nimport type { HttpError } from \"./errors/HttpError.ts\";\nimport type {\n NodeRequestEvent,\n RequestConfigSchema,\n ServerRequest,\n ServerRequestConfigEntry,\n ServerResponse,\n ServerRoute,\n WebRequestEvent,\n} from \"./interfaces/ServerRequest.ts\";\nimport {\n $action,\n type ActionPrimitive,\n type ClientRequestOptions,\n} from \"./primitives/$action.ts\";\nimport { $route } from \"./primitives/$route.ts\";\nimport { BunHttpServerProvider } from \"./providers/BunHttpServerProvider.ts\";\nimport { NodeHttpServerProvider } from \"./providers/NodeHttpServerProvider.ts\";\nimport { ServerBodyParserProvider } from \"./providers/ServerBodyParserProvider.ts\";\nimport { ServerLoggerProvider } from \"./providers/ServerLoggerProvider.ts\";\nimport { ServerNotReadyProvider } from \"./providers/ServerNotReadyProvider.ts\";\nimport { ServerProvider } from \"./providers/ServerProvider.ts\";\nimport { ServerRouterProvider } from \"./providers/ServerRouterProvider.ts\";\nimport { ServerTimingProvider } from \"./providers/ServerTimingProvider.ts\";\nimport type { FetchOptions, HttpAction } from \"./services/HttpClient.ts\";\nimport { HttpClient } from \"./services/HttpClient.ts\";\nimport { ServerRequestParser } from \"./services/ServerRequestParser.ts\";\nimport { UserAgentParser } from \"./services/UserAgentParser.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"alepha\" {\n interface State {\n \"alepha.node.server\"?: Server;\n }\n interface Hooks {\n // -----------------------------------------------------------------------------------------------------------------\n // Local Actions hooks\n \"action:onRequest\": {\n action: ActionPrimitive<RequestConfigSchema>;\n request: ServerRequest;\n options: ClientRequestOptions;\n };\n \"action:onResponse\": {\n action: ActionPrimitive<RequestConfigSchema>;\n request: ServerRequest;\n options: ClientRequestOptions;\n response: any;\n };\n // -----------------------------------------------------------------------------------------------------------------\n // Server hooks\n \"server:onRequest\": {\n route: ServerRoute;\n request: ServerRequest;\n };\n \"server:onError\": {\n route: ServerRoute;\n request: ServerRequest;\n error: Error;\n };\n // last chance to modify the response -\n // TODO: probably not really needed, we can also update the response in the onResponse hook...\n \"server:onSend\": {\n route: ServerRoute;\n request: ServerRequest;\n };\n // response is ready\n \"server:onResponse\": {\n route: ServerRoute;\n request: ServerRequest;\n response: ServerResponse;\n };\n // -----------------------------------------------------------------------------------------------------------------\n // Http client hooks\n \"client:onRequest\": {\n route: HttpAction;\n config: ServerRequestConfigEntry;\n options: ClientRequestOptions;\n headers: Record<string, string>;\n request: RequestInit;\n };\n \"client:beforeFetch\": {\n url: string;\n options: FetchOptions;\n request: RequestInit;\n };\n \"client:onError\": {\n route?: HttpAction;\n error: HttpError;\n };\n // -----------------------------------------------------------------------------------------------------------------\n // Internal hooks\n \"node:request\": NodeRequestEvent;\n \"web:request\": WebRequestEvent;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./index.shared.ts\";\nexport * from \"./primitives/$action.ts\";\nexport * from \"./primitives/$route.ts\";\nexport * from \"./providers/BunHttpServerProvider.ts\";\nexport * from \"./providers/NodeHttpServerProvider.ts\";\nexport * from \"./providers/ServerLoggerProvider.ts\";\nexport * from \"./providers/ServerNotReadyProvider.ts\";\nexport * from \"./providers/ServerProvider.ts\";\nexport * from \"./providers/ServerRouterProvider.ts\";\nexport * from \"./providers/ServerTimingProvider.ts\";\nexport * from \"./services/UserAgentParser.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Provides high-performance HTTP server capabilities with declarative routing and action primitives.\n *\n * The server module enables building REST APIs and web applications using `$route` and `$action` primitives\n * on class properties. It provides automatic request/response handling, schema validation, middleware support,\n * and seamless integration with other Alepha modules for a complete backend solution.\n *\n * @see {@link $route}\n * @see {@link $action}\n * @module alepha.server\n */\nexport const AlephaServer = $module({\n name: \"alepha.server\",\n primitives: [$route, $action as PrimitiveFactoryLike],\n services: [\n ServerProvider,\n BunHttpServerProvider,\n NodeHttpServerProvider,\n ServerBodyParserProvider,\n ServerLoggerProvider,\n ServerNotReadyProvider,\n ServerTimingProvider,\n HttpClient,\n UserAgentParser,\n ServerRequestParser,\n ServerRouterProvider,\n ],\n register: (alepha: Alepha) => {\n if (!alepha.isServerless() && !alepha.isViteDev()) {\n if (alepha.isBun()) {\n alepha.with({\n optional: true,\n provide: ServerProvider,\n use: BunHttpServerProvider,\n });\n } else {\n alepha.with({\n optional: true,\n provide: ServerProvider,\n use: NodeHttpServerProvider,\n });\n }\n } else {\n alepha.with(ServerProvider);\n }\n\n alepha.with(ServerBodyParserProvider);\n alepha.with(ServerLoggerProvider);\n alepha.with(ServerNotReadyProvider);\n\n if (!alepha.isProduction()) {\n alepha.with(ServerTimingProvider);\n }\n },\n});\n"],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ import { KIND, Primitive, Static } from "alepha";
|
|
|
3
3
|
import * as alepha_logger0 from "alepha/logger";
|
|
4
4
|
import { ServerRouterProvider } from "alepha/server";
|
|
5
5
|
|
|
6
|
-
//#region ../../src/server
|
|
6
|
+
//#region ../../src/server/cors/primitives/$cors.d.ts
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Declares CORS configuration for specific server routes.
|
|
@@ -41,7 +41,7 @@ declare class CorsPrimitive extends Primitive<CorsPrimitiveConfig> implements Ab
|
|
|
41
41
|
protected onInit(): void;
|
|
42
42
|
}
|
|
43
43
|
//#endregion
|
|
44
|
-
//#region ../../src/server
|
|
44
|
+
//#region ../../src/server/cors/providers/ServerCorsProvider.d.ts
|
|
45
45
|
/**
|
|
46
46
|
* CORS configuration atom (global defaults)
|
|
47
47
|
*/
|
|
@@ -98,7 +98,7 @@ declare class ServerCorsProvider {
|
|
|
98
98
|
}
|
|
99
99
|
type ServerCorsProviderOptions = CorsOptions;
|
|
100
100
|
//#endregion
|
|
101
|
-
//#region ../../src/server
|
|
101
|
+
//#region ../../src/server/cors/index.d.ts
|
|
102
102
|
declare module "alepha/server" {
|
|
103
103
|
interface ServerRoute {
|
|
104
104
|
/**
|