alepha 0.15.1 → 0.15.3
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 +68 -80
- package/dist/api/audits/index.d.ts +10 -33
- package/dist/api/audits/index.d.ts.map +1 -1
- package/dist/api/audits/index.js +10 -33
- package/dist/api/audits/index.js.map +1 -1
- package/dist/api/files/index.d.ts +10 -3
- package/dist/api/files/index.d.ts.map +1 -1
- package/dist/api/files/index.js +10 -3
- package/dist/api/files/index.js.map +1 -1
- package/dist/api/jobs/index.d.ts +162 -155
- 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.d.ts +10 -4
- package/dist/api/notifications/index.d.ts.map +1 -1
- package/dist/api/notifications/index.js +10 -4
- package/dist/api/notifications/index.js.map +1 -1
- package/dist/api/parameters/index.d.ts +43 -50
- 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 +1081 -760
- package/dist/api/users/index.d.ts.map +1 -1
- package/dist/api/users/index.js +2539 -218
- package/dist/api/users/index.js.map +1 -1
- package/dist/api/verifications/index.d.ts +138 -132
- 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 +20 -40
- 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 +440 -8
- package/dist/bucket/index.d.ts.map +1 -1
- package/dist/bucket/index.js +1861 -12
- package/dist/bucket/index.js.map +1 -1
- package/dist/cache/core/index.d.ts +179 -7
- 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 +4 -0
- package/dist/cache/redis/index.js.map +1 -1
- package/dist/cli/index.d.ts +638 -5645
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +2550 -368
- package/dist/cli/index.js.map +1 -1
- package/dist/command/index.d.ts +203 -45
- package/dist/command/index.d.ts.map +1 -1
- package/dist/command/index.js +2060 -71
- package/dist/command/index.js.map +1 -1
- package/dist/core/index.browser.js +70 -40
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +34 -13
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +90 -40
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js +70 -40
- package/dist/core/index.native.js.map +1 -1
- package/dist/datetime/index.d.ts +15 -0
- 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 +323 -20
- package/dist/email/index.d.ts.map +1 -1
- package/dist/email/index.js +1857 -7
- package/dist/email/index.js.map +1 -1
- package/dist/fake/index.d.ts +90 -8
- package/dist/fake/index.d.ts.map +1 -1
- package/dist/fake/index.js +91 -20
- package/dist/fake/index.js.map +1 -1
- package/dist/lock/core/index.d.ts +11 -4
- 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/logger/index.d.ts +17 -66
- package/dist/logger/index.d.ts.map +1 -1
- package/dist/logger/index.js +14 -63
- package/dist/logger/index.js.map +1 -1
- package/dist/mcp/index.d.ts +10 -30
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +12 -35
- package/dist/mcp/index.js.map +1 -1
- package/dist/orm/index.browser.js +3 -3
- package/dist/orm/index.browser.js.map +1 -1
- package/dist/orm/index.bun.js +39 -20
- package/dist/orm/index.bun.js.map +1 -1
- package/dist/orm/index.d.ts +517 -540
- package/dist/orm/index.d.ts.map +1 -1
- package/dist/orm/index.js +58 -71
- package/dist/orm/index.js.map +1 -1
- package/dist/queue/core/index.d.ts +18 -10
- 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/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 +1974 -0
- package/dist/react/router/index.browser.js.map +1 -0
- package/dist/react/router/index.d.ts +1956 -0
- package/dist/react/router/index.d.ts.map +1 -0
- package/dist/react/router/index.js +4722 -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 +41 -44
- 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 +11 -2
- 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/scheduler/index.d.ts +11 -2
- package/dist/scheduler/index.d.ts.map +1 -1
- package/dist/scheduler/index.js +11 -2
- package/dist/scheduler/index.js.map +1 -1
- package/dist/security/index.d.ts +140 -49
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +164 -32
- package/dist/security/index.js.map +1 -1
- package/dist/server/auth/index.d.ts +12 -7
- package/dist/server/auth/index.d.ts.map +1 -1
- package/dist/server/auth/index.js +12 -7
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/cache/index.d.ts +7 -22
- 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 +10 -2
- 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 +40 -16
- 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 +124 -23
- package/dist/server/core/index.d.ts.map +1 -1
- package/dist/server/core/index.js +231 -14
- package/dist/server/core/index.js.map +1 -1
- package/dist/server/cors/index.d.ts +13 -23
- 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 +8 -2
- 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 +11 -3
- 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.d.ts +11 -6
- package/dist/server/links/index.d.ts.map +1 -1
- package/dist/server/links/index.js +11 -6
- package/dist/server/links/index.js.map +1 -1
- package/dist/server/metrics/index.d.ts +10 -3
- package/dist/server/metrics/index.d.ts.map +1 -1
- package/dist/server/metrics/index.js +10 -3
- package/dist/server/metrics/index.js.map +1 -1
- package/dist/server/multipart/index.d.ts +9 -3
- 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 +8 -2
- 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 +30 -35
- 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 +137 -4
- package/dist/server/static/index.d.ts.map +1 -1
- package/dist/server/static/index.js +1853 -5
- package/dist/server/static/index.js.map +1 -1
- package/dist/server/swagger/index.d.ts +309 -6
- package/dist/server/swagger/index.d.ts.map +1 -1
- package/dist/server/swagger/index.js +1854 -6
- package/dist/server/swagger/index.js.map +1 -1
- package/dist/sms/index.d.ts +309 -7
- package/dist/sms/index.d.ts.map +1 -1
- package/dist/sms/index.js +1856 -7
- package/dist/sms/index.js.map +1 -1
- package/dist/system/index.browser.js +1218 -0
- package/dist/system/index.browser.js.map +1 -0
- package/dist/{file → system}/index.d.ts +343 -16
- package/dist/system/index.d.ts.map +1 -0
- package/dist/{file → system}/index.js +419 -22
- package/dist/system/index.js.map +1 -0
- package/dist/thread/index.d.ts +11 -2
- package/dist/thread/index.d.ts.map +1 -1
- package/dist/thread/index.js +11 -2
- package/dist/thread/index.js.map +1 -1
- package/dist/topic/core/index.d.ts +12 -5
- 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/vite/index.d.ts +5 -6272
- package/dist/vite/index.d.ts.map +1 -1
- package/dist/vite/index.js +23 -10
- package/dist/vite/index.js.map +1 -1
- package/dist/websocket/index.d.ts +12 -8
- package/dist/websocket/index.d.ts.map +1 -1
- package/dist/websocket/index.js +12 -8
- package/dist/websocket/index.js.map +1 -1
- package/package.json +82 -11
- 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 +55 -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 -1
- 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 +1 -14
- package/src/cli/apps/AlephaPackageBuilderCli.ts +10 -1
- package/src/cli/atoms/buildOptions.ts +99 -9
- package/src/cli/commands/build.ts +150 -37
- package/src/cli/commands/db.ts +22 -18
- package/src/cli/commands/deploy.ts +1 -1
- package/src/cli/commands/dev.ts +1 -20
- package/src/cli/commands/gen/env.ts +5 -2
- package/src/cli/commands/gen/openapi.ts +5 -2
- package/src/cli/commands/init.spec.ts +588 -0
- package/src/cli/commands/init.ts +115 -58
- package/src/cli/commands/lint.ts +7 -1
- package/src/cli/commands/typecheck.ts +11 -0
- package/src/cli/providers/AppEntryProvider.ts +1 -1
- package/src/cli/providers/ViteBuildProvider.ts +8 -50
- package/src/cli/providers/ViteDevServerProvider.ts +35 -16
- package/src/cli/services/AlephaCliUtils.ts +52 -121
- package/src/cli/services/PackageManagerUtils.ts +129 -11
- package/src/cli/services/ProjectScaffolder.spec.ts +97 -0
- package/src/cli/services/ProjectScaffolder.ts +148 -81
- package/src/cli/services/ViteUtils.ts +82 -0
- package/src/cli/{assets/claudeMd.ts → templates/agentMd.ts} +37 -24
- package/src/cli/templates/apiAppSecurityTs.ts +11 -0
- package/src/cli/templates/apiIndexTs.ts +30 -0
- package/src/cli/templates/gitignore.ts +39 -0
- package/src/cli/{assets → templates}/mainCss.ts +11 -2
- package/src/cli/templates/mainServerTs.ts +33 -0
- package/src/cli/templates/webAppRouterTs.ts +74 -0
- package/src/cli/templates/webHelloComponentTsx.ts +30 -0
- package/src/command/helpers/Runner.spec.ts +139 -0
- package/src/command/helpers/Runner.ts +7 -22
- package/src/command/index.ts +12 -4
- package/src/command/providers/CliProvider.spec.ts +1392 -0
- package/src/command/providers/CliProvider.ts +320 -47
- package/src/core/Alepha.ts +34 -27
- 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/providers/EventManager.spec.ts +0 -71
- package/src/core/providers/EventManager.ts +3 -15
- package/src/core/providers/Json.ts +2 -14
- 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/mcp/index.ts +10 -27
- package/src/mcp/transports/SseMcpTransport.ts +0 -11
- package/src/orm/__tests__/PostgresProvider.spec.ts +2 -2
- package/src/orm/index.browser.ts +2 -2
- package/src/orm/index.bun.ts +5 -3
- package/src/orm/index.ts +23 -53
- package/src/orm/providers/drivers/BunSqliteProvider.ts +5 -1
- package/src/orm/providers/drivers/CloudflareD1Provider.ts +57 -30
- package/src/orm/providers/drivers/DatabaseProvider.ts +9 -1
- package/src/orm/providers/drivers/NodeSqliteProvider.ts +4 -1
- package/src/orm/services/Repository.ts +7 -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 +146 -0
- package/src/react/router/primitives/$page.browser.spec.tsx +851 -0
- package/src/react/router/primitives/$page.spec.tsx +676 -0
- package/src/react/router/primitives/$page.ts +489 -0
- package/src/react/router/providers/ReactBrowserProvider.ts +312 -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/ReactPreloadProvider.spec.ts +142 -0
- package/src/react/router/providers/ReactPreloadProvider.ts +85 -0
- package/src/react/router/providers/ReactServerProvider.spec.tsx +316 -0
- package/src/react/router/providers/ReactServerProvider.ts +487 -0
- package/src/react/router/providers/ReactServerTemplateProvider.spec.ts +210 -0
- package/src/react/router/providers/ReactServerTemplateProvider.ts +542 -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 +90 -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 +63 -41
- 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 +16 -6
- 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/NodeHttpServerProvider.spec.ts +9 -3
- package/src/server/core/providers/NodeHttpServerProvider.ts +9 -3
- 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/index.ts +11 -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 +36 -0
- package/src/system/index.ts +62 -0
- package/src/system/index.workerd.ts +1 -0
- package/src/{file → system}/providers/FileSystemProvider.ts +24 -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 +47 -2
- 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/tasks/buildClient.ts +2 -7
- package/src/vite/tasks/buildServer.ts +19 -13
- package/src/vite/tasks/generateCloudflare.ts +10 -7
- package/src/vite/tasks/generateDocker.ts +4 -0
- package/src/websocket/index.ts +12 -8
- package/dist/file/index.d.ts.map +0 -1
- package/dist/file/index.js.map +0 -1
- package/src/cli/assets/apiIndexTs.ts +0 -16
- package/src/cli/assets/mainServerTs.ts +0 -24
- package/src/cli/assets/webAppRouterTs.ts +0 -16
- package/src/cli/assets/webHelloComponentTsx.ts +0 -20
- package/src/cli/providers/ViteTemplateProvider.ts +0 -27
- package/src/file/index.ts +0 -43
- /package/src/cli/{assets → templates}/apiHelloControllerTs.ts +0 -0
- /package/src/cli/{assets → templates}/biomeJson.ts +0 -0
- /package/src/cli/{assets → templates}/dummySpecTs.ts +0 -0
- /package/src/cli/{assets → templates}/editorconfig.ts +0 -0
- /package/src/cli/{assets → templates}/mainBrowserTs.ts +0 -0
- /package/src/cli/{assets → templates}/tsconfigJson.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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $inject, type Alepha } from "alepha";
|
|
1
|
+
import { $hook, $inject, type Alepha } from "alepha";
|
|
2
2
|
import { DateTimeProvider, type DurationLike } from "alepha/datetime";
|
|
3
3
|
import { $logger } from "alepha/logger";
|
|
4
4
|
import { type RetryBackoffOptions, RetryProvider } from "alepha/retry";
|
|
@@ -130,6 +130,11 @@ export class BatchProvider {
|
|
|
130
130
|
protected readonly dateTime = $inject(DateTimeProvider);
|
|
131
131
|
protected readonly retryProvider = $inject(RetryProvider);
|
|
132
132
|
|
|
133
|
+
/**
|
|
134
|
+
* All active batch contexts managed by this provider.
|
|
135
|
+
*/
|
|
136
|
+
protected readonly contexts = new Set<BatchContext<any, any>>();
|
|
137
|
+
|
|
133
138
|
/**
|
|
134
139
|
* Creates a new batch context with the given options.
|
|
135
140
|
*/
|
|
@@ -137,7 +142,7 @@ export class BatchProvider {
|
|
|
137
142
|
alepha: Alepha,
|
|
138
143
|
options: BatchOptions<TItem, TResponse>,
|
|
139
144
|
): BatchContext<TItem, TResponse> {
|
|
140
|
-
|
|
145
|
+
const context: BatchContext<TItem, TResponse> = {
|
|
141
146
|
options,
|
|
142
147
|
itemStates: new Map(),
|
|
143
148
|
partitions: new Map(),
|
|
@@ -146,8 +151,30 @@ export class BatchProvider {
|
|
|
146
151
|
isReady: false,
|
|
147
152
|
alepha,
|
|
148
153
|
};
|
|
154
|
+
this.contexts.add(context);
|
|
155
|
+
return context;
|
|
149
156
|
}
|
|
150
157
|
|
|
158
|
+
/**
|
|
159
|
+
* Shutdown hook - flushes all batch contexts on application stop.
|
|
160
|
+
*/
|
|
161
|
+
protected readonly onStop = $hook({
|
|
162
|
+
on: "stop",
|
|
163
|
+
priority: "first",
|
|
164
|
+
handler: async () => {
|
|
165
|
+
if (this.contexts.size === 0) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
this.log.debug(`Shutting down ${this.contexts.size} batch context(s)...`);
|
|
169
|
+
const promises: Promise<void>[] = [];
|
|
170
|
+
for (const context of this.contexts) {
|
|
171
|
+
promises.push(this.shutdown(context));
|
|
172
|
+
}
|
|
173
|
+
await Promise.all(promises);
|
|
174
|
+
this.log.debug("All batch contexts shut down");
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
|
|
151
178
|
/**
|
|
152
179
|
* Get the effective maxSize for a context.
|
|
153
180
|
*/
|
package/src/bucket/index.ts
CHANGED
|
@@ -43,14 +43,21 @@ declare module "alepha" {
|
|
|
43
43
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
|
-
*
|
|
46
|
+
* | type | quality | stability |
|
|
47
|
+
* |------|---------|-----------|
|
|
48
|
+
* | backend | rare | stable |
|
|
47
49
|
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
50
|
+
* Unified file storage abstraction across multiple backends.
|
|
51
|
+
*
|
|
52
|
+
* **Features:**
|
|
53
|
+
* - File storage buckets with constraints
|
|
54
|
+
* - Unified API across all storage backends
|
|
55
|
+
* - MIME type validation
|
|
56
|
+
* - File size limits
|
|
57
|
+
* - Upload/download/delete operations
|
|
58
|
+
* - TTL-based file expiration
|
|
59
|
+
* - Providers: Memory (testing), Local filesystem, AWS S3 / Cloudflare R2 / MinIO, Azure Blob Storage, Vercel Blob
|
|
51
60
|
*
|
|
52
|
-
* @see {@link $bucket}
|
|
53
|
-
* @see {@link FileStorageProvider}
|
|
54
61
|
* @module alepha.bucket
|
|
55
62
|
*/
|
|
56
63
|
export const AlephaBucket = $module({
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
Primitive,
|
|
7
7
|
type Service,
|
|
8
8
|
} from "alepha";
|
|
9
|
-
import { FileSystemProvider } from "alepha/
|
|
9
|
+
import { FileSystemProvider } from "alepha/system";
|
|
10
10
|
import { InvalidFileError } from "../errors/InvalidFileError.ts";
|
|
11
11
|
import { FileStorageProvider } from "../providers/FileStorageProvider.ts";
|
|
12
12
|
import { MemoryFileStorageProvider } from "../providers/MemoryFileStorageProvider.ts";
|
|
@@ -15,8 +15,8 @@ import {
|
|
|
15
15
|
type Static,
|
|
16
16
|
t,
|
|
17
17
|
} from "alepha";
|
|
18
|
-
import { FileDetector, FileSystemProvider } from "alepha/file";
|
|
19
18
|
import { $logger } from "alepha/logger";
|
|
19
|
+
import { FileDetector, FileSystemProvider } from "alepha/system";
|
|
20
20
|
import { FileNotFoundError } from "../errors/FileNotFoundError.ts";
|
|
21
21
|
import { $bucket } from "../primitives/$bucket.ts";
|
|
22
22
|
import type { FileStorageProvider } from "./FileStorageProvider.ts";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { $inject, type FileLike } from "alepha";
|
|
3
|
-
import { FileDetector, FileSystemProvider } from "alepha/
|
|
3
|
+
import { FileDetector, FileSystemProvider } from "alepha/system";
|
|
4
4
|
import { FileNotFoundError } from "../errors/FileNotFoundError.ts";
|
|
5
5
|
import type { FileStorageProvider } from "./FileStorageProvider.ts";
|
|
6
6
|
|
|
@@ -321,6 +321,36 @@ export const testSimpleKeyMappingHandler = async (
|
|
|
321
321
|
expect(await app.run("C")).toBe("C=3");
|
|
322
322
|
};
|
|
323
323
|
|
|
324
|
+
export const testCacheIncr = async (
|
|
325
|
+
env: Env = {},
|
|
326
|
+
cacheProvider: Service<CacheProvider> = MemoryCacheProvider,
|
|
327
|
+
): Promise<void> => {
|
|
328
|
+
const app = Alepha.create({
|
|
329
|
+
env,
|
|
330
|
+
}).with({
|
|
331
|
+
provide: CacheProvider,
|
|
332
|
+
use: cacheProvider,
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
const provider = app.inject(CacheProvider);
|
|
336
|
+
await app.start();
|
|
337
|
+
|
|
338
|
+
const name = "test-incr";
|
|
339
|
+
const key = `counter:${randomUUID()}`;
|
|
340
|
+
|
|
341
|
+
// First increment creates the key
|
|
342
|
+
const val1 = await provider.incr(name, key, 1);
|
|
343
|
+
expect(val1).toBe(1);
|
|
344
|
+
|
|
345
|
+
// Subsequent increments add to existing value
|
|
346
|
+
const val2 = await provider.incr(name, key, 5);
|
|
347
|
+
expect(val2).toBe(6);
|
|
348
|
+
|
|
349
|
+
// Negative amounts work (decrement)
|
|
350
|
+
const val3 = await provider.incr(name, key, -2);
|
|
351
|
+
expect(val3).toBe(4);
|
|
352
|
+
};
|
|
353
|
+
|
|
324
354
|
export const testCacheProviderClear = async (
|
|
325
355
|
env: Env = {},
|
|
326
356
|
cacheProvider: Service<CacheProvider> = MemoryCacheProvider,
|
package/src/cache/core/index.ts
CHANGED
|
@@ -12,14 +12,19 @@ export * from "./providers/MemoryCacheProvider.ts";
|
|
|
12
12
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
15
|
+
* | type | quality | stability |
|
|
16
|
+
* |------|---------|-----------|
|
|
17
|
+
* | backend | rare | stable |
|
|
16
18
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
19
|
+
* Type-safe caching with TTL support.
|
|
20
|
+
*
|
|
21
|
+
* **Features:**
|
|
22
|
+
* - Cached computations with type-safe keys and values
|
|
23
|
+
* - Configurable TTL
|
|
24
|
+
* - Cache invalidation
|
|
25
|
+
* - Automatic cache population
|
|
26
|
+
* - Providers: Memory (default), Redis
|
|
20
27
|
*
|
|
21
|
-
* @see {@link $cache}
|
|
22
|
-
* @see {@link CacheProvider}
|
|
23
28
|
* @module alepha.cache
|
|
24
29
|
*/
|
|
25
30
|
export const AlephaCache = $module({
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
testCacheBasic,
|
|
8
8
|
testCacheClear,
|
|
9
9
|
testCacheDisabled,
|
|
10
|
+
testCacheIncr,
|
|
10
11
|
testCacheInvalidateAll,
|
|
11
12
|
testCacheInvalidateByArgs,
|
|
12
13
|
testCacheInvalidateByKey,
|
|
@@ -108,4 +109,8 @@ describe("$cache", () => {
|
|
|
108
109
|
it("should clear provider cache", async () => {
|
|
109
110
|
await testCacheProviderClear();
|
|
110
111
|
});
|
|
112
|
+
|
|
113
|
+
it("should increment values atomically", async () => {
|
|
114
|
+
await testCacheIncr();
|
|
115
|
+
});
|
|
111
116
|
});
|
|
@@ -51,4 +51,21 @@ export abstract class CacheProvider {
|
|
|
51
51
|
* Remove all keys from all cache names.
|
|
52
52
|
*/
|
|
53
53
|
public abstract clear(): Promise<void>;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Increment the integer value of a key by the given amount.
|
|
57
|
+
*
|
|
58
|
+
* If the key does not exist, it is set to 0 before performing the operation.
|
|
59
|
+
* This operation is atomic when using Redis.
|
|
60
|
+
*
|
|
61
|
+
* @param name Cache name, used to group keys.
|
|
62
|
+
* @param key The key to increment.
|
|
63
|
+
* @param amount The amount to increment by.
|
|
64
|
+
* @returns The new value after incrementing.
|
|
65
|
+
*/
|
|
66
|
+
public abstract incr(
|
|
67
|
+
name: string,
|
|
68
|
+
key: string,
|
|
69
|
+
amount: number,
|
|
70
|
+
): Promise<number>;
|
|
54
71
|
}
|
|
@@ -10,14 +10,150 @@ type CacheValue = {
|
|
|
10
10
|
timeout?: Timeout;
|
|
11
11
|
};
|
|
12
12
|
|
|
13
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
export interface MemoryCacheCall {
|
|
16
|
+
name: string;
|
|
17
|
+
key: string;
|
|
18
|
+
timestamp: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface MemoryCacheSetCall extends MemoryCacheCall {
|
|
22
|
+
value: Uint8Array;
|
|
23
|
+
ttl?: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface MemoryCacheDelCall {
|
|
27
|
+
name: string;
|
|
28
|
+
keys: string[];
|
|
29
|
+
timestamp: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface MemoryCacheStats {
|
|
33
|
+
hits: number;
|
|
34
|
+
misses: number;
|
|
35
|
+
sets: number;
|
|
36
|
+
deletes: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface MemoryCacheProviderOptions {
|
|
40
|
+
/**
|
|
41
|
+
* Error to throw on get operations (for testing error handling)
|
|
42
|
+
*/
|
|
43
|
+
getError?: Error | null;
|
|
44
|
+
/**
|
|
45
|
+
* Error to throw on set operations (for testing error handling)
|
|
46
|
+
*/
|
|
47
|
+
setError?: Error | null;
|
|
48
|
+
/**
|
|
49
|
+
* Error to throw on del operations (for testing error handling)
|
|
50
|
+
*/
|
|
51
|
+
delError?: Error | null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* In-memory implementation of CacheProvider for testing.
|
|
58
|
+
*
|
|
59
|
+
* This provider stores all cache entries in memory, making it ideal for
|
|
60
|
+
* unit tests that need to verify cache operations without touching Redis or other backends.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* // In tests, substitute the real CacheProvider with MemoryCacheProvider
|
|
65
|
+
* const alepha = Alepha.create().with({
|
|
66
|
+
* provide: CacheProvider,
|
|
67
|
+
* use: MemoryCacheProvider,
|
|
68
|
+
* });
|
|
69
|
+
*
|
|
70
|
+
* // Run code that uses caching
|
|
71
|
+
* const service = alepha.inject(MyService);
|
|
72
|
+
* await service.fetchWithCache("key");
|
|
73
|
+
*
|
|
74
|
+
* // Verify cache behavior
|
|
75
|
+
* const cache = alepha.inject(MemoryCacheProvider);
|
|
76
|
+
* expect(cache.stats().misses).toBe(1);
|
|
77
|
+
* await service.fetchWithCache("key");
|
|
78
|
+
* expect(cache.stats().hits).toBe(1);
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
13
81
|
export class MemoryCacheProvider implements CacheProvider {
|
|
14
82
|
protected readonly dateTimeProvider = $inject(DateTimeProvider);
|
|
15
83
|
protected readonly log = $logger();
|
|
16
84
|
|
|
17
85
|
protected store: Record<CacheName, Record<CacheKey, CacheValue>> = {};
|
|
18
86
|
|
|
87
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
88
|
+
// Test tracking
|
|
89
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* All recorded get calls.
|
|
93
|
+
*/
|
|
94
|
+
public getCalls: MemoryCacheCall[] = [];
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* All recorded set calls.
|
|
98
|
+
*/
|
|
99
|
+
public setCalls: MemoryCacheSetCall[] = [];
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* All recorded del calls.
|
|
103
|
+
*/
|
|
104
|
+
public delCalls: MemoryCacheDelCall[] = [];
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Cache statistics.
|
|
108
|
+
*/
|
|
109
|
+
protected _stats: MemoryCacheStats = {
|
|
110
|
+
hits: 0,
|
|
111
|
+
misses: 0,
|
|
112
|
+
sets: 0,
|
|
113
|
+
deletes: 0,
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Error to throw on get (for testing error handling)
|
|
118
|
+
*/
|
|
119
|
+
public getError: Error | null = null;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Error to throw on set (for testing error handling)
|
|
123
|
+
*/
|
|
124
|
+
public setError: Error | null = null;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Error to throw on del (for testing error handling)
|
|
128
|
+
*/
|
|
129
|
+
public delError: Error | null = null;
|
|
130
|
+
|
|
131
|
+
constructor(options: MemoryCacheProviderOptions = {}) {
|
|
132
|
+
this.getError = options.getError ?? null;
|
|
133
|
+
this.setError = options.setError ?? null;
|
|
134
|
+
this.delError = options.delError ?? null;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
138
|
+
// CacheProvider implementation
|
|
139
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
140
|
+
|
|
19
141
|
public async get(name: string, key: string): Promise<Uint8Array | undefined> {
|
|
20
|
-
|
|
142
|
+
this.getCalls.push({ name, key, timestamp: Date.now() });
|
|
143
|
+
|
|
144
|
+
if (this.getError) {
|
|
145
|
+
throw this.getError;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const data = this.store[name]?.[key]?.data;
|
|
149
|
+
|
|
150
|
+
if (data !== undefined) {
|
|
151
|
+
this._stats.hits++;
|
|
152
|
+
} else {
|
|
153
|
+
this._stats.misses++;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return data;
|
|
21
157
|
}
|
|
22
158
|
|
|
23
159
|
public async set(
|
|
@@ -26,6 +162,13 @@ export class MemoryCacheProvider implements CacheProvider {
|
|
|
26
162
|
value: Uint8Array,
|
|
27
163
|
ttl?: number,
|
|
28
164
|
): Promise<Uint8Array> {
|
|
165
|
+
this.setCalls.push({ name, key, value, ttl, timestamp: Date.now() });
|
|
166
|
+
this._stats.sets++;
|
|
167
|
+
|
|
168
|
+
if (this.setError) {
|
|
169
|
+
throw this.setError;
|
|
170
|
+
}
|
|
171
|
+
|
|
29
172
|
if (this.store[name] == null) {
|
|
30
173
|
this.store[name] = {};
|
|
31
174
|
}
|
|
@@ -52,6 +195,13 @@ export class MemoryCacheProvider implements CacheProvider {
|
|
|
52
195
|
}
|
|
53
196
|
|
|
54
197
|
public async del(name: string, ...keys: string[]): Promise<void> {
|
|
198
|
+
this.delCalls.push({ name, keys, timestamp: Date.now() });
|
|
199
|
+
this._stats.deletes++;
|
|
200
|
+
|
|
201
|
+
if (this.delError) {
|
|
202
|
+
throw this.delError;
|
|
203
|
+
}
|
|
204
|
+
|
|
55
205
|
// delete all keys in name
|
|
56
206
|
if (keys.length === 0) {
|
|
57
207
|
this.log.debug(`Deleting all cache for name`, { name });
|
|
@@ -116,4 +266,153 @@ export class MemoryCacheProvider implements CacheProvider {
|
|
|
116
266
|
|
|
117
267
|
this.store = {};
|
|
118
268
|
}
|
|
269
|
+
|
|
270
|
+
public async incr(
|
|
271
|
+
name: string,
|
|
272
|
+
key: string,
|
|
273
|
+
amount: number,
|
|
274
|
+
): Promise<number> {
|
|
275
|
+
if (this.store[name] == null) {
|
|
276
|
+
this.store[name] = {};
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const existing = this.store[name][key]?.data;
|
|
280
|
+
let current = 0;
|
|
281
|
+
|
|
282
|
+
if (existing) {
|
|
283
|
+
const str = new TextDecoder().decode(existing);
|
|
284
|
+
current = Number.parseInt(str, 10) || 0;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const newValue = current + amount;
|
|
288
|
+
this.store[name][key] ??= {};
|
|
289
|
+
this.store[name][key].data = new TextEncoder().encode(String(newValue));
|
|
290
|
+
|
|
291
|
+
return newValue;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
295
|
+
// Test utilities
|
|
296
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Get cache statistics (hits, misses, sets, deletes).
|
|
300
|
+
*
|
|
301
|
+
* @example
|
|
302
|
+
* ```typescript
|
|
303
|
+
* expect(cache.stats().hits).toBe(1);
|
|
304
|
+
* expect(cache.stats().misses).toBe(0);
|
|
305
|
+
* ```
|
|
306
|
+
*/
|
|
307
|
+
public stats(): MemoryCacheStats {
|
|
308
|
+
return { ...this._stats };
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Check if a key was set during the test.
|
|
313
|
+
*
|
|
314
|
+
* @example
|
|
315
|
+
* ```typescript
|
|
316
|
+
* expect(cache.wasSet("my-cache", "user:123")).toBe(true);
|
|
317
|
+
* ```
|
|
318
|
+
*/
|
|
319
|
+
public wasSet(name: string, key?: string): boolean {
|
|
320
|
+
if (key === undefined) {
|
|
321
|
+
return this.setCalls.some((call) => call.name === name);
|
|
322
|
+
}
|
|
323
|
+
return this.setCalls.some((call) => call.name === name && call.key === key);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Check if a key was retrieved during the test.
|
|
328
|
+
*
|
|
329
|
+
* @example
|
|
330
|
+
* ```typescript
|
|
331
|
+
* expect(cache.wasGet("my-cache", "user:123")).toBe(true);
|
|
332
|
+
* ```
|
|
333
|
+
*/
|
|
334
|
+
public wasGet(name: string, key?: string): boolean {
|
|
335
|
+
if (key === undefined) {
|
|
336
|
+
return this.getCalls.some((call) => call.name === name);
|
|
337
|
+
}
|
|
338
|
+
return this.getCalls.some((call) => call.name === name && call.key === key);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Check if a key was deleted during the test.
|
|
343
|
+
*
|
|
344
|
+
* @example
|
|
345
|
+
* ```typescript
|
|
346
|
+
* expect(cache.wasDeleted("my-cache", "user:123")).toBe(true);
|
|
347
|
+
* ```
|
|
348
|
+
*/
|
|
349
|
+
public wasDeleted(name: string, key?: string): boolean {
|
|
350
|
+
if (key === undefined) {
|
|
351
|
+
return this.delCalls.some((call) => call.name === name);
|
|
352
|
+
}
|
|
353
|
+
return this.delCalls.some(
|
|
354
|
+
(call) => call.name === name && call.keys.includes(key),
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Get the number of cached entries for a specific cache name.
|
|
360
|
+
*
|
|
361
|
+
* @example
|
|
362
|
+
* ```typescript
|
|
363
|
+
* expect(cache.size("my-cache")).toBe(5);
|
|
364
|
+
* ```
|
|
365
|
+
*/
|
|
366
|
+
public size(name?: string): number {
|
|
367
|
+
if (name === undefined) {
|
|
368
|
+
return Object.values(this.store).reduce(
|
|
369
|
+
(total, entries) => total + Object.keys(entries).length,
|
|
370
|
+
0,
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
return Object.keys(this.store[name] ?? {}).length;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Get all cache names.
|
|
378
|
+
*
|
|
379
|
+
* @example
|
|
380
|
+
* ```typescript
|
|
381
|
+
* expect(cache.names()).toContain("my-cache");
|
|
382
|
+
* ```
|
|
383
|
+
*/
|
|
384
|
+
public names(): string[] {
|
|
385
|
+
return Object.keys(this.store);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Reset all in-memory state (useful between tests).
|
|
390
|
+
*
|
|
391
|
+
* @example
|
|
392
|
+
* ```typescript
|
|
393
|
+
* beforeEach(() => {
|
|
394
|
+
* cache.reset();
|
|
395
|
+
* });
|
|
396
|
+
* ```
|
|
397
|
+
*/
|
|
398
|
+
public reset(): void {
|
|
399
|
+
// Clear all timeouts
|
|
400
|
+
for (const name of Object.keys(this.store)) {
|
|
401
|
+
for (const key of Object.keys(this.store[name])) {
|
|
402
|
+
const timeout = this.store[name][key]?.timeout;
|
|
403
|
+
if (timeout) {
|
|
404
|
+
this.dateTimeProvider.clearTimeout(timeout);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
this.store = {};
|
|
410
|
+
this.getCalls = [];
|
|
411
|
+
this.setCalls = [];
|
|
412
|
+
this.delCalls = [];
|
|
413
|
+
this._stats = { hits: 0, misses: 0, sets: 0, deletes: 0 };
|
|
414
|
+
this.getError = null;
|
|
415
|
+
this.setError = null;
|
|
416
|
+
this.delError = null;
|
|
417
|
+
}
|
|
119
418
|
}
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
testCacheBasic,
|
|
5
5
|
testCacheClear,
|
|
6
6
|
testCacheDisabled,
|
|
7
|
+
testCacheIncr,
|
|
7
8
|
testCacheInvalidateAll,
|
|
8
9
|
testCacheInvalidateByArgs,
|
|
9
10
|
testCacheInvalidateByKey,
|
|
@@ -67,4 +68,8 @@ describe("$cache - redis", () => {
|
|
|
67
68
|
it("should clear provider cache", async () => {
|
|
68
69
|
await testCacheProviderClear(env(), provider);
|
|
69
70
|
});
|
|
71
|
+
|
|
72
|
+
it("should increment values atomically", async () => {
|
|
73
|
+
await testCacheIncr(env(), provider);
|
|
74
|
+
});
|
|
70
75
|
});
|
|
@@ -99,6 +99,15 @@ export class RedisCacheProvider implements CacheProvider {
|
|
|
99
99
|
await this.redisProvider.del(keys);
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
public async incr(
|
|
103
|
+
name: string,
|
|
104
|
+
key: string,
|
|
105
|
+
amount: number,
|
|
106
|
+
): Promise<number> {
|
|
107
|
+
const keyWithPrefix = this.prefix(name, key);
|
|
108
|
+
return this.redisProvider.incr(keyWithPrefix, amount);
|
|
109
|
+
}
|
|
110
|
+
|
|
102
111
|
protected prefix(...path: string[]): string {
|
|
103
112
|
const parts = ["cache", ...path];
|
|
104
113
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { $hook, $inject, $module, Alepha } from "alepha";
|
|
2
|
-
import { FileSystemProvider } from "alepha/
|
|
2
|
+
import { FileSystemProvider } from "alepha/system";
|
|
3
3
|
import { BuildCommand } from "../commands/build.ts";
|
|
4
4
|
import { CleanCommand } from "../commands/clean.ts";
|
|
5
5
|
import { DbCommand } from "../commands/db.ts";
|
|
@@ -17,19 +17,6 @@ import { AppEntryProvider } from "../providers/AppEntryProvider.ts";
|
|
|
17
17
|
|
|
18
18
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
19
19
|
|
|
20
|
-
/**
|
|
21
|
-
* Register `tsx` when running in Node.js, ignore for Bun.
|
|
22
|
-
*
|
|
23
|
-
* It's required to have a full TypeScript support. (mostly .tsx files)
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
if (typeof Bun === "undefined") {
|
|
27
|
-
const { register } = await import("tsx/esm/api");
|
|
28
|
-
register();
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// ---------------------------------------------------------------------------------------------------------------------
|
|
32
|
-
|
|
33
20
|
/**
|
|
34
21
|
* Allow to extend Alepha CLI via `alepha.config.ts` file located in the project root.
|
|
35
22
|
*/
|
|
@@ -3,7 +3,7 @@ import * as os from "node:os";
|
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { $inject, AlephaError } from "alepha";
|
|
5
5
|
import { $command } from "alepha/command";
|
|
6
|
-
import { FileSystemProvider } from "alepha/
|
|
6
|
+
import { FileSystemProvider } from "alepha/system";
|
|
7
7
|
import type { InlineConfig } from "tsdown";
|
|
8
8
|
|
|
9
9
|
interface Module {
|
|
@@ -11,6 +11,7 @@ interface Module {
|
|
|
11
11
|
dependencies: string[];
|
|
12
12
|
native?: boolean;
|
|
13
13
|
browser?: boolean;
|
|
14
|
+
workerd?: boolean;
|
|
14
15
|
bun?: boolean;
|
|
15
16
|
node?: boolean;
|
|
16
17
|
}
|
|
@@ -53,6 +54,10 @@ export class AlephaPackageBuilderCli {
|
|
|
53
54
|
`./src/${item.name}/index.browser.ts`;
|
|
54
55
|
}
|
|
55
56
|
|
|
57
|
+
if (item.workerd) {
|
|
58
|
+
pkgData.exports[path].workerd = `./src/${item.name}/index.workerd.ts`;
|
|
59
|
+
}
|
|
60
|
+
|
|
56
61
|
if (item.browser) {
|
|
57
62
|
pkgData.exports[path].browser = `./src/${item.name}/index.browser.ts`;
|
|
58
63
|
}
|
|
@@ -321,6 +326,9 @@ export async function analyzeModules(
|
|
|
321
326
|
);
|
|
322
327
|
const hasBun = await fileExists(join(modulePath, "index.bun.ts"));
|
|
323
328
|
const hasNode = await fileExists(join(modulePath, "index.node.ts"));
|
|
329
|
+
const hasEdge = await fileExists(
|
|
330
|
+
join(modulePath, "index.workerd.ts"),
|
|
331
|
+
);
|
|
324
332
|
|
|
325
333
|
// Get all .ts/.tsx files in this module
|
|
326
334
|
const files = await getAllFiles(modulePath);
|
|
@@ -353,6 +361,7 @@ export async function analyzeModules(
|
|
|
353
361
|
};
|
|
354
362
|
|
|
355
363
|
if (hasNative) module.native = true;
|
|
364
|
+
if (hasEdge) module.workerd = true;
|
|
356
365
|
if (hasBrowser) module.browser = true;
|
|
357
366
|
if (hasBun) module.bun = true;
|
|
358
367
|
if (hasNode) module.node = true;
|