alepha 0.14.2 → 0.14.4
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 +1 -1
- package/dist/api/audits/index.browser.js +5 -5
- package/dist/api/audits/index.browser.js.map +1 -1
- package/dist/api/audits/index.d.ts +706 -785
- package/dist/api/audits/index.d.ts.map +1 -1
- package/dist/api/audits/index.js +13 -13
- package/dist/api/audits/index.js.map +1 -1
- package/dist/api/files/index.browser.js +5 -5
- package/dist/api/files/index.browser.js.map +1 -1
- package/dist/api/files/index.d.ts +58 -137
- package/dist/api/files/index.d.ts.map +1 -1
- package/dist/api/files/index.js +71 -71
- package/dist/api/files/index.js.map +1 -1
- package/dist/api/jobs/index.browser.js +5 -5
- package/dist/api/jobs/index.browser.js.map +1 -1
- package/dist/api/jobs/index.d.ts +29 -108
- package/dist/api/jobs/index.d.ts.map +1 -1
- package/dist/api/jobs/index.js +10 -10
- package/dist/api/jobs/index.js.map +1 -1
- package/dist/api/notifications/index.browser.js +10 -10
- package/dist/api/notifications/index.browser.js.map +1 -1
- package/dist/api/notifications/index.d.ts +504 -171
- package/dist/api/notifications/index.d.ts.map +1 -1
- package/dist/api/notifications/index.js +12 -12
- package/dist/api/notifications/index.js.map +1 -1
- package/dist/api/parameters/index.browser.js +163 -10
- package/dist/api/parameters/index.browser.js.map +1 -1
- package/dist/api/parameters/index.d.ts +277 -351
- package/dist/api/parameters/index.d.ts.map +1 -1
- package/dist/api/parameters/index.js +196 -91
- package/dist/api/parameters/index.js.map +1 -1
- package/dist/api/users/index.browser.js +19 -19
- package/dist/api/users/index.browser.js.map +1 -1
- package/dist/api/users/index.d.ts +787 -852
- package/dist/api/users/index.d.ts.map +1 -1
- package/dist/api/users/index.js +827 -596
- package/dist/api/users/index.js.map +1 -1
- package/dist/api/verifications/index.browser.js +6 -6
- package/dist/api/verifications/index.browser.js.map +1 -1
- package/dist/api/verifications/index.d.ts +128 -128
- package/dist/api/verifications/index.d.ts.map +1 -1
- package/dist/api/verifications/index.js +6 -6
- package/dist/api/verifications/index.js.map +1 -1
- package/dist/bin/index.d.ts +1 -2
- package/dist/bin/index.js +0 -1
- package/dist/bin/index.js.map +1 -1
- package/dist/cli/index.d.ts +252 -131
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +595 -395
- package/dist/cli/index.js.map +1 -1
- package/dist/command/index.d.ts +46 -11
- package/dist/command/index.d.ts.map +1 -1
- package/dist/command/index.js +99 -19
- package/dist/command/index.js.map +1 -1
- package/dist/core/index.browser.js +40 -22
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +45 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +40 -22
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js +40 -22
- package/dist/core/index.native.js.map +1 -1
- package/dist/fake/index.js +195 -168
- package/dist/fake/index.js.map +1 -1
- package/dist/file/index.d.ts +8 -0
- package/dist/file/index.d.ts.map +1 -1
- package/dist/file/index.js +3 -0
- package/dist/file/index.js.map +1 -1
- package/dist/logger/index.d.ts +1 -1
- package/dist/logger/index.d.ts.map +1 -1
- package/dist/logger/index.js +12 -2
- package/dist/logger/index.js.map +1 -1
- package/dist/mcp/index.js +1 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/orm/index.d.ts +59 -195
- package/dist/orm/index.d.ts.map +1 -1
- package/dist/orm/index.js +201 -430
- package/dist/orm/index.js.map +1 -1
- package/dist/security/index.d.ts +1 -1
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +1 -1
- package/dist/security/index.js.map +1 -1
- package/dist/server/auth/index.d.ts +171 -155
- package/dist/server/auth/index.d.ts.map +1 -1
- package/dist/server/auth/index.js +0 -1
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/cache/index.d.ts +12 -0
- package/dist/server/cache/index.d.ts.map +1 -1
- package/dist/server/cache/index.js +55 -2
- package/dist/server/cache/index.js.map +1 -1
- package/dist/server/compress/index.d.ts +6 -0
- package/dist/server/compress/index.d.ts.map +1 -1
- package/dist/server/compress/index.js +38 -1
- package/dist/server/compress/index.js.map +1 -1
- package/dist/server/core/index.browser.js +2 -2
- package/dist/server/core/index.browser.js.map +1 -1
- package/dist/server/core/index.d.ts +10 -10
- package/dist/server/core/index.d.ts.map +1 -1
- package/dist/server/core/index.js +7 -4
- package/dist/server/core/index.js.map +1 -1
- package/dist/server/links/index.browser.js +22 -6
- package/dist/server/links/index.browser.js.map +1 -1
- package/dist/server/links/index.d.ts +46 -44
- package/dist/server/links/index.d.ts.map +1 -1
- package/dist/server/links/index.js +24 -41
- package/dist/server/links/index.js.map +1 -1
- package/dist/server/static/index.d.ts.map +1 -1
- package/dist/server/static/index.js +4 -0
- package/dist/server/static/index.js.map +1 -1
- package/dist/server/swagger/index.d.ts +2 -1
- package/dist/server/swagger/index.d.ts.map +1 -1
- package/dist/server/swagger/index.js +9 -5
- package/dist/server/swagger/index.js.map +1 -1
- package/dist/vite/index.d.ts +101 -106
- package/dist/vite/index.d.ts.map +1 -1
- package/dist/vite/index.js +574 -503
- package/dist/vite/index.js.map +1 -1
- package/dist/websocket/index.d.ts +7 -7
- package/package.json +7 -7
- package/src/api/audits/controllers/{AuditController.ts → AdminAuditController.ts} +5 -6
- package/src/api/audits/entities/audits.ts +5 -5
- package/src/api/audits/index.browser.ts +1 -1
- package/src/api/audits/index.ts +3 -3
- package/src/api/audits/primitives/$audit.spec.ts +276 -0
- package/src/api/audits/services/AuditService.spec.ts +495 -0
- package/src/api/files/__tests__/$bucket.spec.ts +91 -0
- package/src/api/files/controllers/AdminFileStatsController.spec.ts +166 -0
- package/src/api/files/controllers/{StorageStatsController.ts → AdminFileStatsController.ts} +2 -2
- package/src/api/files/controllers/FileController.spec.ts +558 -0
- package/src/api/files/controllers/FileController.ts +4 -5
- package/src/api/files/entities/files.ts +5 -5
- package/src/api/files/index.browser.ts +1 -1
- package/src/api/files/index.ts +4 -4
- package/src/api/files/jobs/FileJobs.spec.ts +52 -0
- package/src/api/files/services/FileService.spec.ts +109 -0
- package/src/api/jobs/__tests__/JobController.spec.ts +343 -0
- package/src/api/jobs/controllers/{JobController.ts → AdminJobController.ts} +2 -2
- package/src/api/jobs/entities/jobExecutions.ts +5 -5
- package/src/api/jobs/index.ts +3 -3
- package/src/api/jobs/primitives/$job.spec.ts +476 -0
- package/src/api/notifications/controllers/{NotificationController.ts → AdminNotificationController.ts} +4 -5
- package/src/api/notifications/entities/notifications.ts +5 -5
- package/src/api/notifications/index.browser.ts +1 -1
- package/src/api/notifications/index.ts +4 -4
- package/src/api/parameters/controllers/{ConfigController.ts → AdminConfigController.ts} +46 -107
- package/src/api/parameters/entities/parameters.ts +7 -17
- package/src/api/parameters/index.ts +3 -3
- package/src/api/parameters/primitives/$config.spec.ts +356 -0
- package/src/api/parameters/schemas/activateConfigBodySchema.ts +12 -0
- package/src/api/parameters/schemas/checkScheduledResponseSchema.ts +8 -0
- package/src/api/parameters/schemas/configCurrentResponseSchema.ts +13 -0
- package/src/api/parameters/schemas/configHistoryResponseSchema.ts +9 -0
- package/src/api/parameters/schemas/configNameParamSchema.ts +10 -0
- package/src/api/parameters/schemas/configNamesResponseSchema.ts +8 -0
- package/src/api/parameters/schemas/configTreeNodeSchema.ts +13 -0
- package/src/api/parameters/schemas/configVersionParamSchema.ts +9 -0
- package/src/api/parameters/schemas/configVersionResponseSchema.ts +9 -0
- package/src/api/parameters/schemas/configsByStatusResponseSchema.ts +9 -0
- package/src/api/parameters/schemas/createConfigVersionBodySchema.ts +24 -0
- package/src/api/parameters/schemas/index.ts +15 -0
- package/src/api/parameters/schemas/parameterResponseSchema.ts +26 -0
- package/src/api/parameters/schemas/parameterStatusSchema.ts +13 -0
- package/src/api/parameters/schemas/rollbackConfigBodySchema.ts +15 -0
- package/src/api/parameters/schemas/statusParamSchema.ts +9 -0
- package/src/api/users/__tests__/EmailVerification.spec.ts +369 -0
- package/src/api/users/__tests__/PasswordReset.spec.ts +550 -0
- package/src/api/users/controllers/AdminIdentityController.spec.ts +365 -0
- package/src/api/users/controllers/{IdentityController.ts → AdminIdentityController.ts} +3 -4
- package/src/api/users/controllers/AdminSessionController.spec.ts +274 -0
- package/src/api/users/controllers/{SessionController.ts → AdminSessionController.ts} +3 -4
- package/src/api/users/controllers/AdminUserController.spec.ts +372 -0
- package/src/api/users/controllers/AdminUserController.ts +116 -0
- package/src/api/users/controllers/UserController.ts +4 -107
- package/src/api/users/controllers/UserRealmController.ts +3 -0
- package/src/api/users/entities/identities.ts +6 -6
- package/src/api/users/entities/sessions.ts +6 -6
- package/src/api/users/entities/users.ts +9 -9
- package/src/api/users/index.ts +9 -6
- package/src/api/users/primitives/$userRealm.ts +13 -8
- package/src/api/users/services/CredentialService.spec.ts +509 -0
- package/src/api/users/services/CredentialService.ts +46 -0
- package/src/api/users/services/IdentityService.ts +15 -0
- package/src/api/users/services/RegistrationService.spec.ts +630 -0
- package/src/api/users/services/RegistrationService.ts +18 -0
- package/src/api/users/services/SessionService.spec.ts +301 -0
- package/src/api/users/services/SessionService.ts +110 -1
- package/src/api/users/services/UserService.ts +67 -2
- package/src/api/verifications/__tests__/CodeVerification.spec.ts +318 -0
- package/src/api/verifications/__tests__/LinkVerification.spec.ts +279 -0
- package/src/api/verifications/entities/verifications.ts +6 -6
- package/src/api/verifications/jobs/VerificationJobs.spec.ts +50 -0
- package/src/batch/__tests__/startup-buffering.spec.ts +458 -0
- package/src/batch/primitives/$batch.spec.ts +766 -0
- package/src/batch/providers/BatchProvider.spec.ts +786 -0
- package/src/bin/index.ts +0 -1
- package/src/bucket/__tests__/shared.ts +194 -0
- package/src/bucket/primitives/$bucket.spec.ts +104 -0
- package/src/bucket/providers/FileStorageProvider.spec.ts +13 -0
- package/src/bucket/providers/LocalFileStorageProvider.spec.ts +77 -0
- package/src/bucket/providers/MemoryFileStorageProvider.spec.ts +82 -0
- package/src/cache/core/__tests__/shared.ts +377 -0
- package/src/cache/core/primitives/$cache.spec.ts +111 -0
- package/src/cache/redis/__tests__/cache-redis.spec.ts +70 -0
- package/src/cli/apps/AlephaCli.ts +25 -6
- package/src/cli/atoms/buildOptions.ts +88 -0
- package/src/cli/commands/build.ts +32 -69
- package/src/cli/commands/db.ts +0 -4
- package/src/cli/commands/dev.ts +34 -10
- package/src/cli/commands/gen/changelog.spec.ts +315 -0
- package/src/cli/commands/{changelog.ts → gen/changelog.ts} +9 -9
- package/src/cli/commands/gen/env.ts +53 -0
- package/src/cli/commands/gen/openapi.ts +71 -0
- package/src/cli/commands/gen/resource.ts +15 -0
- package/src/cli/commands/gen.ts +24 -0
- package/src/cli/commands/init.ts +2 -1
- package/src/cli/commands/root.ts +12 -3
- package/src/cli/commands/test.ts +0 -1
- package/src/cli/commands/typecheck.ts +5 -0
- package/src/cli/commands/verify.ts +1 -1
- package/src/cli/defineConfig.ts +49 -7
- package/src/cli/index.ts +2 -2
- package/src/cli/services/AlephaCliUtils.ts +105 -55
- package/src/cli/services/GitMessageParser.ts +1 -1
- package/src/command/helpers/Asker.spec.ts +127 -0
- package/src/command/helpers/Runner.spec.ts +126 -0
- package/src/command/helpers/Runner.ts +1 -1
- package/src/command/primitives/$command.spec.ts +1588 -0
- package/src/command/primitives/$command.ts +0 -6
- package/src/command/providers/CliProvider.ts +75 -27
- package/src/core/Alepha.ts +87 -0
- package/src/core/__tests__/Alepha-emit.spec.ts +22 -0
- package/src/core/__tests__/Alepha-graph.spec.ts +93 -0
- package/src/core/__tests__/Alepha-has.spec.ts +41 -0
- package/src/core/__tests__/Alepha-inject.spec.ts +93 -0
- package/src/core/__tests__/Alepha-register.spec.ts +81 -0
- package/src/core/__tests__/Alepha-start.spec.ts +176 -0
- package/src/core/__tests__/Alepha-with.spec.ts +14 -0
- package/src/core/__tests__/TypeBox-usecases.spec.ts +35 -0
- package/src/core/__tests__/TypeBoxLocale.spec.ts +15 -0
- package/src/core/__tests__/descriptor.spec.ts +34 -0
- package/src/core/__tests__/fixtures/A.ts +5 -0
- package/src/core/__tests__/pagination.spec.ts +77 -0
- package/src/core/helpers/jsonSchemaToTypeBox.ts +2 -2
- package/src/core/primitives/$atom.spec.ts +43 -0
- package/src/core/primitives/$hook.spec.ts +130 -0
- package/src/core/primitives/$inject.spec.ts +175 -0
- package/src/core/primitives/$module.spec.ts +115 -0
- package/src/core/providers/CodecManager.spec.ts +740 -0
- package/src/core/providers/EventManager.spec.ts +762 -0
- package/src/core/providers/EventManager.ts +4 -0
- package/src/core/providers/StateManager.spec.ts +365 -0
- package/src/core/providers/TypeProvider.spec.ts +1607 -0
- package/src/core/providers/TypeProvider.ts +20 -26
- package/src/datetime/primitives/$interval.spec.ts +103 -0
- package/src/datetime/providers/DateTimeProvider.spec.ts +86 -0
- package/src/email/primitives/$email.spec.ts +175 -0
- package/src/email/providers/LocalEmailProvider.spec.ts +341 -0
- package/src/fake/__tests__/keyName.example.ts +40 -0
- package/src/fake/__tests__/keyName.spec.ts +152 -0
- package/src/fake/__tests__/module.example.ts +32 -0
- package/src/fake/providers/FakeProvider.spec.ts +438 -0
- package/src/file/providers/FileSystemProvider.ts +8 -0
- package/src/file/providers/NodeFileSystemProvider.spec.ts +418 -0
- package/src/file/providers/NodeFileSystemProvider.ts +5 -0
- package/src/file/services/FileDetector.spec.ts +591 -0
- package/src/lock/core/__tests__/shared.ts +190 -0
- package/src/lock/core/providers/MemoryLockProvider.spec.ts +25 -0
- package/src/lock/redis/providers/RedisLockProvider.spec.ts +25 -0
- package/src/logger/__tests__/SimpleFormatterProvider.spec.ts +109 -0
- package/src/logger/index.ts +15 -3
- package/src/logger/primitives/$logger.spec.ts +108 -0
- package/src/logger/services/Logger.spec.ts +295 -0
- package/src/mcp/__tests__/errors.spec.ts +175 -0
- package/src/mcp/__tests__/integration.spec.ts +450 -0
- package/src/mcp/helpers/jsonrpc.spec.ts +380 -0
- package/src/mcp/primitives/$prompt.spec.ts +468 -0
- package/src/mcp/primitives/$resource.spec.ts +390 -0
- package/src/mcp/primitives/$tool.spec.ts +406 -0
- package/src/mcp/providers/McpServerProvider.spec.ts +797 -0
- package/src/mcp/transports/StdioMcpTransport.ts +1 -1
- package/src/orm/__tests__/$repository-crud.spec.ts +276 -0
- package/src/orm/__tests__/$repository-hooks.spec.ts +325 -0
- package/src/orm/__tests__/$repository-orderBy.spec.ts +128 -0
- package/src/orm/__tests__/$repository-pagination-sort.spec.ts +149 -0
- package/src/orm/__tests__/$repository-save.spec.ts +37 -0
- package/src/orm/__tests__/ModelBuilder-integration.spec.ts +490 -0
- package/src/orm/__tests__/ModelBuilder-types.spec.ts +186 -0
- package/src/orm/__tests__/PostgresProvider.spec.ts +46 -0
- package/src/orm/__tests__/delete-returning.spec.ts +256 -0
- package/src/orm/__tests__/deletedAt.spec.ts +80 -0
- package/src/orm/__tests__/enums.spec.ts +315 -0
- package/src/orm/__tests__/execute.spec.ts +72 -0
- package/src/orm/__tests__/fixtures/bigEntitySchema.ts +65 -0
- package/src/orm/__tests__/fixtures/userEntitySchema.ts +27 -0
- package/src/orm/__tests__/joins.spec.ts +1114 -0
- package/src/orm/__tests__/page.spec.ts +287 -0
- package/src/orm/__tests__/primaryKey.spec.ts +87 -0
- package/src/orm/__tests__/query-date-encoding.spec.ts +402 -0
- package/src/orm/__tests__/ref-auto-onDelete.spec.ts +156 -0
- package/src/orm/__tests__/references.spec.ts +102 -0
- package/src/orm/__tests__/security.spec.ts +710 -0
- package/src/orm/__tests__/sqlite.spec.ts +111 -0
- package/src/orm/__tests__/string-operators.spec.ts +429 -0
- package/src/orm/__tests__/timestamps.spec.ts +388 -0
- package/src/orm/__tests__/validation.spec.ts +183 -0
- package/src/orm/__tests__/version.spec.ts +64 -0
- package/src/orm/helpers/parseQueryString.spec.ts +196 -0
- package/src/orm/index.ts +2 -8
- package/src/orm/primitives/$repository.spec.ts +137 -0
- package/src/orm/primitives/$sequence.spec.ts +29 -0
- package/src/orm/primitives/$transaction.spec.ts +82 -0
- package/src/orm/providers/drivers/BunPostgresProvider.ts +3 -3
- package/src/orm/providers/drivers/BunSqliteProvider.ts +1 -1
- package/src/orm/providers/drivers/CloudflareD1Provider.ts +1 -1
- package/src/orm/providers/drivers/DatabaseProvider.ts +1 -1
- package/src/orm/providers/drivers/NodePostgresProvider.ts +3 -3
- package/src/orm/providers/drivers/NodeSqliteProvider.ts +1 -1
- package/src/orm/providers/drivers/PglitePostgresProvider.ts +2 -2
- package/src/orm/services/ModelBuilder.spec.ts +575 -0
- package/src/orm/services/Repository.spec.ts +137 -0
- package/src/queue/core/__tests__/shared.ts +143 -0
- package/src/queue/core/providers/MemoryQueueProvider.spec.ts +23 -0
- package/src/queue/core/providers/WorkerProvider.spec.ts +394 -0
- package/src/queue/redis/providers/RedisQueueProvider.spec.ts +23 -0
- package/src/redis/__tests__/redis.spec.ts +58 -0
- package/src/retry/primitives/$retry.spec.ts +234 -0
- package/src/retry/providers/RetryProvider.spec.ts +438 -0
- package/src/router/__tests__/match.spec.ts +252 -0
- package/src/router/providers/RouterProvider.spec.ts +197 -0
- package/src/scheduler/__tests__/$scheduler-cron.spec.ts +25 -0
- package/src/scheduler/__tests__/$scheduler-interval.spec.ts +25 -0
- package/src/scheduler/__tests__/shared.ts +77 -0
- package/src/security/__tests__/bug-1-wildcard-after-start.spec.ts +229 -0
- package/src/security/__tests__/bug-2-password-validation.spec.ts +245 -0
- package/src/security/__tests__/bug-3-regex-vulnerability.spec.ts +407 -0
- package/src/security/__tests__/bug-4-oauth2-validation.spec.ts +439 -0
- package/src/security/__tests__/multi-layer-permissions.spec.ts +522 -0
- package/src/security/primitives/$permission.spec.ts +30 -0
- package/src/security/primitives/$permission.ts +2 -2
- package/src/security/primitives/$realm.spec.ts +101 -0
- package/src/security/primitives/$role.spec.ts +52 -0
- package/src/security/primitives/$serviceAccount.spec.ts +61 -0
- package/src/security/providers/SecurityProvider.spec.ts +350 -0
- package/src/server/auth/providers/ServerAuthProvider.ts +0 -2
- package/src/server/cache/providers/ServerCacheProvider.spec.ts +1125 -0
- package/src/server/cache/providers/ServerCacheProvider.ts +94 -9
- package/src/server/compress/providers/ServerCompressProvider.spec.ts +31 -0
- package/src/server/compress/providers/ServerCompressProvider.ts +63 -2
- package/src/server/cookies/providers/ServerCookiesProvider.spec.ts +253 -0
- package/src/server/core/__tests__/ServerRouterProvider-getRoutes.spec.ts +334 -0
- package/src/server/core/__tests__/ServerRouterProvider-requestId.spec.ts +129 -0
- package/src/server/core/helpers/ServerReply.ts +2 -2
- package/src/server/core/primitives/$action.spec.ts +191 -0
- package/src/server/core/primitives/$route.spec.ts +65 -0
- package/src/server/core/providers/ServerBodyParserProvider.spec.ts +93 -0
- package/src/server/core/providers/ServerLoggerProvider.spec.ts +100 -0
- package/src/server/core/providers/ServerProvider.ts +14 -2
- package/src/server/core/services/HttpClient.spec.ts +123 -0
- package/src/server/core/services/UserAgentParser.spec.ts +111 -0
- package/src/server/cors/providers/ServerCorsProvider.spec.ts +481 -0
- package/src/server/health/providers/ServerHealthProvider.spec.ts +22 -0
- package/src/server/helmet/providers/ServerHelmetProvider.spec.ts +105 -0
- package/src/server/links/__tests__/$action.spec.ts +238 -0
- package/src/server/links/__tests__/fixtures/CrudApp.ts +122 -0
- package/src/server/links/__tests__/requestId.spec.ts +120 -0
- package/src/server/links/primitives/$remote.spec.ts +228 -0
- package/src/server/links/providers/LinkProvider.spec.ts +54 -0
- package/src/server/links/providers/LinkProvider.ts +49 -3
- package/src/server/links/providers/ServerLinksProvider.ts +1 -53
- package/src/server/links/schemas/apiLinksResponseSchema.ts +7 -0
- package/src/server/metrics/providers/ServerMetricsProvider.spec.ts +25 -0
- package/src/server/multipart/providers/ServerMultipartProvider.spec.ts +528 -0
- package/src/server/proxy/primitives/$proxy.spec.ts +87 -0
- package/src/server/rate-limit/__tests__/ActionRateLimit.spec.ts +211 -0
- package/src/server/rate-limit/providers/ServerRateLimitProvider.spec.ts +344 -0
- package/src/server/security/__tests__/BasicAuth.spec.ts +684 -0
- package/src/server/security/__tests__/ServerSecurityProvider-realm.spec.ts +388 -0
- package/src/server/security/providers/ServerSecurityProvider.spec.ts +123 -0
- package/src/server/static/primitives/$serve.spec.ts +193 -0
- package/src/server/static/providers/ServerStaticProvider.ts +10 -0
- package/src/server/swagger/__tests__/ui.spec.ts +52 -0
- package/src/server/swagger/primitives/$swagger.spec.ts +193 -0
- package/src/server/swagger/providers/ServerSwaggerProvider.ts +19 -12
- package/src/sms/primitives/$sms.spec.ts +165 -0
- package/src/sms/providers/LocalSmsProvider.spec.ts +224 -0
- package/src/sms/providers/MemorySmsProvider.spec.ts +193 -0
- package/src/thread/primitives/$thread.spec.ts +186 -0
- package/src/topic/core/__tests__/shared.ts +144 -0
- package/src/topic/core/providers/MemoryTopicProvider.spec.ts +23 -0
- package/src/topic/redis/providers/RedisTopicProvider.spec.ts +23 -0
- package/src/vite/helpers/importViteReact.ts +13 -0
- package/src/vite/index.ts +1 -21
- package/src/vite/plugins/viteAlephaDev.ts +32 -5
- package/src/vite/plugins/viteAlephaSsrPreload.ts +222 -0
- package/src/vite/tasks/buildClient.ts +11 -0
- package/src/vite/tasks/buildServer.ts +47 -3
- package/src/vite/tasks/devServer.ts +69 -0
- package/src/vite/tasks/index.ts +2 -1
- package/src/vite/tasks/runAlepha.ts +7 -1
- package/src/websocket/__tests__/$websocket-new.spec.ts +195 -0
- package/src/websocket/primitives/$channel.spec.ts +30 -0
- package/src/cli/assets/viteConfigTs.ts +0 -14
- package/src/cli/commands/run.ts +0 -24
- package/src/vite/plugins/viteAlepha.ts +0 -37
- package/src/vite/plugins/viteAlephaBuild.ts +0 -281
|
@@ -261,24 +261,55 @@ export class ServerCacheProvider {
|
|
|
261
261
|
return;
|
|
262
262
|
}
|
|
263
263
|
|
|
264
|
-
// Only process string responses (text, html, json, etc.)
|
|
265
|
-
// Buffer is not supported by alepha/cache for now
|
|
266
|
-
if (typeof response.body !== "string") {
|
|
267
|
-
return;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
264
|
// Don't cache error responses (status >= 400)
|
|
271
265
|
if (response.status && response.status >= 400) {
|
|
272
266
|
return;
|
|
273
267
|
}
|
|
274
268
|
|
|
269
|
+
// Initialize headers if not present
|
|
270
|
+
response.headers ??= {};
|
|
271
|
+
|
|
275
272
|
const key = this.createCacheKey(route, request);
|
|
273
|
+
|
|
274
|
+
// Handle ReadableStream responses (e.g., SSR streaming)
|
|
275
|
+
if (response.body instanceof ReadableStream && shouldStore) {
|
|
276
|
+
// Tee the stream: one for client, one for cache collection
|
|
277
|
+
const [clientStream, cacheStream] = (
|
|
278
|
+
response.body as ReadableStream<Uint8Array>
|
|
279
|
+
).tee();
|
|
280
|
+
|
|
281
|
+
// Replace response body with client stream (continues streaming to client)
|
|
282
|
+
response.body = clientStream as typeof response.body;
|
|
283
|
+
|
|
284
|
+
// Collect cache stream in background (non-blocking)
|
|
285
|
+
this.collectStreamForCache(
|
|
286
|
+
cacheStream,
|
|
287
|
+
key,
|
|
288
|
+
response.status,
|
|
289
|
+
response.headers?.["content-type"],
|
|
290
|
+
shouldUseEtag,
|
|
291
|
+
)
|
|
292
|
+
.then((hash) => {
|
|
293
|
+
if (shouldUseEtag && hash) {
|
|
294
|
+
// Note: headers already sent for streaming, etag only useful for future requests
|
|
295
|
+
this.log.trace("Stream cached with hash", { key, hash });
|
|
296
|
+
}
|
|
297
|
+
})
|
|
298
|
+
.catch((err) => {
|
|
299
|
+
this.log.warn("Failed to cache stream", { key, error: err });
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Only process string responses (text, html, json, etc.)
|
|
306
|
+
if (typeof response.body !== "string") {
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
|
|
276
310
|
const generatedEtag = this.generateETag(response.body);
|
|
277
311
|
const lastModified = this.time.toISOString();
|
|
278
312
|
|
|
279
|
-
// Initialize headers if not present
|
|
280
|
-
response.headers ??= {};
|
|
281
|
-
|
|
282
313
|
// Store response if storing is enabled
|
|
283
314
|
if (shouldStore) {
|
|
284
315
|
this.log.trace("Storing response", {
|
|
@@ -404,6 +435,60 @@ export class ServerCacheProvider {
|
|
|
404
435
|
|
|
405
436
|
return `${route.method}:${route.path.replaceAll(":", "")}:${params.join(",").replaceAll(":", "")}`;
|
|
406
437
|
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Collect a ReadableStream into a string and store it in the cache.
|
|
441
|
+
* This runs in the background while the original stream is sent to the client.
|
|
442
|
+
*
|
|
443
|
+
* @param stream - The stream to collect
|
|
444
|
+
* @param key - Cache key
|
|
445
|
+
* @param status - HTTP status code
|
|
446
|
+
* @param contentType - Content-Type header
|
|
447
|
+
* @param generateEtag - Whether to generate and return an ETag
|
|
448
|
+
* @returns The generated ETag hash, or undefined
|
|
449
|
+
*/
|
|
450
|
+
protected async collectStreamForCache(
|
|
451
|
+
stream: ReadableStream<Uint8Array>,
|
|
452
|
+
key: string,
|
|
453
|
+
status: number | undefined,
|
|
454
|
+
contentType: string | undefined,
|
|
455
|
+
generateEtag: boolean,
|
|
456
|
+
): Promise<string | undefined> {
|
|
457
|
+
const chunks: Uint8Array[] = [];
|
|
458
|
+
const reader = stream.getReader();
|
|
459
|
+
|
|
460
|
+
try {
|
|
461
|
+
while (true) {
|
|
462
|
+
const { done, value } = await reader.read();
|
|
463
|
+
if (done) break;
|
|
464
|
+
chunks.push(value);
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// Combine chunks into a single string
|
|
468
|
+
const decoder = new TextDecoder();
|
|
469
|
+
const body =
|
|
470
|
+
chunks
|
|
471
|
+
.map((chunk) => decoder.decode(chunk, { stream: true }))
|
|
472
|
+
.join("") + decoder.decode(); // Flush remaining
|
|
473
|
+
|
|
474
|
+
const hash = this.generateETag(body);
|
|
475
|
+
const lastModified = this.time.toISOString();
|
|
476
|
+
|
|
477
|
+
this.log.trace("Storing streamed response", { key });
|
|
478
|
+
|
|
479
|
+
await this.cache.set(key, {
|
|
480
|
+
body,
|
|
481
|
+
status,
|
|
482
|
+
contentType,
|
|
483
|
+
lastModified,
|
|
484
|
+
hash,
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
return generateEtag ? hash : undefined;
|
|
488
|
+
} finally {
|
|
489
|
+
reader.releaseLock();
|
|
490
|
+
}
|
|
491
|
+
}
|
|
407
492
|
}
|
|
408
493
|
|
|
409
494
|
export type ServerRouteCache =
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Alepha } from "alepha";
|
|
2
|
+
import { $action, ServerProvider } from "alepha/server";
|
|
3
|
+
import { describe, it } from "vitest";
|
|
4
|
+
import { AlephaServerCompress } from "../index.ts";
|
|
5
|
+
|
|
6
|
+
class App {
|
|
7
|
+
hello = $action({
|
|
8
|
+
handler: () => "Hello, world!",
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const a1 = Alepha.create().with(App).with(AlephaServerCompress);
|
|
13
|
+
const a2 = Alepha.create().with(App);
|
|
14
|
+
|
|
15
|
+
describe("ServerCompressProvider", () => {
|
|
16
|
+
it("should compress responses when enabled", async ({ expect }) => {
|
|
17
|
+
const serv1 = a1.inject(ServerProvider);
|
|
18
|
+
const serv2 = a2.inject(ServerProvider);
|
|
19
|
+
|
|
20
|
+
const resp1 = await fetch(`${serv1.hostname}/api/hello`, {
|
|
21
|
+
headers: { "Accept-Encoding": "gzip" },
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const resp2 = await fetch(`${serv2.hostname}/api/hello`, {
|
|
25
|
+
headers: { "Accept-Encoding": "gzip" },
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
expect(resp1.headers.get("content-encoding")).toBe("gzip");
|
|
29
|
+
expect(resp2.headers.get("content-encoding")).toBeNull();
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -125,21 +125,82 @@ export class ServerCompressProvider {
|
|
|
125
125
|
this.setHeaders(response, encoding);
|
|
126
126
|
response.headers["content-length"] = compressed.length.toString();
|
|
127
127
|
response.body = compressed;
|
|
128
|
+
return;
|
|
128
129
|
}
|
|
129
130
|
|
|
130
131
|
if (typeof body === "object" && body instanceof Readable) {
|
|
131
132
|
this.setHeaders(response, encoding);
|
|
132
133
|
response.body = body.pipe(compressor.stream({ params }));
|
|
134
|
+
return;
|
|
133
135
|
}
|
|
134
136
|
|
|
135
137
|
if (typeof body === "object" && body instanceof ReadableStream) {
|
|
136
138
|
this.setHeaders(response, encoding);
|
|
137
|
-
|
|
138
|
-
|
|
139
|
+
// For streaming responses, use flush mode to avoid buffering
|
|
140
|
+
response.body = this.createFlushingCompressStream(
|
|
141
|
+
body,
|
|
142
|
+
compressor.stream,
|
|
143
|
+
encoding,
|
|
144
|
+
params,
|
|
139
145
|
);
|
|
140
146
|
}
|
|
141
147
|
}
|
|
142
148
|
|
|
149
|
+
/**
|
|
150
|
+
* Create a compressed stream that flushes after each chunk.
|
|
151
|
+
* This is essential for streaming SSR - ensures each chunk is sent immediately.
|
|
152
|
+
*/
|
|
153
|
+
protected createFlushingCompressStream(
|
|
154
|
+
input: ReadableStream,
|
|
155
|
+
createCompressor: (options?: any) => Transform,
|
|
156
|
+
encoding: string,
|
|
157
|
+
params: Record<number, any>,
|
|
158
|
+
): ReadableStream<Uint8Array> {
|
|
159
|
+
const compressor = createCompressor({
|
|
160
|
+
params,
|
|
161
|
+
flush: zlib.constants.Z_SYNC_FLUSH,
|
|
162
|
+
});
|
|
163
|
+
const reader = Readable.fromWeb(input);
|
|
164
|
+
|
|
165
|
+
return new ReadableStream<Uint8Array>({
|
|
166
|
+
start(controller) {
|
|
167
|
+
compressor.on("data", (chunk: Buffer) => {
|
|
168
|
+
controller.enqueue(new Uint8Array(chunk));
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
compressor.on("end", () => {
|
|
172
|
+
controller.close();
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
compressor.on("error", (err) => {
|
|
176
|
+
controller.error(err);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
reader.on("data", (chunk: Buffer) => {
|
|
180
|
+
compressor.write(chunk);
|
|
181
|
+
// Force flush after each chunk for streaming
|
|
182
|
+
// Cast to any because flush() exists on zlib streams but not in Transform type
|
|
183
|
+
const zlibStream = compressor as any;
|
|
184
|
+
if (encoding === "gzip") {
|
|
185
|
+
zlibStream.flush(zlib.constants.Z_SYNC_FLUSH);
|
|
186
|
+
} else if (encoding === "br") {
|
|
187
|
+
zlibStream.flush(zlib.constants.BROTLI_OPERATION_FLUSH);
|
|
188
|
+
} else if (encoding === "zstd") {
|
|
189
|
+
zlibStream.flush();
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
reader.on("end", () => {
|
|
194
|
+
compressor.end();
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
reader.on("error", (err) => {
|
|
198
|
+
controller.error(err);
|
|
199
|
+
});
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
143
204
|
protected getParams(
|
|
144
205
|
encoding: keyof typeof ServerCompressProvider.compressors,
|
|
145
206
|
): Record<number, any> {
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import { Alepha, t } from "alepha";
|
|
2
|
+
import { $action, AlephaServer } from "alepha/server";
|
|
3
|
+
import { describe, expect, test } from "vitest";
|
|
4
|
+
import { $cookie, AlephaServerCookies } from "../index.ts";
|
|
5
|
+
|
|
6
|
+
// A strong, 32-character secret for testing purposes
|
|
7
|
+
const TEST_COOKIE_SECRET = "DCf6DvpLAfwy8XdPRucMO4tPS6dVCHob";
|
|
8
|
+
|
|
9
|
+
// --- Test Application Setup ---
|
|
10
|
+
|
|
11
|
+
class CookieTestApp {
|
|
12
|
+
// 1. Basic Cookie
|
|
13
|
+
session = $cookie({
|
|
14
|
+
name: "session",
|
|
15
|
+
schema: t.object({ userId: t.number(), role: t.text() }),
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// 2. Signed Cookie
|
|
19
|
+
signed = $cookie({
|
|
20
|
+
name: "signed_session",
|
|
21
|
+
schema: t.text(),
|
|
22
|
+
sign: true,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// 3. Encrypted Cookie
|
|
26
|
+
encrypted = $cookie({
|
|
27
|
+
name: "encrypted_secret",
|
|
28
|
+
schema: t.object({ apiKey: t.text() }),
|
|
29
|
+
encrypt: true,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// 4. Compressed, Signed, and Encrypted Cookie with TTL
|
|
33
|
+
secure_all = $cookie({
|
|
34
|
+
name: "ultra_secure",
|
|
35
|
+
schema: t.object({ data: t.text() }),
|
|
36
|
+
compress: true,
|
|
37
|
+
sign: true,
|
|
38
|
+
encrypt: true,
|
|
39
|
+
ttl: [1, "hour"],
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// An action to test the cookie functionality in a request cycle
|
|
43
|
+
cookie_test = $action({
|
|
44
|
+
schema: {
|
|
45
|
+
response: t.object({
|
|
46
|
+
incomingSession: t.optional(this.session.options.schema),
|
|
47
|
+
reqCookies: t.object({
|
|
48
|
+
req: t.record(t.text(), t.text()),
|
|
49
|
+
res: t.record(t.text(), t.any()),
|
|
50
|
+
}),
|
|
51
|
+
}),
|
|
52
|
+
},
|
|
53
|
+
handler: ({ cookies }) => {
|
|
54
|
+
// Set some cookies
|
|
55
|
+
this.session.set({ userId: 123, role: "admin" });
|
|
56
|
+
this.signed.set("i-am-signed");
|
|
57
|
+
this.encrypted.set({ apiKey: "secret-key" });
|
|
58
|
+
this.secure_all.set({ data: "super sensitive data" });
|
|
59
|
+
|
|
60
|
+
// Read a cookie from the request
|
|
61
|
+
const incomingSession = this.session.get({ cookies });
|
|
62
|
+
|
|
63
|
+
// Delete a cookie
|
|
64
|
+
if (incomingSession?.role === "guest") {
|
|
65
|
+
this.signed.del();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return { incomingSession, reqCookies: cookies };
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const alepha = Alepha.create({
|
|
74
|
+
env: {
|
|
75
|
+
COOKIE_SECRET: TEST_COOKIE_SECRET,
|
|
76
|
+
},
|
|
77
|
+
})
|
|
78
|
+
.with(AlephaServer)
|
|
79
|
+
.with(AlephaServerCookies);
|
|
80
|
+
|
|
81
|
+
const app = alepha.inject(CookieTestApp);
|
|
82
|
+
|
|
83
|
+
// Helper to simulate a request and capture the response headers
|
|
84
|
+
const makeRequest = async (incomingCookieHeader = "") => {
|
|
85
|
+
const response = await app.cookie_test.fetch(
|
|
86
|
+
{},
|
|
87
|
+
{
|
|
88
|
+
request: { headers: { cookie: incomingCookieHeader } },
|
|
89
|
+
},
|
|
90
|
+
);
|
|
91
|
+
return {
|
|
92
|
+
data: response.data,
|
|
93
|
+
// The fetch client in tests might not handle multiple headers the same way a browser does.
|
|
94
|
+
// We get the raw header to properly check it.
|
|
95
|
+
setCookieHeader: response.raw?.headers.get("set-cookie"),
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
describe("ServerCookiesProvider", () => {
|
|
100
|
+
test("should set and get a basic cookie", async () => {
|
|
101
|
+
const { data, setCookieHeader } = await makeRequest();
|
|
102
|
+
|
|
103
|
+
// The handler receives no initial cookie
|
|
104
|
+
expect(data.incomingSession).toBeUndefined();
|
|
105
|
+
|
|
106
|
+
// Check if the response sets the cookie correctly
|
|
107
|
+
expect(setCookieHeader).toBeDefined();
|
|
108
|
+
const decodedValue = JSON.parse(
|
|
109
|
+
decodeURIComponent(setCookieHeader!.match(/session=([^;]*)/)![1]),
|
|
110
|
+
);
|
|
111
|
+
expect(decodedValue).toEqual({ userId: 123, role: "admin" });
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test("should correctly read an incoming cookie", async () => {
|
|
115
|
+
const sessionData = { userId: 456, role: "user" };
|
|
116
|
+
const cookieHeader = `session=${encodeURIComponent(JSON.stringify(sessionData))}`;
|
|
117
|
+
|
|
118
|
+
const { data } = await makeRequest(cookieHeader);
|
|
119
|
+
|
|
120
|
+
// The handler should have received and parsed the cookie
|
|
121
|
+
expect(data.incomingSession).toEqual(sessionData);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test("should set and get a signed cookie", async () => {
|
|
125
|
+
const { setCookieHeader } = await makeRequest();
|
|
126
|
+
const signedCookie = setCookieHeader!.match(/signed_session=([^;]*)/)![1];
|
|
127
|
+
|
|
128
|
+
// Make a new request with the signed cookie
|
|
129
|
+
const { data } = await makeRequest(`signed_session=${signedCookie}`);
|
|
130
|
+
|
|
131
|
+
// The `get` method should successfully validate the signature and return the value
|
|
132
|
+
expect(app.signed.get({ cookies: data.reqCookies })).toBe("i-am-signed");
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test("should reject a tampered signed cookie", async () => {
|
|
136
|
+
const { setCookieHeader } = await makeRequest();
|
|
137
|
+
let tamperedCookie = setCookieHeader!.match(/signed_session=([^;]*)/)![1];
|
|
138
|
+
tamperedCookie += "tampered"; // alter the cookie value
|
|
139
|
+
|
|
140
|
+
const { data } = await makeRequest(`signed_session=${tamperedCookie}`);
|
|
141
|
+
|
|
142
|
+
// The get should fail and return undefined
|
|
143
|
+
expect(app.signed.get({ cookies: data.reqCookies })).toBeUndefined();
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
test("should set and get an encrypted cookie", async () => {
|
|
147
|
+
const { setCookieHeader } = await makeRequest();
|
|
148
|
+
const encryptedCookie = setCookieHeader!.match(
|
|
149
|
+
/encrypted_secret=([^;]*)/,
|
|
150
|
+
)![1];
|
|
151
|
+
|
|
152
|
+
// The value should not be plain text
|
|
153
|
+
expect(decodeURIComponent(encryptedCookie)).not.toContain("secret-key");
|
|
154
|
+
|
|
155
|
+
const { data } = await makeRequest(`encrypted_secret=${encryptedCookie}`);
|
|
156
|
+
|
|
157
|
+
expect(app.encrypted.get({ cookies: data.reqCookies })).toEqual({
|
|
158
|
+
apiKey: "secret-key",
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
test("should reject a tampered encrypted cookie", async () => {
|
|
163
|
+
const { setCookieHeader } = await makeRequest();
|
|
164
|
+
const tamperedCookie = setCookieHeader!.match(
|
|
165
|
+
/encrypted_secret=([^;]*)/,
|
|
166
|
+
)![1];
|
|
167
|
+
|
|
168
|
+
const { data } = await makeRequest(
|
|
169
|
+
`encrypted_secret=aa${tamperedCookie}aa`,
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
// The get should fail (throw internally) and return undefined
|
|
173
|
+
expect(app.encrypted.get({ cookies: data.reqCookies })).toBeUndefined();
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
test("should handle a combination of compress, sign, and encrypt", async () => {
|
|
177
|
+
const { setCookieHeader } = await makeRequest();
|
|
178
|
+
const secureCookie = setCookieHeader!.match(/ultra_secure=([^;]*)/)![1];
|
|
179
|
+
|
|
180
|
+
const { data } = await makeRequest(`ultra_secure=${secureCookie}`);
|
|
181
|
+
|
|
182
|
+
expect(app.secure_all.get({ cookies: data.reqCookies })).toEqual({
|
|
183
|
+
data: "super sensitive data",
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
test("should delete a cookie", async () => {
|
|
188
|
+
const sessionData = { userId: 789, role: "guest" };
|
|
189
|
+
const cookieHeader = `session=${encodeURIComponent(JSON.stringify(sessionData))}`;
|
|
190
|
+
|
|
191
|
+
const { setCookieHeader } = await makeRequest(cookieHeader);
|
|
192
|
+
|
|
193
|
+
// The handler should detect role === 'guest' and delete the signed cookie
|
|
194
|
+
expect(setCookieHeader).toContain("signed_session=; Path=/; Max-Age=0");
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
test("should serialize all cookie attributes correctly", async () => {
|
|
198
|
+
class AttrApp {
|
|
199
|
+
advanced = $cookie({
|
|
200
|
+
name: "advanced",
|
|
201
|
+
schema: t.text(),
|
|
202
|
+
path: "/admin",
|
|
203
|
+
ttl: [30, "minutes"],
|
|
204
|
+
httpOnly: true,
|
|
205
|
+
secure: true,
|
|
206
|
+
sameSite: "strict",
|
|
207
|
+
domain: "example.com",
|
|
208
|
+
});
|
|
209
|
+
test = $action({
|
|
210
|
+
handler: () => {
|
|
211
|
+
this.advanced.set("value");
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const attrAlepha = Alepha.create({
|
|
217
|
+
env: { COOKIE_SECRET: TEST_COOKIE_SECRET },
|
|
218
|
+
})
|
|
219
|
+
.with(AlephaServer)
|
|
220
|
+
.with(AlephaServerCookies)
|
|
221
|
+
.with(AttrApp);
|
|
222
|
+
|
|
223
|
+
await attrAlepha.start();
|
|
224
|
+
|
|
225
|
+
const response = await attrAlepha.inject(AttrApp).test.fetch();
|
|
226
|
+
const setCookieHeader = response.headers.get("set-cookie");
|
|
227
|
+
expect(setCookieHeader).toContain("Max-Age=1800");
|
|
228
|
+
expect(setCookieHeader).toContain("Path=/admin");
|
|
229
|
+
expect(setCookieHeader).toContain("HttpOnly");
|
|
230
|
+
expect(setCookieHeader).toContain("SameSite=strict");
|
|
231
|
+
expect(setCookieHeader).toContain("Domain=example.com");
|
|
232
|
+
// Secure flag is not added in tests unless protocol is https, which is handled by the provider
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// test("should throw if secret is missing for secure cookies", async () => {
|
|
236
|
+
// class AppWithMissingSecret {
|
|
237
|
+
// badCookie = $cookie({
|
|
238
|
+
// name: "bad",
|
|
239
|
+
// schema: t.text(),
|
|
240
|
+
// sign: true,
|
|
241
|
+
// });
|
|
242
|
+
// }
|
|
243
|
+
//
|
|
244
|
+
// const alephaWithoutSecret = Alepha.create()
|
|
245
|
+
// .with(AlephaServer)
|
|
246
|
+
// .with(AlephaServerCookies)
|
|
247
|
+
// .with(AppWithMissingSecret);
|
|
248
|
+
//
|
|
249
|
+
// await expect(() => alephaWithoutSecret.start()).rejects.toThrow(
|
|
250
|
+
// /COOKIE_SECRET environment variable is not set/,
|
|
251
|
+
// );
|
|
252
|
+
// });
|
|
253
|
+
});
|