alepha 0.15.0 → 0.15.2
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 +43 -98
- package/dist/api/audits/index.d.ts +630 -653
- package/dist/api/audits/index.d.ts.map +1 -1
- package/dist/api/audits/index.js +12 -35
- package/dist/api/audits/index.js.map +1 -1
- package/dist/api/files/index.d.ts +365 -358
- package/dist/api/files/index.d.ts.map +1 -1
- package/dist/api/files/index.js +12 -5
- package/dist/api/files/index.js.map +1 -1
- package/dist/api/jobs/index.d.ts +255 -248
- package/dist/api/jobs/index.d.ts.map +1 -1
- package/dist/api/jobs/index.js +10 -3
- package/dist/api/jobs/index.js.map +1 -1
- package/dist/api/keys/index.d.ts +413 -0
- package/dist/api/keys/index.d.ts.map +1 -0
- package/dist/api/keys/index.js +476 -0
- package/dist/api/keys/index.js.map +1 -0
- package/dist/api/notifications/index.browser.js +4 -4
- package/dist/api/notifications/index.browser.js.map +1 -1
- package/dist/api/notifications/index.d.ts +84 -78
- package/dist/api/notifications/index.d.ts.map +1 -1
- package/dist/api/notifications/index.js +14 -8
- package/dist/api/notifications/index.js.map +1 -1
- package/dist/api/parameters/index.d.ts +528 -535
- package/dist/api/parameters/index.d.ts.map +1 -1
- package/dist/api/parameters/index.js +30 -37
- package/dist/api/parameters/index.js.map +1 -1
- package/dist/api/users/index.d.ts +1221 -910
- package/dist/api/users/index.d.ts.map +1 -1
- package/dist/api/users/index.js +2556 -248
- package/dist/api/users/index.js.map +1 -1
- package/dist/api/verifications/index.d.ts +142 -136
- package/dist/api/verifications/index.d.ts.map +1 -1
- package/dist/api/verifications/index.js +12 -4
- package/dist/api/verifications/index.js.map +1 -1
- package/dist/batch/index.d.ts +142 -162
- package/dist/batch/index.d.ts.map +1 -1
- package/dist/batch/index.js +31 -44
- package/dist/batch/index.js.map +1 -1
- package/dist/bucket/index.d.ts +595 -171
- package/dist/bucket/index.d.ts.map +1 -1
- package/dist/bucket/index.js +1856 -12
- package/dist/bucket/index.js.map +1 -1
- package/dist/cache/core/index.d.ts +225 -53
- package/dist/cache/core/index.d.ts.map +1 -1
- package/dist/cache/core/index.js +213 -7
- package/dist/cache/core/index.js.map +1 -1
- package/dist/cache/redis/index.d.ts +1 -0
- package/dist/cache/redis/index.d.ts.map +1 -1
- package/dist/cache/redis/index.js +6 -2
- package/dist/cache/redis/index.js.map +1 -1
- package/dist/cli/index.d.ts +834 -226
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +2872 -417
- package/dist/cli/index.js.map +1 -1
- package/dist/command/index.d.ts +458 -310
- package/dist/command/index.d.ts.map +1 -1
- package/dist/command/index.js +2011 -76
- package/dist/command/index.js.map +1 -1
- package/dist/core/index.browser.js +309 -97
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +796 -701
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +329 -97
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js +309 -97
- package/dist/core/index.native.js.map +1 -1
- package/dist/datetime/index.d.ts +59 -44
- package/dist/datetime/index.d.ts.map +1 -1
- package/dist/datetime/index.js +15 -0
- package/dist/datetime/index.js.map +1 -1
- package/dist/email/index.d.ts +314 -19
- package/dist/email/index.d.ts.map +1 -1
- package/dist/email/index.js +1852 -7
- package/dist/email/index.js.map +1 -1
- package/dist/fake/index.d.ts +5500 -5418
- package/dist/fake/index.d.ts.map +1 -1
- package/dist/fake/index.js +113 -42
- package/dist/fake/index.js.map +1 -1
- package/dist/lock/core/index.d.ts +219 -212
- package/dist/lock/core/index.d.ts.map +1 -1
- package/dist/lock/core/index.js +11 -4
- package/dist/lock/core/index.js.map +1 -1
- package/dist/lock/redis/index.d.ts.map +1 -1
- package/dist/logger/index.d.ts +41 -90
- package/dist/logger/index.d.ts.map +1 -1
- package/dist/logger/index.js +15 -68
- package/dist/logger/index.js.map +1 -1
- package/dist/mcp/index.d.ts +228 -230
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +32 -31
- package/dist/mcp/index.js.map +1 -1
- package/dist/orm/index.browser.js +12 -12
- package/dist/orm/index.browser.js.map +1 -1
- package/dist/orm/index.bun.js +90 -80
- package/dist/orm/index.bun.js.map +1 -1
- package/dist/orm/index.d.ts +1434 -1459
- package/dist/orm/index.d.ts.map +1 -1
- package/dist/orm/index.js +112 -130
- package/dist/orm/index.js.map +1 -1
- package/dist/queue/core/index.d.ts +262 -254
- package/dist/queue/core/index.d.ts.map +1 -1
- package/dist/queue/core/index.js +14 -6
- package/dist/queue/core/index.js.map +1 -1
- package/dist/queue/redis/index.d.ts.map +1 -1
- package/dist/react/auth/index.browser.js +108 -0
- package/dist/react/auth/index.browser.js.map +1 -0
- package/dist/react/auth/index.d.ts +100 -0
- package/dist/react/auth/index.d.ts.map +1 -0
- package/dist/react/auth/index.js +145 -0
- package/dist/react/auth/index.js.map +1 -0
- package/dist/react/core/index.d.ts +469 -0
- package/dist/react/core/index.d.ts.map +1 -0
- package/dist/react/core/index.js +464 -0
- package/dist/react/core/index.js.map +1 -0
- package/dist/react/form/index.d.ts +232 -0
- package/dist/react/form/index.d.ts.map +1 -0
- package/dist/react/form/index.js +432 -0
- package/dist/react/form/index.js.map +1 -0
- package/dist/react/head/index.browser.js +423 -0
- package/dist/react/head/index.browser.js.map +1 -0
- package/dist/react/head/index.d.ts +288 -0
- package/dist/react/head/index.d.ts.map +1 -0
- package/dist/react/head/index.js +465 -0
- package/dist/react/head/index.js.map +1 -0
- package/dist/react/i18n/index.d.ts +175 -0
- package/dist/react/i18n/index.d.ts.map +1 -0
- package/dist/react/i18n/index.js +224 -0
- package/dist/react/i18n/index.js.map +1 -0
- package/dist/react/router/index.browser.js +1980 -0
- package/dist/react/router/index.browser.js.map +1 -0
- package/dist/react/router/index.d.ts +2068 -0
- package/dist/react/router/index.d.ts.map +1 -0
- package/dist/react/router/index.js +4932 -0
- package/dist/react/router/index.js.map +1 -0
- package/dist/react/websocket/index.d.ts +117 -0
- package/dist/react/websocket/index.d.ts.map +1 -0
- package/dist/react/websocket/index.js +107 -0
- package/dist/react/websocket/index.js.map +1 -0
- package/dist/redis/index.bun.js +4 -0
- package/dist/redis/index.bun.js.map +1 -1
- package/dist/redis/index.d.ts +127 -130
- package/dist/redis/index.d.ts.map +1 -1
- package/dist/redis/index.js +16 -25
- package/dist/redis/index.js.map +1 -1
- package/dist/retry/index.d.ts +80 -71
- package/dist/retry/index.d.ts.map +1 -1
- package/dist/retry/index.js +11 -2
- package/dist/retry/index.js.map +1 -1
- package/dist/router/index.d.ts +6 -6
- package/dist/router/index.d.ts.map +1 -1
- package/dist/scheduler/index.d.ts +119 -28
- package/dist/scheduler/index.d.ts.map +1 -1
- package/dist/scheduler/index.js +404 -3
- package/dist/scheduler/index.js.map +1 -1
- package/dist/security/index.d.ts +642 -228
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +1579 -37
- package/dist/security/index.js.map +1 -1
- package/dist/server/auth/index.d.ts +1141 -111
- package/dist/server/auth/index.d.ts.map +1 -1
- package/dist/server/auth/index.js +1261 -25
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/cache/index.d.ts +63 -78
- package/dist/server/cache/index.d.ts.map +1 -1
- package/dist/server/cache/index.js +7 -22
- package/dist/server/cache/index.js.map +1 -1
- package/dist/server/compress/index.d.ts +13 -5
- package/dist/server/compress/index.d.ts.map +1 -1
- package/dist/server/compress/index.js +10 -2
- package/dist/server/compress/index.js.map +1 -1
- package/dist/server/cookies/index.d.ts +46 -22
- package/dist/server/cookies/index.d.ts.map +1 -1
- package/dist/server/cookies/index.js +7 -5
- package/dist/server/cookies/index.js.map +1 -1
- package/dist/server/core/index.d.ts +307 -196
- package/dist/server/core/index.d.ts.map +1 -1
- package/dist/server/core/index.js +271 -38
- package/dist/server/core/index.js.map +1 -1
- package/dist/server/cors/index.d.ts +24 -34
- package/dist/server/cors/index.d.ts.map +1 -1
- package/dist/server/cors/index.js +7 -21
- package/dist/server/cors/index.js.map +1 -1
- package/dist/server/health/index.d.ts +25 -19
- package/dist/server/health/index.d.ts.map +1 -1
- package/dist/server/health/index.js +8 -2
- package/dist/server/health/index.js.map +1 -1
- package/dist/server/helmet/index.d.ts +13 -5
- package/dist/server/helmet/index.d.ts.map +1 -1
- package/dist/server/helmet/index.js +11 -3
- package/dist/server/helmet/index.js.map +1 -1
- package/dist/server/links/index.browser.js +9 -1
- package/dist/server/links/index.browser.js.map +1 -1
- package/dist/server/links/index.d.ts +133 -128
- package/dist/server/links/index.d.ts.map +1 -1
- package/dist/server/links/index.js +24 -11
- package/dist/server/links/index.js.map +1 -1
- package/dist/server/metrics/index.d.ts +524 -4
- package/dist/server/metrics/index.d.ts.map +1 -1
- package/dist/server/metrics/index.js +4472 -7
- package/dist/server/metrics/index.js.map +1 -1
- package/dist/server/multipart/index.d.ts +15 -9
- package/dist/server/multipart/index.d.ts.map +1 -1
- package/dist/server/multipart/index.js +9 -3
- package/dist/server/multipart/index.js.map +1 -1
- package/dist/server/proxy/index.d.ts +110 -104
- package/dist/server/proxy/index.d.ts.map +1 -1
- package/dist/server/proxy/index.js +8 -2
- package/dist/server/proxy/index.js.map +1 -1
- package/dist/server/rate-limit/index.d.ts +46 -51
- package/dist/server/rate-limit/index.d.ts.map +1 -1
- package/dist/server/rate-limit/index.js +18 -55
- package/dist/server/rate-limit/index.js.map +1 -1
- package/dist/server/static/index.d.ts +181 -48
- package/dist/server/static/index.d.ts.map +1 -1
- package/dist/server/static/index.js +1848 -5
- package/dist/server/static/index.js.map +1 -1
- package/dist/server/swagger/index.d.ts +348 -53
- package/dist/server/swagger/index.d.ts.map +1 -1
- package/dist/server/swagger/index.js +1849 -6
- package/dist/server/swagger/index.js.map +1 -1
- package/dist/sms/index.d.ts +312 -18
- package/dist/sms/index.d.ts.map +1 -1
- package/dist/sms/index.js +1854 -10
- package/dist/sms/index.js.map +1 -1
- package/dist/system/index.browser.js +496 -0
- package/dist/system/index.browser.js.map +1 -0
- package/dist/system/index.d.ts +1158 -0
- package/dist/system/index.d.ts.map +1 -0
- package/dist/{file → system}/index.js +412 -20
- package/dist/system/index.js.map +1 -0
- package/dist/thread/index.d.ts +82 -73
- package/dist/thread/index.d.ts.map +1 -1
- package/dist/thread/index.js +13 -4
- package/dist/thread/index.js.map +1 -1
- package/dist/topic/core/index.d.ts +330 -323
- package/dist/topic/core/index.d.ts.map +1 -1
- package/dist/topic/core/index.js +12 -5
- package/dist/topic/core/index.js.map +1 -1
- package/dist/topic/redis/index.d.ts +6 -6
- package/dist/topic/redis/index.d.ts.map +1 -1
- package/dist/vite/index.d.ts +163 -5825
- package/dist/vite/index.d.ts.map +1 -1
- package/dist/vite/index.js +130 -477
- 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.d.ts +287 -283
- package/dist/websocket/index.d.ts.map +1 -1
- package/dist/websocket/index.js +15 -11
- package/dist/websocket/index.js.map +1 -1
- package/package.json +86 -17
- package/src/api/audits/index.ts +10 -33
- package/src/api/files/__tests__/$bucket.spec.ts +1 -1
- package/src/api/files/controllers/AdminFileStatsController.spec.ts +1 -1
- package/src/api/files/controllers/FileController.spec.ts +1 -1
- package/src/api/files/index.ts +10 -3
- package/src/api/files/jobs/FileJobs.spec.ts +1 -1
- package/src/api/files/services/FileService.spec.ts +1 -1
- package/src/api/jobs/index.ts +10 -3
- package/src/api/keys/controllers/AdminApiKeyController.ts +75 -0
- package/src/api/keys/controllers/ApiKeyController.ts +103 -0
- package/src/api/keys/entities/apiKeyEntity.ts +41 -0
- package/src/api/keys/index.ts +49 -0
- package/src/api/keys/schemas/adminApiKeyQuerySchema.ts +7 -0
- package/src/api/keys/schemas/adminApiKeyResourceSchema.ts +17 -0
- package/src/api/keys/schemas/createApiKeyBodySchema.ts +7 -0
- package/src/api/keys/schemas/createApiKeyResponseSchema.ts +11 -0
- package/src/api/keys/schemas/listApiKeyResponseSchema.ts +15 -0
- package/src/api/keys/schemas/revokeApiKeyParamsSchema.ts +5 -0
- package/src/api/keys/schemas/revokeApiKeyResponseSchema.ts +5 -0
- package/src/api/keys/services/ApiKeyService.spec.ts +553 -0
- package/src/api/keys/services/ApiKeyService.ts +306 -0
- package/src/api/logs/TODO.md +52 -0
- package/src/api/notifications/index.ts +10 -4
- package/src/api/parameters/index.ts +9 -30
- package/src/api/parameters/primitives/$config.ts +12 -4
- package/src/api/parameters/services/ConfigStore.ts +9 -3
- package/src/api/users/__tests__/ApiKeys-integration.spec.ts +1035 -0
- package/src/api/users/__tests__/ApiKeys.spec.ts +401 -0
- package/src/api/users/index.ts +14 -3
- package/src/api/users/primitives/$realm.ts +33 -5
- package/src/api/users/providers/RealmProvider.ts +1 -12
- package/src/api/users/services/SessionService.ts +1 -11
- package/src/api/verifications/controllers/VerificationController.ts +2 -0
- package/src/api/verifications/index.ts +10 -4
- package/src/batch/index.ts +9 -36
- package/src/batch/primitives/$batch.ts +0 -8
- package/src/batch/providers/BatchProvider.ts +29 -2
- package/src/bucket/__tests__/shared.ts +1 -1
- package/src/bucket/index.ts +13 -6
- package/src/bucket/primitives/$bucket.ts +1 -1
- package/src/bucket/providers/LocalFileStorageProvider.ts +1 -1
- package/src/bucket/providers/MemoryFileStorageProvider.ts +1 -1
- package/src/cache/core/__tests__/shared.ts +30 -0
- package/src/cache/core/index.ts +11 -6
- package/src/cache/core/primitives/$cache.spec.ts +5 -0
- package/src/cache/core/providers/CacheProvider.ts +17 -0
- package/src/cache/core/providers/MemoryCacheProvider.ts +300 -1
- package/src/cache/redis/__tests__/cache-redis.spec.ts +5 -0
- package/src/cache/redis/providers/RedisCacheProvider.ts +9 -0
- package/src/cli/apps/AlephaCli.ts +3 -16
- package/src/cli/apps/AlephaPackageBuilderCli.ts +10 -2
- package/src/cli/atoms/appEntryOptions.ts +13 -0
- package/src/cli/atoms/buildOptions.ts +1 -1
- package/src/cli/atoms/changelogOptions.ts +1 -1
- package/src/cli/commands/build.ts +64 -52
- package/src/cli/commands/db.ts +17 -11
- package/src/cli/commands/deploy.ts +1 -1
- package/src/cli/commands/dev.ts +13 -49
- package/src/cli/commands/gen/env.ts +6 -3
- package/src/cli/commands/gen/openapi.ts +5 -2
- package/src/cli/commands/init.spec.ts +544 -0
- package/src/cli/commands/init.ts +101 -58
- package/src/cli/commands/lint.ts +8 -2
- package/src/cli/commands/typecheck.ts +11 -0
- package/src/cli/defineConfig.ts +9 -0
- package/src/cli/index.ts +2 -1
- package/src/cli/providers/AppEntryProvider.ts +131 -0
- package/src/cli/providers/ViteBuildProvider.ts +40 -0
- package/src/cli/providers/ViteDevServerProvider.ts +378 -0
- package/src/cli/services/AlephaCliUtils.ts +39 -93
- package/src/cli/services/PackageManagerUtils.ts +140 -17
- package/src/cli/services/ProjectScaffolder.ts +169 -101
- package/src/cli/services/ViteUtils.ts +82 -0
- package/src/cli/{assets/claudeMd.ts → templates/agentMd.ts} +41 -28
- package/src/cli/{assets → templates}/apiHelloControllerTs.ts +2 -1
- package/src/cli/{assets → templates}/biomeJson.ts +2 -1
- package/src/cli/{assets → templates}/dummySpecTs.ts +2 -1
- package/src/cli/{assets → templates}/editorconfig.ts +2 -1
- package/src/cli/templates/gitignore.ts +39 -0
- package/src/cli/{assets → templates}/mainBrowserTs.ts +2 -1
- package/src/cli/templates/mainCss.ts +33 -0
- package/src/cli/templates/mainServerTs.ts +33 -0
- package/src/cli/{assets → templates}/tsconfigJson.ts +2 -1
- package/src/cli/templates/webAppRouterTs.ts +50 -0
- package/src/cli/templates/webHelloComponentTsx.ts +20 -0
- package/src/command/helpers/Runner.spec.ts +4 -0
- package/src/command/helpers/Runner.ts +3 -21
- package/src/command/index.ts +12 -4
- package/src/command/providers/CliProvider.spec.ts +1067 -0
- package/src/command/providers/CliProvider.ts +203 -40
- package/src/core/Alepha.ts +3 -9
- package/src/core/__tests__/Alepha-start.spec.ts +4 -4
- package/src/core/helpers/jsonSchemaToTypeBox.spec.ts +771 -0
- package/src/core/helpers/jsonSchemaToTypeBox.ts +62 -10
- package/src/core/index.shared.ts +1 -0
- package/src/core/index.ts +20 -0
- package/src/core/primitives/$module.ts +12 -0
- package/src/core/providers/EventManager.spec.ts +0 -71
- package/src/core/providers/EventManager.ts +3 -15
- package/src/core/providers/Json.ts +2 -14
- package/src/core/providers/KeylessJsonSchemaCodec.spec.ts +257 -0
- package/src/core/providers/KeylessJsonSchemaCodec.ts +396 -14
- package/src/core/providers/SchemaValidator.spec.ts +236 -0
- package/src/datetime/index.ts +15 -0
- package/src/email/index.ts +10 -5
- package/src/email/providers/LocalEmailProvider.spec.ts +1 -1
- package/src/email/providers/LocalEmailProvider.ts +1 -1
- package/src/fake/__tests__/keyName.example.ts +1 -1
- package/src/fake/__tests__/keyName.spec.ts +5 -5
- package/src/fake/index.ts +9 -6
- package/src/fake/providers/FakeProvider.spec.ts +258 -40
- package/src/fake/providers/FakeProvider.ts +133 -19
- package/src/lock/core/index.ts +11 -4
- package/src/logger/index.ts +17 -66
- package/src/logger/providers/PrettyFormatterProvider.ts +0 -9
- package/src/mcp/errors/McpError.ts +30 -0
- package/src/mcp/index.ts +13 -27
- package/src/mcp/transports/SseMcpTransport.ts +6 -7
- package/src/orm/__tests__/PostgresProvider.spec.ts +2 -2
- package/src/orm/index.browser.ts +2 -2
- package/src/orm/index.bun.ts +4 -2
- package/src/orm/index.ts +21 -47
- package/src/orm/providers/DrizzleKitProvider.ts +3 -5
- package/src/orm/providers/drivers/BunSqliteProvider.ts +1 -0
- package/src/orm/services/Repository.ts +18 -3
- package/src/queue/core/index.ts +14 -6
- package/src/react/auth/__tests__/$auth.spec.ts +202 -0
- package/src/react/auth/hooks/useAuth.ts +32 -0
- package/src/react/auth/index.browser.ts +13 -0
- package/src/react/auth/index.shared.ts +2 -0
- package/src/react/auth/index.ts +48 -0
- package/src/react/auth/providers/ReactAuthProvider.ts +16 -0
- package/src/react/auth/services/ReactAuth.ts +135 -0
- package/src/react/core/__tests__/Router.spec.tsx +169 -0
- package/src/react/core/components/ClientOnly.tsx +49 -0
- package/src/react/core/components/ErrorBoundary.tsx +73 -0
- package/src/react/core/contexts/AlephaContext.ts +7 -0
- package/src/react/core/contexts/AlephaProvider.tsx +42 -0
- package/src/react/core/hooks/useAction.browser.spec.tsx +569 -0
- package/src/react/core/hooks/useAction.ts +480 -0
- package/src/react/core/hooks/useAlepha.ts +26 -0
- package/src/react/core/hooks/useClient.ts +17 -0
- package/src/react/core/hooks/useEvents.ts +51 -0
- package/src/react/core/hooks/useInject.ts +12 -0
- package/src/react/core/hooks/useStore.ts +52 -0
- package/src/react/core/index.ts +90 -0
- package/src/react/form/components/FormState.tsx +17 -0
- package/src/react/form/errors/FormValidationError.ts +18 -0
- package/src/react/form/hooks/useForm.browser.spec.tsx +366 -0
- package/src/react/form/hooks/useForm.ts +47 -0
- package/src/react/form/hooks/useFormState.ts +130 -0
- package/src/react/form/index.ts +44 -0
- package/src/react/form/services/FormModel.ts +614 -0
- package/src/react/head/helpers/SeoExpander.spec.ts +203 -0
- package/src/react/head/helpers/SeoExpander.ts +142 -0
- package/src/react/head/hooks/useHead.spec.tsx +288 -0
- package/src/react/head/hooks/useHead.ts +62 -0
- package/src/react/head/index.browser.ts +26 -0
- package/src/react/head/index.ts +44 -0
- package/src/react/head/interfaces/Head.ts +105 -0
- package/src/react/head/primitives/$head.ts +25 -0
- package/src/react/head/providers/BrowserHeadProvider.browser.spec.ts +196 -0
- package/src/react/head/providers/BrowserHeadProvider.ts +212 -0
- package/src/react/head/providers/HeadProvider.ts +168 -0
- package/src/react/head/providers/ServerHeadProvider.ts +31 -0
- package/src/react/i18n/__tests__/integration.spec.tsx +239 -0
- package/src/react/i18n/components/Localize.spec.tsx +357 -0
- package/src/react/i18n/components/Localize.tsx +35 -0
- package/src/react/i18n/hooks/useI18n.browser.spec.tsx +438 -0
- package/src/react/i18n/hooks/useI18n.ts +18 -0
- package/src/react/i18n/index.ts +41 -0
- package/src/react/i18n/primitives/$dictionary.ts +69 -0
- package/src/react/i18n/providers/I18nProvider.spec.ts +389 -0
- package/src/react/i18n/providers/I18nProvider.ts +278 -0
- package/src/react/router/__tests__/page-head-browser.browser.spec.ts +95 -0
- package/src/react/router/__tests__/page-head.spec.ts +48 -0
- package/src/react/router/__tests__/seo-head.spec.ts +125 -0
- package/src/react/router/atoms/ssrManifestAtom.ts +58 -0
- package/src/react/router/components/ErrorViewer.tsx +872 -0
- package/src/react/router/components/Link.tsx +23 -0
- package/src/react/router/components/NestedView.tsx +223 -0
- package/src/react/router/components/NotFound.tsx +30 -0
- package/src/react/router/constants/PAGE_PRELOAD_KEY.ts +6 -0
- package/src/react/router/contexts/RouterLayerContext.ts +12 -0
- package/src/react/router/errors/Redirection.ts +28 -0
- package/src/react/router/hooks/useActive.ts +52 -0
- package/src/react/router/hooks/useQueryParams.ts +63 -0
- package/src/react/router/hooks/useRouter.ts +20 -0
- package/src/react/router/hooks/useRouterState.ts +11 -0
- package/src/react/router/index.browser.ts +45 -0
- package/src/react/router/index.shared.ts +19 -0
- package/src/react/router/index.ts +142 -0
- package/src/react/router/primitives/$page.browser.spec.tsx +851 -0
- package/src/react/router/primitives/$page.spec.tsx +708 -0
- package/src/react/router/primitives/$page.ts +497 -0
- package/src/react/router/providers/ReactBrowserProvider.ts +309 -0
- package/src/react/router/providers/ReactBrowserRendererProvider.ts +25 -0
- package/src/react/router/providers/ReactBrowserRouterProvider.ts +168 -0
- package/src/react/router/providers/ReactPageProvider.ts +726 -0
- package/src/react/router/providers/ReactServerProvider.spec.tsx +316 -0
- package/src/react/router/providers/ReactServerProvider.ts +558 -0
- package/src/react/router/providers/ReactServerTemplateProvider.ts +979 -0
- package/src/react/router/providers/SSRManifestProvider.ts +334 -0
- package/src/react/router/services/ReactPageServerService.ts +48 -0
- package/src/react/router/services/ReactPageService.ts +27 -0
- package/src/react/router/services/ReactRouter.ts +262 -0
- package/src/react/websocket/hooks/useRoom.tsx +242 -0
- package/src/react/websocket/index.ts +7 -0
- package/src/redis/__tests__/redis.spec.ts +13 -0
- package/src/redis/index.ts +9 -25
- package/src/redis/providers/BunRedisProvider.ts +9 -0
- package/src/redis/providers/NodeRedisProvider.ts +8 -0
- package/src/redis/providers/RedisProvider.ts +16 -0
- package/src/retry/index.ts +11 -2
- package/src/router/index.ts +15 -0
- package/src/scheduler/index.ts +11 -2
- package/src/security/__tests__/BasicAuth.spec.ts +2 -0
- package/src/security/__tests__/ServerSecurityProvider.spec.ts +13 -5
- package/src/security/index.ts +15 -10
- package/src/security/interfaces/IssuerResolver.ts +27 -0
- package/src/security/primitives/$issuer.ts +55 -0
- package/src/security/providers/SecurityProvider.ts +179 -0
- package/src/security/providers/ServerBasicAuthProvider.ts +6 -2
- package/src/security/providers/ServerSecurityProvider.ts +36 -22
- package/src/server/auth/index.ts +12 -7
- package/src/server/cache/index.ts +7 -22
- package/src/server/compress/index.ts +10 -2
- package/src/server/cookies/index.ts +7 -5
- package/src/server/cookies/primitives/$cookie.ts +33 -11
- package/src/server/core/index.ts +17 -7
- package/src/server/core/interfaces/ServerRequest.ts +83 -1
- package/src/server/core/primitives/$action.spec.ts +1 -1
- package/src/server/core/primitives/$action.ts +8 -3
- package/src/server/core/providers/BunHttpServerProvider.ts +1 -1
- package/src/server/core/providers/NodeHttpServerProvider.spec.ts +125 -0
- package/src/server/core/providers/NodeHttpServerProvider.ts +77 -22
- package/src/server/core/providers/ServerLoggerProvider.ts +2 -2
- package/src/server/core/providers/ServerProvider.ts +9 -12
- package/src/server/core/services/ServerRequestParser.spec.ts +520 -0
- package/src/server/core/services/ServerRequestParser.ts +306 -13
- package/src/server/cors/index.ts +7 -21
- package/src/server/cors/primitives/$cors.ts +6 -2
- package/src/server/health/index.ts +8 -2
- package/src/server/helmet/index.ts +11 -3
- package/src/server/links/atoms/apiLinksAtom.ts +7 -0
- package/src/server/links/index.browser.ts +2 -0
- package/src/server/links/index.ts +13 -6
- package/src/server/metrics/index.ts +10 -3
- package/src/server/multipart/index.ts +9 -3
- package/src/server/proxy/index.ts +8 -2
- package/src/server/rate-limit/index.ts +21 -25
- package/src/server/rate-limit/primitives/$rateLimit.ts +6 -2
- package/src/server/rate-limit/providers/ServerRateLimitProvider.spec.ts +38 -14
- package/src/server/rate-limit/providers/ServerRateLimitProvider.ts +22 -56
- package/src/server/static/index.ts +8 -2
- package/src/server/static/providers/ServerStaticProvider.ts +1 -1
- package/src/server/swagger/index.ts +9 -4
- package/src/server/swagger/providers/ServerSwaggerProvider.ts +1 -1
- package/src/sms/index.ts +9 -5
- package/src/sms/providers/LocalSmsProvider.spec.ts +1 -1
- package/src/sms/providers/LocalSmsProvider.ts +1 -1
- package/src/system/index.browser.ts +11 -0
- package/src/system/index.ts +62 -0
- package/src/{file → system}/providers/FileSystemProvider.ts +16 -0
- package/src/{file → system}/providers/MemoryFileSystemProvider.ts +116 -3
- package/src/system/providers/MemoryShellProvider.ts +164 -0
- package/src/{file → system}/providers/NodeFileSystemProvider.spec.ts +2 -2
- package/src/{file → system}/providers/NodeFileSystemProvider.ts +36 -0
- package/src/system/providers/NodeShellProvider.ts +184 -0
- package/src/system/providers/ShellProvider.ts +74 -0
- package/src/{file → system}/services/FileDetector.spec.ts +2 -2
- package/src/thread/index.ts +11 -2
- package/src/topic/core/index.ts +12 -5
- package/src/vite/index.ts +3 -2
- package/src/vite/tasks/buildClient.ts +2 -8
- package/src/vite/tasks/buildServer.ts +84 -21
- package/src/vite/tasks/copyAssets.ts +5 -4
- package/src/vite/tasks/generateSitemap.ts +64 -23
- package/src/vite/tasks/index.ts +0 -2
- package/src/vite/tasks/prerenderPages.ts +49 -24
- package/src/websocket/index.ts +12 -8
- package/dist/file/index.d.ts +0 -839
- package/dist/file/index.d.ts.map +0 -1
- package/dist/file/index.js.map +0 -1
- package/src/cli/assets/indexHtml.ts +0 -15
- package/src/cli/assets/mainServerTs.ts +0 -24
- package/src/cli/assets/webAppRouterTs.ts +0 -15
- package/src/cli/assets/webHelloComponentTsx.ts +0 -16
- package/src/cli/commands/format.ts +0 -23
- package/src/file/index.ts +0 -43
- package/src/vite/helpers/boot.ts +0 -117
- package/src/vite/plugins/viteAlephaDev.ts +0 -177
- package/src/vite/tasks/devServer.ts +0 -71
- package/src/vite/tasks/runAlepha.ts +0 -270
- /package/dist/orm/{chunk-DtkW-qnP.js → chunk-DH6iiROE.js} +0 -0
- /package/src/cli/{assets → templates}/apiIndexTs.ts +0 -0
- /package/src/cli/{assets → templates}/webIndexTs.ts +0 -0
- /package/src/{file → system}/errors/FileError.ts +0 -0
- /package/src/{file → system}/services/FileDetector.ts +0 -0
|
@@ -15,6 +15,7 @@ import { InvalidPermissionError } from "../errors/InvalidPermissionError.ts";
|
|
|
15
15
|
import { InvalidTokenError } from "../errors/InvalidTokenError.ts";
|
|
16
16
|
import { RealmNotFoundError } from "../errors/RealmNotFoundError.ts";
|
|
17
17
|
import { SecurityError } from "../errors/SecurityError.ts";
|
|
18
|
+
import type { IssuerResolver, UserInfo } from "../interfaces/IssuerResolver.ts";
|
|
18
19
|
import type { UserAccountToken } from "../interfaces/UserAccountToken.ts";
|
|
19
20
|
import type { Permission } from "../schemas/permissionSchema.ts";
|
|
20
21
|
import type { Role } from "../schemas/roleSchema.ts";
|
|
@@ -90,10 +91,46 @@ export class SecurityProvider {
|
|
|
90
91
|
typeof realm.secret === "function" ? realm.secret() : realm.secret;
|
|
91
92
|
this.jwt.setKeyLoader(realm.name, secret);
|
|
92
93
|
}
|
|
94
|
+
|
|
95
|
+
// Register default JWT resolver for realms without resolvers
|
|
96
|
+
if (!realm.resolvers || realm.resolvers.length === 0) {
|
|
97
|
+
this.registerResolver(
|
|
98
|
+
this.createDefaultJwtResolver(realm.name),
|
|
99
|
+
realm.name,
|
|
100
|
+
);
|
|
101
|
+
}
|
|
93
102
|
}
|
|
94
103
|
},
|
|
95
104
|
});
|
|
96
105
|
|
|
106
|
+
/**
|
|
107
|
+
* Creates a default JWT resolver for a realm.
|
|
108
|
+
*/
|
|
109
|
+
protected createDefaultJwtResolver(realmName: string): IssuerResolver {
|
|
110
|
+
return {
|
|
111
|
+
priority: 100,
|
|
112
|
+
onRequest: async (req) => {
|
|
113
|
+
const auth = req.headers.authorization;
|
|
114
|
+
if (!auth?.startsWith("Bearer ")) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const token = auth.slice(7);
|
|
119
|
+
|
|
120
|
+
// Check if it looks like a JWT (has dots)
|
|
121
|
+
if (!token.includes(".")) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Parse and validate JWT
|
|
126
|
+
const { result } = await this.jwt.parse(token, realmName);
|
|
127
|
+
|
|
128
|
+
// Extract user info from JWT payload
|
|
129
|
+
return this.createUserFromPayload(result.payload, realmName);
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
97
134
|
/**
|
|
98
135
|
* Adds a role to one or more realms.
|
|
99
136
|
*
|
|
@@ -305,6 +342,143 @@ export class SecurityProvider {
|
|
|
305
342
|
};
|
|
306
343
|
}
|
|
307
344
|
|
|
345
|
+
/**
|
|
346
|
+
* Generic user creation from any source (JWT, API key, etc.).
|
|
347
|
+
* Handles permission checking, ownership, default roles.
|
|
348
|
+
*/
|
|
349
|
+
public createUser(
|
|
350
|
+
userInfo: UserInfo,
|
|
351
|
+
options: {
|
|
352
|
+
realm?: string;
|
|
353
|
+
permission?: Permission | string;
|
|
354
|
+
} = {},
|
|
355
|
+
): UserAccountToken {
|
|
356
|
+
const realmRoles = this.getRoles(options.realm).filter((it) => it.default);
|
|
357
|
+
const roles = [...(userInfo.roles ?? [])];
|
|
358
|
+
|
|
359
|
+
// Add default roles
|
|
360
|
+
for (const role of realmRoles) {
|
|
361
|
+
if (!roles.includes(role.name)) {
|
|
362
|
+
roles.push(role.name);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
let ownership: string | boolean | undefined;
|
|
367
|
+
|
|
368
|
+
// Permission check
|
|
369
|
+
if (options.permission) {
|
|
370
|
+
const check = this.checkPermission(options.permission, ...roles);
|
|
371
|
+
if (!check.isAuthorized) {
|
|
372
|
+
throw new SecurityError(
|
|
373
|
+
`User is not allowed to access '${this.permissionToString(options.permission)}'`,
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
ownership = check.ownership;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
return {
|
|
380
|
+
...userInfo,
|
|
381
|
+
roles,
|
|
382
|
+
ownership,
|
|
383
|
+
realm: options.realm,
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Register a resolver to a realm.
|
|
389
|
+
* Resolvers are sorted by priority (lower = first).
|
|
390
|
+
*/
|
|
391
|
+
public registerResolver(resolver: IssuerResolver, realmName?: string): void {
|
|
392
|
+
const realm = this.getRealm(realmName);
|
|
393
|
+
if (!realm.resolvers) {
|
|
394
|
+
realm.resolvers = [];
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
realm.resolvers.push(resolver);
|
|
398
|
+
realm.resolvers.sort((a, b) => (a.priority ?? 100) - (b.priority ?? 100));
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Get a realm by name.
|
|
403
|
+
* Throws if realm not found.
|
|
404
|
+
*/
|
|
405
|
+
public getRealm(realmName?: string): Realm {
|
|
406
|
+
const realm = realmName
|
|
407
|
+
? this.realms.find((it) => it.name === realmName)
|
|
408
|
+
: this.realms[0];
|
|
409
|
+
|
|
410
|
+
if (!realm) {
|
|
411
|
+
throw new RealmNotFoundError(realmName ?? "default");
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
return realm;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Resolve user from request using registered resolvers.
|
|
419
|
+
* Returns undefined if no resolver could authenticate (no auth provided).
|
|
420
|
+
* Throws UnauthorizedError if auth was provided but invalid.
|
|
421
|
+
*
|
|
422
|
+
* Note: This method tries resolvers from ALL realms to find a match,
|
|
423
|
+
* regardless of the `realm` option. The `realm` option is only used for
|
|
424
|
+
* permission checking after the user is resolved.
|
|
425
|
+
*/
|
|
426
|
+
public async resolveUserFromServerRequest(
|
|
427
|
+
req: { url: URL | string; headers: { authorization?: string } },
|
|
428
|
+
options: {
|
|
429
|
+
realm?: string;
|
|
430
|
+
permission?: Permission | string;
|
|
431
|
+
} = {},
|
|
432
|
+
): Promise<UserAccountToken | undefined> {
|
|
433
|
+
// Collect all resolvers from all realms with their realm name
|
|
434
|
+
const allResolvers: Array<{
|
|
435
|
+
resolver: IssuerResolver;
|
|
436
|
+
realmName: string;
|
|
437
|
+
}> = [];
|
|
438
|
+
|
|
439
|
+
for (const realm of this.realms) {
|
|
440
|
+
for (const resolver of realm.resolvers ?? []) {
|
|
441
|
+
allResolvers.push({ resolver, realmName: realm.name });
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// Sort by priority
|
|
446
|
+
allResolvers.sort(
|
|
447
|
+
(a, b) => (a.resolver.priority ?? 100) - (b.resolver.priority ?? 100),
|
|
448
|
+
);
|
|
449
|
+
|
|
450
|
+
// Try resolvers in priority order
|
|
451
|
+
for (const { resolver, realmName } of allResolvers) {
|
|
452
|
+
let userInfo: UserInfo | null;
|
|
453
|
+
|
|
454
|
+
try {
|
|
455
|
+
userInfo = await resolver.onRequest(req as any);
|
|
456
|
+
} catch {
|
|
457
|
+
// Resolver failed (e.g., wrong key), try next
|
|
458
|
+
continue;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
if (userInfo) {
|
|
462
|
+
// User was resolved - now create user and check permissions
|
|
463
|
+
// (errors from createUser should propagate, not be caught)
|
|
464
|
+
const user = this.createUser(userInfo, {
|
|
465
|
+
realm: realmName,
|
|
466
|
+
permission: options.permission,
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
await this.alepha.events.emit("security:user:created", {
|
|
470
|
+
realm: realmName,
|
|
471
|
+
user,
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
return user;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// No resolver matched = no auth provided
|
|
479
|
+
return undefined;
|
|
480
|
+
}
|
|
481
|
+
|
|
308
482
|
/**
|
|
309
483
|
* Checks if the user has the specified permission.
|
|
310
484
|
*
|
|
@@ -783,6 +957,11 @@ export interface Realm {
|
|
|
783
957
|
* By default, SecurityProvider has his own implementation, but this method allow to override it.
|
|
784
958
|
*/
|
|
785
959
|
profile?: (raw: Record<string, any>) => UserAccount;
|
|
960
|
+
|
|
961
|
+
/**
|
|
962
|
+
* Custom resolvers for this realm (sorted by priority).
|
|
963
|
+
*/
|
|
964
|
+
resolvers?: IssuerResolver[];
|
|
786
965
|
}
|
|
787
966
|
|
|
788
967
|
export interface SecurityCheckResult {
|
|
@@ -15,9 +15,13 @@ export interface BasicAuthOptions {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export interface BasicAuthPrimitiveConfig extends BasicAuthOptions {
|
|
18
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* Name identifier for this basic auth (default: property key).
|
|
20
|
+
*/
|
|
19
21
|
name?: string;
|
|
20
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* Path patterns to match (supports wildcards like /devtools/*).
|
|
24
|
+
*/
|
|
21
25
|
paths?: string[];
|
|
22
26
|
}
|
|
23
27
|
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
type ServerRequest,
|
|
8
8
|
UnauthorizedError,
|
|
9
9
|
} from "alepha/server";
|
|
10
|
+
import { InvalidTokenError } from "../errors/InvalidTokenError.ts";
|
|
10
11
|
import type { UserAccountToken } from "../interfaces/UserAccountToken.ts";
|
|
11
12
|
import type { Permission } from "../schemas/permissionSchema.ts";
|
|
12
13
|
import { userAccountInfoSchema } from "../schemas/userAccountInfoSchema.ts";
|
|
@@ -23,6 +24,8 @@ export class ServerSecurityProvider {
|
|
|
23
24
|
protected readonly jwtProvider = $inject(JwtProvider);
|
|
24
25
|
protected readonly alepha = $inject(Alepha);
|
|
25
26
|
|
|
27
|
+
protected readonly resolvers: Array<ServerSecurityUserResolver> = [];
|
|
28
|
+
|
|
26
29
|
protected readonly onConfigure = $hook({
|
|
27
30
|
on: "configure",
|
|
28
31
|
handler: async () => {
|
|
@@ -119,20 +122,35 @@ export class ServerSecurityProvider {
|
|
|
119
122
|
.getPermissions()
|
|
120
123
|
.find((it) => it.path === route.path && it.method === route.method);
|
|
121
124
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
"Skipping security check for route - no authorization header and not secure",
|
|
125
|
-
);
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
125
|
+
const realm =
|
|
126
|
+
typeof route.secure === "object" ? route.secure.realm : undefined;
|
|
128
127
|
|
|
129
128
|
try {
|
|
130
|
-
//
|
|
131
|
-
request.user = await this.securityProvider.
|
|
132
|
-
request
|
|
133
|
-
{ permission },
|
|
129
|
+
// Try to resolve user (JWT, API key, etc.)
|
|
130
|
+
request.user = await this.securityProvider.resolveUserFromServerRequest(
|
|
131
|
+
request,
|
|
132
|
+
{ permission, realm },
|
|
134
133
|
);
|
|
135
134
|
|
|
135
|
+
// No user resolved?
|
|
136
|
+
if (!request.user) {
|
|
137
|
+
// Route requires auth → throw
|
|
138
|
+
if (route.secure || permission) {
|
|
139
|
+
// Provide a more specific error message when no auth header was provided
|
|
140
|
+
if (!request.headers.authorization) {
|
|
141
|
+
throw new InvalidTokenError(
|
|
142
|
+
"Invalid authorization header, maybe token is missing ?",
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
throw new UnauthorizedError("Authentication required");
|
|
146
|
+
}
|
|
147
|
+
// Route is public → skip
|
|
148
|
+
this.log.trace(
|
|
149
|
+
"Skipping security check for route - no auth provided and not required",
|
|
150
|
+
);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
136
154
|
if (typeof route.secure === "object") {
|
|
137
155
|
this.check(request.user, route.secure);
|
|
138
156
|
}
|
|
@@ -143,7 +161,7 @@ export class ServerSecurityProvider {
|
|
|
143
161
|
this.alepha.codec.decode(userAccountInfoSchema, request.user),
|
|
144
162
|
);
|
|
145
163
|
|
|
146
|
-
this.log.trace("User set from request
|
|
164
|
+
this.log.trace("User set from request", {
|
|
147
165
|
user: request.user,
|
|
148
166
|
permission,
|
|
149
167
|
});
|
|
@@ -209,19 +227,10 @@ export class ServerSecurityProvider {
|
|
|
209
227
|
}
|
|
210
228
|
|
|
211
229
|
if (!user) {
|
|
212
|
-
// in testing mode, we create a test user
|
|
213
|
-
if (this.alepha.isTest() && !("user" in options)) {
|
|
214
|
-
return this.createTestUser();
|
|
215
|
-
}
|
|
216
|
-
|
|
217
230
|
throw new UnauthorizedError("User is required for calling this action");
|
|
218
231
|
}
|
|
219
232
|
|
|
220
|
-
const roles =
|
|
221
|
-
user.roles ??
|
|
222
|
-
(this.alepha.isTest()
|
|
223
|
-
? this.securityProvider.getRoles().map((role) => role.name)
|
|
224
|
-
: []);
|
|
233
|
+
const roles = user.roles ?? [];
|
|
225
234
|
let ownership: boolean | string | undefined;
|
|
226
235
|
|
|
227
236
|
if (permission) {
|
|
@@ -264,7 +273,8 @@ export class ServerSecurityProvider {
|
|
|
264
273
|
}
|
|
265
274
|
|
|
266
275
|
// skip helper if user is explicitly set to undefined
|
|
267
|
-
if ("user" in options && options.user === undefined) {
|
|
276
|
+
//if ("user" in options && options.user === undefined) {
|
|
277
|
+
if (!options.user) {
|
|
268
278
|
return;
|
|
269
279
|
}
|
|
270
280
|
|
|
@@ -295,3 +305,7 @@ export type ServerRouteSecure = {
|
|
|
295
305
|
realm?: string;
|
|
296
306
|
basic?: BasicAuthOptions;
|
|
297
307
|
};
|
|
308
|
+
|
|
309
|
+
export type ServerSecurityUserResolver = (
|
|
310
|
+
request: ServerRequest,
|
|
311
|
+
) => Promise<UserAccountToken | undefined>;
|
package/src/server/auth/index.ts
CHANGED
|
@@ -29,16 +29,21 @@ declare module "alepha" {
|
|
|
29
29
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
32
|
+
* | type | quality | stability |
|
|
33
|
+
* |------|---------|-----------|
|
|
34
|
+
* | backend | rare | stable |
|
|
34
35
|
*
|
|
35
|
-
*
|
|
36
|
-
* You can also delegate authentication to your own OIDC/OAuth2, for example using Keycloak or Auth0.
|
|
36
|
+
* OAuth2/OIDC authentication with social login providers.
|
|
37
37
|
*
|
|
38
|
-
*
|
|
38
|
+
* **Features:**
|
|
39
|
+
* - OAuth authentication provider
|
|
40
|
+
* - Username/password authentication
|
|
41
|
+
* - Google OAuth integration
|
|
42
|
+
* - GitHub OAuth integration
|
|
43
|
+
* - Apple OAuth integration
|
|
44
|
+
* - Cookie-based, SSR-friendly authentication
|
|
45
|
+
* - Token management and refresh
|
|
39
46
|
*
|
|
40
|
-
* @see {@link $auth}
|
|
41
|
-
* @see {@link ServerAuthProvider}
|
|
42
47
|
* @module alepha.server.auth
|
|
43
48
|
*/
|
|
44
49
|
export const AlephaServerAuth = $module({
|
|
@@ -9,31 +9,16 @@ export * from "./providers/ServerCacheProvider.ts";
|
|
|
9
9
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* | type | quality | stability |
|
|
13
|
+
* |------|---------|-----------|
|
|
14
|
+
* | backend | standard | stable |
|
|
15
15
|
*
|
|
16
|
-
*
|
|
17
|
-
* ```ts
|
|
18
|
-
* import { Alepha } from "alepha";
|
|
19
|
-
* import { $action } from "alepha/server";
|
|
20
|
-
* import { AlephaServerCache } from "alepha/server/cache";
|
|
16
|
+
* ETag-based response caching.
|
|
21
17
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* handler: () => "Hello, World!",
|
|
26
|
-
* });
|
|
27
|
-
* }
|
|
18
|
+
* **Features:**
|
|
19
|
+
* - ETag generation and validation
|
|
20
|
+
* - Conditional request handling
|
|
28
21
|
*
|
|
29
|
-
* const alepha = Alepha.create()
|
|
30
|
-
* .with(AlephaServerCache)
|
|
31
|
-
* .with(ApiServer);
|
|
32
|
-
*
|
|
33
|
-
* run(alepha);
|
|
34
|
-
* ```
|
|
35
|
-
*
|
|
36
|
-
* @see {@link ServerCacheProvider}
|
|
37
22
|
* @module alepha.server.cache
|
|
38
23
|
*/
|
|
39
24
|
export const AlephaServerCache = $module({
|
|
@@ -9,9 +9,17 @@ export * from "./providers/ServerCompressProvider.ts";
|
|
|
9
9
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
12
|
+
* | type | quality | stability |
|
|
13
|
+
* |------|---------|-----------|
|
|
14
|
+
* | backend | standard | stable |
|
|
13
15
|
*
|
|
14
|
-
*
|
|
16
|
+
* Response compression.
|
|
17
|
+
*
|
|
18
|
+
* **Features:**
|
|
19
|
+
* - Gzip compression
|
|
20
|
+
* - Brotli compression
|
|
21
|
+
*
|
|
22
|
+
* @module alepha.server.compress
|
|
15
23
|
*/
|
|
16
24
|
export const AlephaServerCompress = $module({
|
|
17
25
|
name: "alepha.server.compress",
|
|
@@ -18,13 +18,15 @@ declare module "alepha/server" {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
21
|
+
* | type | quality | stability |
|
|
22
|
+
* |------|---------|-----------|
|
|
23
|
+
* | backend | standard | stable |
|
|
22
24
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
25
|
+
* Server and browser-safe cookie handling.
|
|
26
|
+
*
|
|
27
|
+
* **Features:**
|
|
28
|
+
* - Cookie management on server and browser
|
|
26
29
|
*
|
|
27
|
-
* @see {@link $cookie}
|
|
28
30
|
* @module alepha.server.cookies
|
|
29
31
|
*/
|
|
30
32
|
export const AlephaServerCookies = $module({
|
|
@@ -23,37 +23,59 @@ export const $cookie = <T extends TSchema>(
|
|
|
23
23
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
24
24
|
|
|
25
25
|
export interface CookiePrimitiveOptions<T extends TSchema> {
|
|
26
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* The schema for the cookie's value, used for validation and type safety.
|
|
28
|
+
*/
|
|
27
29
|
schema: T;
|
|
28
30
|
|
|
29
|
-
/**
|
|
31
|
+
/**
|
|
32
|
+
* The name of the cookie.
|
|
33
|
+
*/
|
|
30
34
|
name?: string;
|
|
31
35
|
|
|
32
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* The cookie's path. Defaults to "/".
|
|
38
|
+
*/
|
|
33
39
|
path?: string;
|
|
34
40
|
|
|
35
|
-
/**
|
|
41
|
+
/**
|
|
42
|
+
* Time-to-live for the cookie. Maps to `Max-Age`.
|
|
43
|
+
*/
|
|
36
44
|
ttl?: DurationLike;
|
|
37
45
|
|
|
38
|
-
/**
|
|
46
|
+
/**
|
|
47
|
+
* If true, the cookie is only sent over HTTPS. Defaults to true in production.
|
|
48
|
+
*/
|
|
39
49
|
secure?: boolean;
|
|
40
50
|
|
|
41
|
-
/**
|
|
51
|
+
/**
|
|
52
|
+
* If true, the cookie cannot be accessed by client-side scripts.
|
|
53
|
+
*/
|
|
42
54
|
httpOnly?: boolean;
|
|
43
55
|
|
|
44
|
-
/**
|
|
56
|
+
/**
|
|
57
|
+
* SameSite policy for the cookie. Defaults to "lax".
|
|
58
|
+
*/
|
|
45
59
|
sameSite?: "strict" | "lax" | "none";
|
|
46
60
|
|
|
47
|
-
/**
|
|
61
|
+
/**
|
|
62
|
+
* The domain for the cookie.
|
|
63
|
+
*/
|
|
48
64
|
domain?: string;
|
|
49
65
|
|
|
50
|
-
/**
|
|
66
|
+
/**
|
|
67
|
+
* If true, the cookie value will be compressed using zlib.
|
|
68
|
+
*/
|
|
51
69
|
compress?: boolean;
|
|
52
70
|
|
|
53
|
-
/**
|
|
71
|
+
/**
|
|
72
|
+
* If true, the cookie value will be encrypted. Requires `COOKIE_SECRET` env var.
|
|
73
|
+
*/
|
|
54
74
|
encrypt?: boolean;
|
|
55
75
|
|
|
56
|
-
/**
|
|
76
|
+
/**
|
|
77
|
+
* If true, the cookie will be signed to prevent tampering. Requires `COOKIE_SECRET` env var.
|
|
78
|
+
*/
|
|
57
79
|
sign?: boolean;
|
|
58
80
|
}
|
|
59
81
|
|
package/src/server/core/index.ts
CHANGED
|
@@ -114,14 +114,24 @@ export * from "./services/UserAgentParser.ts";
|
|
|
114
114
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
115
115
|
|
|
116
116
|
/**
|
|
117
|
-
*
|
|
117
|
+
* | type | quality | stability |
|
|
118
|
+
* |------|---------|-----------|
|
|
119
|
+
* | backend | epic | stable |
|
|
118
120
|
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
121
|
+
* Convention-driven HTTP server with automatic validation and type inference.
|
|
122
|
+
*
|
|
123
|
+
* **Features:**
|
|
124
|
+
* - Type-safe API endpoints with schema validation
|
|
125
|
+
* - Lower-level HTTP route definitions
|
|
126
|
+
* - Automatic request/response validation via TypeBox
|
|
127
|
+
* - Convention-based URL generation (`/api/{ActionName}`)
|
|
128
|
+
* - Direct invocation (`run()`) or HTTP (`fetch()`)
|
|
129
|
+
* - Built-in authentication integration
|
|
130
|
+
* - Multipart file upload handling
|
|
131
|
+
* - Content-type auto-negotiation (JSON, form-data, text)
|
|
132
|
+
* - HTTP methods: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS
|
|
133
|
+
* - Error handling: BadRequestError, ValidationError, ForbiddenError, UnauthorizedError, ConflictError, NotFoundError
|
|
122
134
|
*
|
|
123
|
-
* @see {@link $route}
|
|
124
|
-
* @see {@link $action}
|
|
125
135
|
* @module alepha.server
|
|
126
136
|
*/
|
|
127
137
|
export const AlephaServer = $module({
|
|
@@ -141,7 +151,7 @@ export const AlephaServer = $module({
|
|
|
141
151
|
ServerRouterProvider,
|
|
142
152
|
],
|
|
143
153
|
register: (alepha: Alepha) => {
|
|
144
|
-
if (!alepha.isServerless()
|
|
154
|
+
if (!alepha.isServerless()) {
|
|
145
155
|
if (alepha.isBun()) {
|
|
146
156
|
alepha.with({
|
|
147
157
|
optional: true,
|
|
@@ -83,7 +83,7 @@ export interface ServerRequest<
|
|
|
83
83
|
|
|
84
84
|
/**
|
|
85
85
|
* Client IP address.
|
|
86
|
-
*
|
|
86
|
+
* Uses `X-Forwarded-For` header when `TRUST_PROXY=true`.
|
|
87
87
|
*/
|
|
88
88
|
ip?: string;
|
|
89
89
|
|
|
@@ -100,6 +100,42 @@ export interface ServerRequest<
|
|
|
100
100
|
*/
|
|
101
101
|
userAgent: UserAgentInfo;
|
|
102
102
|
|
|
103
|
+
/**
|
|
104
|
+
* Geolocation information derived from proxy headers.
|
|
105
|
+
* Available when behind Cloudflare, Vercel, or similar CDNs.
|
|
106
|
+
*/
|
|
107
|
+
geo: RequestGeo;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Whether the request appears to be from a bot/crawler.
|
|
111
|
+
* Based on user-agent analysis.
|
|
112
|
+
*/
|
|
113
|
+
isBot: boolean;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Whether the request is from a mobile device.
|
|
117
|
+
* Based on user-agent analysis.
|
|
118
|
+
*/
|
|
119
|
+
isMobile: boolean;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Request protocol (http or https).
|
|
123
|
+
* Uses `X-Forwarded-Proto` header when behind a proxy.
|
|
124
|
+
*/
|
|
125
|
+
protocol: "http" | "https";
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Preferred language from `Accept-Language` header.
|
|
129
|
+
* Returns the first/most preferred language code (e.g., "en", "fr", "en-US").
|
|
130
|
+
*/
|
|
131
|
+
language?: string;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Parsed referer information.
|
|
135
|
+
* Undefined if no Referer header or invalid URL.
|
|
136
|
+
*/
|
|
137
|
+
referer?: RequestReferer;
|
|
138
|
+
|
|
103
139
|
/**
|
|
104
140
|
* Arbitrary metadata attached to the request. Can be used by middlewares to store information.
|
|
105
141
|
*/
|
|
@@ -208,3 +244,49 @@ export interface WebRequestEvent {
|
|
|
208
244
|
req: Request;
|
|
209
245
|
res?: Response;
|
|
210
246
|
}
|
|
247
|
+
|
|
248
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Geolocation information from proxy headers (Cloudflare, Vercel, etc.)
|
|
252
|
+
*/
|
|
253
|
+
export interface RequestGeo {
|
|
254
|
+
/**
|
|
255
|
+
* ISO 3166-1 alpha-2 country code (e.g., "US", "FR", "JP").
|
|
256
|
+
*/
|
|
257
|
+
country?: string;
|
|
258
|
+
/**
|
|
259
|
+
* City name (e.g., "San Francisco", "Paris").
|
|
260
|
+
*/
|
|
261
|
+
city?: string;
|
|
262
|
+
/**
|
|
263
|
+
* Region/state (e.g., "California", "Île-de-France").
|
|
264
|
+
*/
|
|
265
|
+
region?: string;
|
|
266
|
+
/**
|
|
267
|
+
* Latitude (if available).
|
|
268
|
+
*/
|
|
269
|
+
latitude?: string;
|
|
270
|
+
/**
|
|
271
|
+
* Longitude (if available).
|
|
272
|
+
*/
|
|
273
|
+
longitude?: string;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Parsed referer information.
|
|
278
|
+
*/
|
|
279
|
+
export interface RequestReferer {
|
|
280
|
+
/**
|
|
281
|
+
* Full referer URL.
|
|
282
|
+
*/
|
|
283
|
+
url: string;
|
|
284
|
+
/**
|
|
285
|
+
* Hostname of the referer (e.g., "google.com").
|
|
286
|
+
*/
|
|
287
|
+
hostname: string;
|
|
288
|
+
/**
|
|
289
|
+
* Path of the referer URL.
|
|
290
|
+
*/
|
|
291
|
+
pathname: string;
|
|
292
|
+
}
|