alepha 0.21.2 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -1
- package/dist/api/audits/index.browser.js.map +1 -1
- package/dist/api/audits/index.d.ts +393 -403
- package/dist/api/audits/index.d.ts.map +1 -1
- package/dist/api/audits/index.js +25 -56
- package/dist/api/audits/index.js.map +1 -1
- package/dist/api/files/index.browser.js +31 -1
- package/dist/api/files/index.browser.js.map +1 -1
- package/dist/api/files/index.d.ts +313 -208
- package/dist/api/files/index.d.ts.map +1 -1
- package/dist/api/files/index.js +152 -42
- package/dist/api/files/index.js.map +1 -1
- package/dist/api/jobs/index.browser.js +2 -2
- package/dist/api/jobs/index.browser.js.map +1 -1
- package/dist/api/jobs/index.d.ts +289 -292
- package/dist/api/jobs/index.d.ts.map +1 -1
- package/dist/api/jobs/index.js +39 -33
- package/dist/api/jobs/index.js.map +1 -1
- package/dist/api/keys/index.d.ts +211 -216
- package/dist/api/keys/index.d.ts.map +1 -1
- package/dist/api/keys/index.js.map +1 -1
- package/dist/api/notifications/index.browser.js.map +1 -1
- package/dist/api/notifications/index.d.ts +188 -195
- package/dist/api/notifications/index.d.ts.map +1 -1
- package/dist/api/notifications/index.js.map +1 -1
- package/dist/api/oauth/index.d.ts +71 -76
- package/dist/api/oauth/index.d.ts.map +1 -1
- package/dist/api/oauth/index.js.map +1 -1
- package/dist/api/organizations/index.browser.js.map +1 -1
- package/dist/api/organizations/index.d.ts +104 -109
- package/dist/api/organizations/index.d.ts.map +1 -1
- package/dist/api/organizations/index.js.map +1 -1
- package/dist/api/parameters/index.browser.js +43 -16
- package/dist/api/parameters/index.browser.js.map +1 -1
- package/dist/api/parameters/index.d.ts +488 -344
- package/dist/api/parameters/index.d.ts.map +1 -1
- package/dist/api/parameters/index.js +175 -35
- package/dist/api/parameters/index.js.map +1 -1
- package/dist/api/payments/index.d.ts +396 -402
- package/dist/api/payments/index.d.ts.map +1 -1
- package/dist/api/payments/index.js.map +1 -1
- package/dist/api/subscriptions/index.d.ts +644 -652
- package/dist/api/subscriptions/index.d.ts.map +1 -1
- package/dist/api/subscriptions/index.js +1 -1
- package/dist/api/subscriptions/index.js.map +1 -1
- package/dist/api/users/index.browser.js +7 -0
- package/dist/api/users/index.browser.js.map +1 -1
- package/dist/api/users/index.d.ts +1073 -1006
- package/dist/api/users/index.d.ts.map +1 -1
- package/dist/api/users/index.js +283 -61
- package/dist/api/users/index.js.map +1 -1
- package/dist/api/verifications/index.browser.js.map +1 -1
- package/dist/api/verifications/index.d.ts +134 -140
- package/dist/api/verifications/index.d.ts.map +1 -1
- package/dist/api/verifications/index.js.map +1 -1
- package/dist/background/index.d.ts +95 -0
- package/dist/background/index.d.ts.map +1 -0
- package/dist/background/index.js +121 -0
- package/dist/background/index.js.map +1 -0
- package/dist/background/index.workerd.js +110 -0
- package/dist/background/index.workerd.js.map +1 -0
- package/dist/batch/index.d.ts +5 -7
- package/dist/batch/index.d.ts.map +1 -1
- package/dist/batch/index.js.map +1 -1
- package/dist/bin/index.js.map +1 -1
- package/dist/bucket/index.d.ts +76 -54
- package/dist/bucket/index.d.ts.map +1 -1
- package/dist/bucket/index.js +58 -11
- package/dist/bucket/index.js.map +1 -1
- package/dist/bucket/index.workerd.js +200 -5
- package/dist/bucket/index.workerd.js.map +1 -1
- package/dist/cache/core/index.d.ts +7 -10
- package/dist/cache/core/index.d.ts.map +1 -1
- package/dist/cache/core/index.js.map +1 -1
- package/dist/cache/core/index.workerd.js.map +1 -1
- package/dist/cache/database/index.d.ts +22 -26
- package/dist/cache/database/index.d.ts.map +1 -1
- package/dist/cache/database/index.js.map +1 -1
- package/dist/cache/redis/index.d.ts +4 -7
- package/dist/cache/redis/index.d.ts.map +1 -1
- package/dist/cache/redis/index.js.map +1 -1
- package/dist/captcha/index.d.ts +3 -6
- package/dist/captcha/index.d.ts.map +1 -1
- package/dist/captcha/index.js.map +1 -1
- package/dist/cli/config/index.d.ts.map +1 -1
- package/dist/cli/config/index.js.map +1 -1
- package/dist/cli/core/index.d.ts +417 -214
- package/dist/cli/core/index.d.ts.map +1 -1
- package/dist/cli/core/index.js +325 -563
- package/dist/cli/core/index.js.map +1 -1
- package/dist/cli/devtools/index.d.ts +3 -5
- package/dist/cli/devtools/index.d.ts.map +1 -1
- package/dist/cli/devtools/index.js.map +1 -1
- package/dist/cli/i18n/index.d.ts +8 -12
- package/dist/cli/i18n/index.d.ts.map +1 -1
- package/dist/cli/i18n/index.js.map +1 -1
- package/dist/cli/platform/index.d.ts +126 -1342
- package/dist/cli/platform/index.d.ts.map +1 -1
- package/dist/cli/platform/index.js +136 -2374
- package/dist/cli/platform/index.js.map +1 -1
- package/dist/cli/platform-lib/index.d.ts +1446 -0
- package/dist/cli/platform-lib/index.d.ts.map +1 -0
- package/dist/cli/platform-lib/index.js +2597 -0
- package/dist/cli/platform-lib/index.js.map +1 -0
- package/dist/cli/vendor/index.d.ts +17 -21
- package/dist/cli/vendor/index.d.ts.map +1 -1
- package/dist/cli/vendor/index.js.map +1 -1
- package/dist/command/index.d.ts +21 -20
- package/dist/command/index.d.ts.map +1 -1
- package/dist/command/index.js +39 -10
- package/dist/command/index.js.map +1 -1
- package/dist/{containers → container}/core/index.d.ts +13 -15
- package/dist/container/core/index.d.ts.map +1 -0
- package/dist/{containers → container}/core/index.js +23 -14
- package/dist/container/core/index.js.map +1 -0
- package/dist/{containers → container}/core/index.workerd.js +37 -22
- package/dist/container/core/index.workerd.js.map +1 -0
- package/dist/core/index.browser.js +27 -1
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +48 -24
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +27 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js +27 -1
- package/dist/core/index.native.js.map +1 -1
- package/dist/core/index.workerd.js +27 -1
- package/dist/core/index.workerd.js.map +1 -1
- package/dist/crypto/index.browser.js.map +1 -1
- package/dist/crypto/index.d.ts +5 -8
- package/dist/crypto/index.d.ts.map +1 -1
- package/dist/crypto/index.js.map +1 -1
- package/dist/datetime/index.d.ts +3 -4
- package/dist/datetime/index.d.ts.map +1 -1
- package/dist/datetime/index.js.map +1 -1
- package/dist/email/brevo/index.d.ts +2 -4
- package/dist/email/brevo/index.d.ts.map +1 -1
- package/dist/email/brevo/index.js.map +1 -1
- package/dist/email/cloudflare/index.d.ts +20 -7
- package/dist/email/cloudflare/index.d.ts.map +1 -1
- package/dist/email/cloudflare/index.js +46 -9
- package/dist/email/cloudflare/index.js.map +1 -1
- package/dist/email/core/index.d.ts +6 -9
- package/dist/email/core/index.d.ts.map +1 -1
- package/dist/email/core/index.js.map +1 -1
- package/dist/email/core/index.workerd.js.map +1 -1
- package/dist/email/smtp/index.d.ts +10 -13
- package/dist/email/smtp/index.d.ts.map +1 -1
- package/dist/email/smtp/index.js +107 -32
- package/dist/email/smtp/index.js.map +1 -1
- package/dist/fake/index.d.ts +1 -2
- package/dist/fake/index.d.ts.map +1 -1
- package/dist/fake/index.js.map +1 -1
- package/dist/lock/core/index.d.ts +9 -14
- package/dist/lock/core/index.d.ts.map +1 -1
- package/dist/lock/core/index.js.map +1 -1
- package/dist/lock/redis/index.d.ts +2 -4
- package/dist/lock/redis/index.d.ts.map +1 -1
- package/dist/lock/redis/index.js.map +1 -1
- package/dist/logger/index.d.ts +105 -76
- package/dist/logger/index.d.ts.map +1 -1
- package/dist/logger/index.js +196 -174
- package/dist/logger/index.js.map +1 -1
- package/dist/mcp/index.d.ts +16 -20
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/orm/core/index.browser.js.map +1 -1
- package/dist/orm/core/index.bun.js +19 -1
- package/dist/orm/core/index.bun.js.map +1 -1
- package/dist/orm/core/index.d.ts +76 -62
- package/dist/orm/core/index.d.ts.map +1 -1
- package/dist/orm/core/index.js +20 -2
- package/dist/orm/core/index.js.map +1 -1
- package/dist/orm/postgres/index.bun.js.map +1 -1
- package/dist/orm/postgres/index.d.ts +28 -20
- package/dist/orm/postgres/index.d.ts.map +1 -1
- package/dist/orm/postgres/index.js.map +1 -1
- package/dist/queue/core/index.d.ts +12 -15
- package/dist/queue/core/index.d.ts.map +1 -1
- package/dist/queue/core/index.js.map +1 -1
- package/dist/queue/core/index.workerd.js.map +1 -1
- package/dist/queue/redis/index.d.ts +3 -5
- package/dist/queue/redis/index.d.ts.map +1 -1
- package/dist/queue/redis/index.js.map +1 -1
- package/dist/react/auth/index.browser.js +9 -2
- package/dist/react/auth/index.browser.js.map +1 -1
- package/dist/react/auth/index.d.ts +14 -9
- package/dist/react/auth/index.d.ts.map +1 -1
- package/dist/react/auth/index.js +9 -2
- package/dist/react/auth/index.js.map +1 -1
- package/dist/react/core/index.d.ts +7 -8
- package/dist/react/core/index.d.ts.map +1 -1
- package/dist/react/core/index.js +6 -3
- package/dist/react/core/index.js.map +1 -1
- package/dist/react/form/index.d.ts +2 -4
- package/dist/react/form/index.d.ts.map +1 -1
- package/dist/react/form/index.js.map +1 -1
- package/dist/react/head/index.browser.js.map +1 -1
- package/dist/react/head/index.d.ts +2 -4
- package/dist/react/head/index.d.ts.map +1 -1
- package/dist/react/head/index.js.map +1 -1
- package/dist/react/i18n/index.d.ts +47 -11
- package/dist/react/i18n/index.d.ts.map +1 -1
- package/dist/react/i18n/index.js +33 -1
- package/dist/react/i18n/index.js.map +1 -1
- package/dist/react/intro/index.d.ts +1 -2
- package/dist/react/intro/index.d.ts.map +1 -1
- package/dist/react/intro/index.js +2 -2
- package/dist/react/intro/index.js.map +1 -1
- package/dist/react/router/index.browser.js +65 -19
- package/dist/react/router/index.browser.js.map +1 -1
- package/dist/react/router/index.d.ts +327 -222
- package/dist/react/router/index.d.ts.map +1 -1
- package/dist/react/router/index.js +65 -29
- package/dist/react/router/index.js.map +1 -1
- package/dist/react/testing/index.d.ts +1 -2
- package/dist/react/testing/index.d.ts.map +1 -1
- package/dist/react/testing/index.js +16 -17
- package/dist/react/testing/index.js.map +1 -1
- package/dist/react/ui/index.d.ts +20 -25
- package/dist/react/ui/index.d.ts.map +1 -1
- package/dist/react/ui/index.js.map +1 -1
- package/dist/redis/index.bun.js.map +1 -1
- package/dist/redis/index.d.ts +17 -19
- package/dist/redis/index.d.ts.map +1 -1
- package/dist/redis/index.js.map +1 -1
- package/dist/retry/index.d.ts +2 -4
- package/dist/retry/index.d.ts.map +1 -1
- package/dist/retry/index.js.map +1 -1
- package/dist/router/index.d.ts.map +1 -1
- package/dist/router/index.js.map +1 -1
- package/dist/scheduler/index.d.ts +10 -13
- package/dist/scheduler/index.d.ts.map +1 -1
- package/dist/scheduler/index.js.map +1 -1
- package/dist/scheduler/index.workerd.js.map +1 -1
- package/dist/security/index.browser.js.map +1 -1
- package/dist/security/index.d.ts +45 -48
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js.map +1 -1
- package/dist/server/auth/index.browser.js.map +1 -1
- package/dist/server/auth/index.d.ts +167 -172
- package/dist/server/auth/index.d.ts.map +1 -1
- package/dist/server/auth/index.js +4 -8
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/cookies/index.browser.js.map +1 -1
- package/dist/server/cookies/index.d.ts +5 -7
- package/dist/server/cookies/index.d.ts.map +1 -1
- package/dist/server/cookies/index.js.map +1 -1
- package/dist/server/core/index.browser.js.map +1 -1
- package/dist/server/core/index.d.ts +88 -73
- package/dist/server/core/index.d.ts.map +1 -1
- package/dist/server/core/index.js +19 -0
- package/dist/server/core/index.js.map +1 -1
- package/dist/server/cors/index.d.ts +11 -14
- package/dist/server/cors/index.d.ts.map +1 -1
- package/dist/server/cors/index.js.map +1 -1
- package/dist/server/etag/index.d.ts +6 -9
- package/dist/server/etag/index.d.ts.map +1 -1
- package/dist/server/etag/index.js.map +1 -1
- package/dist/server/health/index.d.ts +18 -21
- package/dist/server/health/index.d.ts.map +1 -1
- package/dist/server/health/index.js.map +1 -1
- package/dist/server/links/index.browser.js +2 -0
- package/dist/server/links/index.browser.js.map +1 -1
- package/dist/server/links/index.d.ts +63 -67
- package/dist/server/links/index.d.ts.map +1 -1
- package/dist/server/links/index.js +2 -0
- package/dist/server/links/index.js.map +1 -1
- package/dist/server/metrics/index.d.ts +5 -7
- package/dist/server/metrics/index.d.ts.map +1 -1
- package/dist/server/metrics/index.js.map +1 -1
- package/dist/server/proxy/index.d.ts +3 -5
- package/dist/server/proxy/index.d.ts.map +1 -1
- package/dist/server/proxy/index.js.map +1 -1
- package/dist/server/rate-limit/index.d.ts +10 -13
- package/dist/server/rate-limit/index.d.ts.map +1 -1
- package/dist/server/rate-limit/index.js.map +1 -1
- package/dist/server/static/index.d.ts +3 -5
- package/dist/server/static/index.d.ts.map +1 -1
- package/dist/server/static/index.js.map +1 -1
- package/dist/server/swagger/index.d.ts +5 -8
- package/dist/server/swagger/index.d.ts.map +1 -1
- package/dist/server/swagger/index.js.map +1 -1
- package/dist/sms/index.d.ts +3 -5
- package/dist/sms/index.d.ts.map +1 -1
- package/dist/sms/index.js.map +1 -1
- package/dist/system/index.browser.js.map +1 -1
- package/dist/system/index.d.ts +2 -4
- package/dist/system/index.d.ts.map +1 -1
- package/dist/system/index.js.map +1 -1
- package/dist/system/index.workerd.js.map +1 -1
- package/dist/topic/core/index.d.ts +4 -6
- package/dist/topic/core/index.d.ts.map +1 -1
- package/dist/topic/core/index.js.map +1 -1
- package/dist/topic/redis/index.d.ts +5 -8
- package/dist/topic/redis/index.d.ts.map +1 -1
- package/dist/topic/redis/index.js.map +1 -1
- package/package.json +45 -22
- package/src/api/audits/__tests__/AuditService.spec.ts +18 -110
- package/src/api/audits/controllers/AdminAuditController.ts +14 -0
- package/src/api/audits/services/AuditService.ts +21 -88
- package/src/api/files/__tests__/FileService.spec.ts +207 -2
- package/src/api/files/index.ts +3 -0
- package/src/api/files/schemas/fileCreatorSummarySchema.ts +22 -0
- package/src/api/files/schemas/fileResourceSchema.ts +10 -1
- package/src/api/files/services/FileService.ts +170 -72
- package/src/api/jobs/__tests__/$job.spec.ts +24 -1
- package/src/api/jobs/index.ts +4 -3
- package/src/api/jobs/primitives/$job.ts +7 -3
- package/src/api/jobs/providers/DirectJobDispatcher.ts +17 -36
- package/src/api/jobs/providers/JobProvider.ts +53 -24
- package/src/api/jobs/schemas/jobConfigAtom.ts +1 -1
- package/src/api/jobs/schemas/jobExecutionResourceSchema.ts +4 -1
- package/src/api/keys/schemas/adminApiKeyResourceSchema.ts +3 -1
- package/src/api/parameters/__tests__/$parameter.spec.ts +19 -2
- package/src/api/parameters/audits/ParameterAudits.ts +17 -0
- package/src/api/parameters/controllers/AdminParameterController.ts +95 -19
- package/src/api/parameters/index.ts +3 -0
- package/src/api/parameters/schemas/activateParameterBodySchema.ts +3 -3
- package/src/api/parameters/schemas/createParameterVersionBodySchema.ts +3 -2
- package/src/api/parameters/schemas/parameterCreatorSummarySchema.ts +25 -0
- package/src/api/parameters/schemas/parameterResponseSchema.ts +5 -0
- package/src/api/parameters/schemas/rollbackParameterBodySchema.ts +4 -2
- package/src/api/parameters/services/ParameterProvider.ts +69 -6
- package/src/api/subscriptions/jobs/SubscriptionJobs.ts +1 -1
- package/src/api/users/__tests__/AdminSessionController.spec.ts +37 -0
- package/src/api/users/audits/SessionAudits.ts +33 -0
- package/src/api/users/audits/UserAudits.ts +19 -43
- package/src/api/users/controllers/AdminUserController.ts +66 -1
- package/src/api/users/entities/sessions.ts +6 -0
- package/src/api/users/entities/users.ts +2 -0
- package/src/api/users/index.ts +9 -1
- package/src/api/users/primitives/$realm.ts +3 -0
- package/src/api/users/schemas/sessionResourceSchema.ts +16 -0
- package/src/api/users/schemas/updateUserSchema.ts +1 -8
- package/src/api/users/schemas/userQuerySchema.ts +7 -0
- package/src/api/users/services/CredentialService.ts +15 -6
- package/src/api/users/services/IdentityService.ts +2 -1
- package/src/api/users/services/RegistrationService.ts +2 -1
- package/src/api/users/services/SessionCrudService.ts +19 -2
- package/src/api/users/services/SessionService.ts +39 -19
- package/src/api/users/services/UserService.ts +106 -8
- package/src/background/__tests__/BackgroundTaskProvider.spec.ts +96 -0
- package/src/background/index.ts +37 -0
- package/src/background/index.workerd.ts +28 -0
- package/src/background/providers/BackgroundTaskProvider.ts +70 -0
- package/src/background/providers/WorkerdBackgroundTaskProvider.ts +43 -0
- package/src/bucket/__tests__/$bucket.spec.ts +18 -0
- package/src/bucket/__tests__/LocalFileStorageProvider.spec.ts +5 -0
- package/src/bucket/__tests__/MemoryFileStorageProvider.spec.ts +5 -0
- package/src/bucket/__tests__/NodeS3BucketProvider.spec.ts +23 -4
- package/src/bucket/__tests__/shared.ts +30 -0
- package/src/bucket/index.ts +5 -5
- package/src/bucket/index.workerd.ts +11 -4
- package/src/bucket/primitives/$bucket.ts +27 -0
- package/src/bucket/providers/FileStorageProvider.ts +13 -0
- package/src/bucket/providers/LocalFileStorageProvider.ts +17 -1
- package/src/bucket/providers/MemoryFileStorageProvider.ts +7 -0
- package/src/bucket/providers/{CloudflareR2Provider.ts → R2FileStorageProvider.ts} +10 -1
- package/src/bucket/providers/{NodeS3BucketProvider.ts → S3FileStorageProvider.ts} +27 -5
- package/src/cli/core/__tests__/BuildDockerTask.spec.ts +25 -1
- package/src/cli/core/__tests__/init.spec.ts +0 -219
- package/src/cli/core/commands/__tests__/BuildCommand.spec.ts +43 -0
- package/src/cli/core/commands/build.ts +108 -30
- package/src/cli/core/commands/init.ts +0 -12
- package/src/cli/core/commands/pack.ts +133 -0
- package/src/cli/core/index.ts +3 -0
- package/src/cli/core/providers/ViteDevServerProvider.ts +40 -16
- package/src/cli/core/services/PackageManagerUtils.ts +0 -16
- package/src/cli/core/services/ProjectScaffolder.ts +29 -291
- package/src/cli/core/tasks/BuildCloudflareTask.ts +353 -47
- package/src/cli/core/tasks/BuildDockerTask.ts +33 -3
- package/src/cli/core/tasks/BuildTask.ts +34 -0
- package/src/cli/core/templates/apiIndexTs.ts +1 -22
- package/src/cli/core/templates/mainCss.ts +0 -1
- package/src/cli/core/templates/webAppRouterTs.ts +0 -99
- package/src/cli/core/templates/webIndexTs.ts +1 -22
- package/src/cli/platform/__tests__/SecretsCommand.spec.ts +5 -3
- package/src/cli/platform/commands/SecretsCommand.ts +8 -6
- package/src/cli/platform/commands/platform.ts +192 -46
- package/src/cli/platform/index.ts +12 -52
- package/src/cli/{platform → platform-lib}/__tests__/CloudflareAdapter.spec.ts +426 -169
- package/src/cli/{platform → platform-lib}/__tests__/NamingService.spec.ts +91 -4
- package/src/cli/{platform → platform-lib}/__tests__/VercelAdapter.spec.ts +56 -85
- package/src/cli/{platform → platform-lib}/adapters/CloudflareAdapter.ts +402 -165
- package/src/cli/{platform → platform-lib}/adapters/PlatformAdapter.ts +62 -35
- package/src/cli/{platform → platform-lib}/adapters/VercelAdapter.ts +6 -10
- package/src/cli/{platform → platform-lib}/atoms/platformOptions.ts +34 -1
- package/src/cli/platform-lib/index.ts +67 -0
- package/src/cli/platform-lib/services/NamingService.ts +136 -0
- package/src/cli/{platform → platform-lib}/services/PlatformInspector.ts +60 -13
- package/src/cli/{platform → platform-lib}/services/PlatformOrchestrator.ts +54 -43
- package/src/cli/{platform → platform-lib}/services/WranglerApi.ts +4 -2
- package/src/command/__tests__/Runner.spec.ts +20 -0
- package/src/command/helpers/EnvUtils.ts +19 -3
- package/src/command/helpers/Runner.ts +12 -2
- package/src/command/providers/CliProvider.ts +34 -1
- package/src/{containers → container}/core/__tests__/$container.spec.ts +5 -5
- package/src/{containers → container}/core/index.ts +4 -4
- package/src/{containers → container}/core/index.workerd.ts +19 -3
- package/src/{containers → container}/core/primitives/$container.ts +1 -1
- package/src/{containers → container}/core/providers/CloudflareContainerProvider.ts +17 -19
- package/src/{containers → container}/core/providers/ContainerProvider.ts +16 -2
- package/src/{containers → container}/core/providers/MockContainerProvider.ts +1 -1
- package/src/core/Alepha.ts +49 -1
- package/src/core/__tests__/$env.spec.ts +42 -0
- package/src/core/__tests__/dump.spec.ts +47 -0
- package/src/email/cloudflare/__tests__/CloudflareEmailProvider.spec.ts +42 -10
- package/src/email/cloudflare/index.ts +14 -5
- package/src/email/cloudflare/providers/CloudflareEmailProvider.ts +54 -9
- package/src/logger/__tests__/Logger.spec.ts +55 -0
- package/src/logger/index.ts +13 -0
- package/src/logger/services/Logger.ts +31 -1
- package/src/orm/__tests__/orm-showcase-tests.ts +27 -0
- package/src/orm/__tests__/orm-showcase.spec.ts +12 -0
- package/src/orm/core/interfaces/PgQuery.ts +4 -1
- package/src/orm/core/services/Repository.ts +27 -11
- package/src/react/auth/hooks/useAuth.ts +10 -5
- package/src/react/core/__tests__/useQuery.browser.spec.tsx +25 -0
- package/src/react/core/hooks/useAction.ts +14 -3
- package/src/react/core/hooks/useQuery.ts +24 -4
- package/src/react/i18n/components/Translate.tsx +47 -0
- package/src/react/i18n/index.ts +2 -0
- package/src/react/intro/components/GettingStartedAdminSlide.tsx +2 -2
- package/src/react/router/__tests__/$page.spec.tsx +3 -2
- package/src/react/router/__tests__/page-can.spec.ts +18 -13
- package/src/react/router/hooks/useQueryParams.ts +114 -14
- package/src/react/router/primitives/$page.ts +85 -4
- package/src/react/router/providers/ReactBrowserRouterProvider.ts +3 -7
- package/src/react/router/providers/ReactServerProvider.ts +4 -13
- package/src/react/ui/services/SchemaControl.ts +3 -4
- package/src/server/core/providers/ServerMultipartProvider.ts +19 -0
- package/src/server/links/providers/LinkProvider.ts +10 -0
- package/dist/containers/core/index.d.ts.map +0 -1
- package/dist/containers/core/index.js.map +0 -1
- package/dist/containers/core/index.workerd.js.map +0 -1
- package/src/cli/core/templates/componentsJsonTs.ts +0 -39
- package/src/cli/core/templates/saasAdminLayoutTsx.ts +0 -77
- package/src/cli/core/templates/saasAdminPagesTsx.ts +0 -26
- package/src/cli/core/templates/saasAuthLayoutTsx.ts +0 -22
- package/src/cli/core/templates/saasAuthPagesTsx.ts +0 -62
- package/src/cli/core/templates/saasRealmProviderTs.ts +0 -52
- package/src/cli/platform/services/NamingService.ts +0 -54
- /package/dist/orm/core/{chunk-o8xxKEmq.js → chunk-B4FMCO8f.js} +0 -0
- /package/dist/react/testing/{chunk-6Ep1yQYe.js → chunk-BpyX8vjI.js} +0 -0
- /package/src/cli/{platform → platform-lib}/__tests__/GitHubSecretStore.spec.ts +0 -0
- /package/src/cli/{platform → platform-lib}/__tests__/PlatformCacheProvider.spec.ts +0 -0
- /package/src/cli/{platform → platform-lib}/__tests__/PlatformInspector.spec.ts +0 -0
- /package/src/cli/{platform → platform-lib}/__tests__/PlatformOrchestrator.spec.ts +0 -0
- /package/src/cli/{platform → platform-lib}/__tests__/SecretFilterService.spec.ts +0 -0
- /package/src/cli/{platform → platform-lib}/__tests__/detectResources.spec.ts +0 -0
- /package/src/cli/{platform → platform-lib}/providers/GitHubSecretStore.ts +0 -0
- /package/src/cli/{platform → platform-lib}/providers/MemorySecretStore.ts +0 -0
- /package/src/cli/{platform → platform-lib}/providers/PlatformCacheProvider.ts +0 -0
- /package/src/cli/{platform → platform-lib}/providers/SecretStoreProvider.ts +0 -0
- /package/src/cli/{platform → platform-lib}/schemas/cloudflare.ts +0 -0
- /package/src/cli/{platform → platform-lib}/schemas/platform.ts +0 -0
- /package/src/cli/{platform → platform-lib}/schemas/vercel.ts +0 -0
- /package/src/cli/{platform → platform-lib}/services/CloudflareApi.ts +0 -0
- /package/src/cli/{platform → platform-lib}/services/SecretFilterService.ts +0 -0
- /package/src/cli/{platform → platform-lib}/services/VercelApi.ts +0 -0
- /package/src/cli/{platform → platform-lib}/services/VercelCli.ts +0 -0
- /package/src/{containers → container}/core/interfaces/ContainerOptions.ts +0 -0
- /package/src/{containers → container}/core/providers/NodeContainerProvider.ts +0 -0
package/dist/react/ui/index.d.ts
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import * as _$alepha from "alepha";
|
|
2
1
|
import { Static } from "alepha";
|
|
3
|
-
import * as _$alepha_react_head0 from "alepha/react/head";
|
|
4
|
-
import * as _$alepha_server_cookies0 from "alepha/server/cookies";
|
|
5
|
-
import * as _$typebox from "typebox";
|
|
6
2
|
import { FormModel } from "alepha/react/form";
|
|
7
3
|
|
|
8
4
|
//#region ../../src/react/ui/atoms/uiAtom.d.ts
|
|
@@ -12,11 +8,11 @@ import { FormModel } from "alepha/react/form";
|
|
|
12
8
|
* The atom is bound to a single `alepha-ui` cookie via {@link UiPersistence},
|
|
13
9
|
* so values survive page reloads and are available during SSR.
|
|
14
10
|
*/
|
|
15
|
-
declare const uiAtom:
|
|
16
|
-
/** Color mode preference. `"system"` follows the OS-level setting. */mode:
|
|
17
|
-
theme:
|
|
18
|
-
sidebar:
|
|
19
|
-
collapsed:
|
|
11
|
+
declare const uiAtom: import("alepha").Atom<import("typebox").TObject<{
|
|
12
|
+
/** Color mode preference. `"system"` follows the OS-level setting. */mode: import("typebox").TUnsafe<"light" | "dark" | "system">; /** Theme palette name. UI consumers map this to a CSS class on the root. */
|
|
13
|
+
theme: import("typebox").TString; /** Sidebar UI state. */
|
|
14
|
+
sidebar: import("typebox").TObject<{
|
|
15
|
+
collapsed: import("typebox").TBoolean;
|
|
20
16
|
}>;
|
|
21
17
|
}>, "alepha.react.ui">;
|
|
22
18
|
type UiState = Static<typeof uiAtom.schema>;
|
|
@@ -31,19 +27,19 @@ type UiState = Static<typeof uiAtom.schema>;
|
|
|
31
27
|
* Defaults to a single `"default"` entry so the registry stays usable when
|
|
32
28
|
* an app doesn't declare its own list.
|
|
33
29
|
*/
|
|
34
|
-
declare const uiThemeListAtom:
|
|
35
|
-
/** Stable id stored in `uiAtom.theme`. Mapped to a CSS class on `<html>`. */id:
|
|
36
|
-
label:
|
|
30
|
+
declare const uiThemeListAtom: import("alepha").Atom<import("typebox").TArray<import("typebox").TObject<{
|
|
31
|
+
/** Stable id stored in `uiAtom.theme`. Mapped to a CSS class on `<html>`. */id: import("typebox").TString; /** Human-readable label shown in the picker. */
|
|
32
|
+
label: import("typebox").TString;
|
|
37
33
|
/**
|
|
38
34
|
* Optional 4-color preview swatch in 2×2 order (TL, TR, BL, BR). Any
|
|
39
35
|
* CSS-valid color string.
|
|
40
36
|
*/
|
|
41
|
-
swatch:
|
|
37
|
+
swatch: import("typebox").TOptional<import("typebox").TArray<import("typebox").TString>>;
|
|
42
38
|
/**
|
|
43
39
|
* Optional stylesheet URL (typically Google Fonts) loaded lazily when
|
|
44
40
|
* the theme is selected.
|
|
45
41
|
*/
|
|
46
|
-
fontHref:
|
|
42
|
+
fontHref: import("typebox").TOptional<import("typebox").TString>;
|
|
47
43
|
}>>, "alepha.react.ui.themes">;
|
|
48
44
|
type UiThemeList = Static<typeof uiThemeListAtom.schema>;
|
|
49
45
|
type UiTheme = UiThemeList[number];
|
|
@@ -110,9 +106,8 @@ declare const useTheme: () => {
|
|
|
110
106
|
//#endregion
|
|
111
107
|
//#region ../../src/react/ui/services/SchemaControl.d.ts
|
|
112
108
|
/**
|
|
113
|
-
* Schema-bound metadata read by `<Control>` (in `@alepha/ui
|
|
114
|
-
*
|
|
115
|
-
* schema option.
|
|
109
|
+
* Schema-bound metadata read by `<Control>` (in `@alepha/ui`) to configure
|
|
110
|
+
* how a field renders. Place under `$control` on any TypeBox schema option.
|
|
116
111
|
*
|
|
117
112
|
* Two forms:
|
|
118
113
|
*
|
|
@@ -266,7 +261,7 @@ declare const resolveSchemaControl: (raw: unknown, context: {
|
|
|
266
261
|
declare module "typebox" {
|
|
267
262
|
interface TSchemaOptions {
|
|
268
263
|
/**
|
|
269
|
-
* UI metadata read by `<Control>` from `@alepha/ui
|
|
264
|
+
* UI metadata read by `<Control>` from `@alepha/ui`. See
|
|
270
265
|
* {@link SchemaControl}.
|
|
271
266
|
*/
|
|
272
267
|
$control?: SchemaControlOption;
|
|
@@ -287,14 +282,14 @@ declare module "typebox" {
|
|
|
287
282
|
* but not on cross-origin requests.
|
|
288
283
|
*/
|
|
289
284
|
declare class UiPersistence {
|
|
290
|
-
ui:
|
|
291
|
-
mode:
|
|
292
|
-
theme:
|
|
293
|
-
sidebar:
|
|
294
|
-
collapsed:
|
|
285
|
+
ui: import("alepha/server/cookies").AbstractCookiePrimitive<import("typebox").TObject<{
|
|
286
|
+
mode: import("typebox").TUnsafe<"light" | "dark" | "system">;
|
|
287
|
+
theme: import("typebox").TString;
|
|
288
|
+
sidebar: import("typebox").TObject<{
|
|
289
|
+
collapsed: import("typebox").TBoolean;
|
|
295
290
|
}>;
|
|
296
291
|
}>>;
|
|
297
|
-
head:
|
|
292
|
+
head: import("alepha/react/head").HeadPrimitive;
|
|
298
293
|
}
|
|
299
294
|
//#endregion
|
|
300
295
|
//#region ../../src/react/ui/index.d.ts
|
|
@@ -312,7 +307,7 @@ declare module "alepha" {
|
|
|
312
307
|
*
|
|
313
308
|
* @module alepha.react.ui
|
|
314
309
|
*/
|
|
315
|
-
declare const AlephaReactUi:
|
|
310
|
+
declare const AlephaReactUi: import("alepha").Service<import("alepha").Module>;
|
|
316
311
|
//#endregion
|
|
317
312
|
export { AlephaReactUi, ColorMode, ColorScheme, ResolvedColorMode, SchemaControl, SchemaControlFn, SchemaControlItem, SchemaControlItemsFn, SchemaControlOption, UiPersistence, UiState, UiTheme, UiThemeList, resolveSchemaControl, uiAtom, uiThemeListAtom, useColorMode, useSidebarState, useTheme };
|
|
318
313
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/react/ui/atoms/uiAtom.ts","../../../src/react/ui/atoms/uiThemeListAtom.ts","../../../src/react/ui/components/ColorScheme.tsx","../../../src/react/ui/hooks/useColorMode.ts","../../../src/react/ui/hooks/useSidebarState.ts","../../../src/react/ui/hooks/useTheme.ts","../../../src/react/ui/services/SchemaControl.ts","../../../src/react/ui/services/UiPersistence.ts","../../../src/react/ui/index.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/react/ui/atoms/uiAtom.ts","../../../src/react/ui/atoms/uiThemeListAtom.ts","../../../src/react/ui/components/ColorScheme.tsx","../../../src/react/ui/hooks/useColorMode.ts","../../../src/react/ui/hooks/useSidebarState.ts","../../../src/react/ui/hooks/useTheme.ts","../../../src/react/ui/services/SchemaControl.ts","../../../src/react/ui/services/UiPersistence.ts","../../../src/react/ui/index.ts"],"mappings":";;;;;;;AAQA;;;cAAa,MAAA,mBAAM,IAAA,mBAAA,OAAA;EAAA;;;;;;KAmBP,OAAA,GAAU,MAAM,QAAQ,MAAA,CAAO,MAAA;;;;;;AAnB3C;;;;;;cCGa,eAAA,mBAAe,IAAA,mBAAA,MAAA,mBAAA,OAAA;;;;;;;;EDgBhB;;;;;;KCOA,WAAA,GAAc,MAAM,QAAQ,eAAA,CAAgB,MAAA;AAAA,KAC5C,OAAA,GAAU,WAAW;;;;;;;AD3BjC;;;;;;iBEMgB,WAAA;;;KCVJ,SAAA;AAAA,KACA,iBAAA;;;AHGZ;;;;;;;cGQa,YAAA;;;kBAQO,SAAA;AAAA;;;;;;;AHhBpB;;;;cIGa,eAAA;;;;;;;;;;;AJHb;;;;cKGa,QAAA;;;;;;;;;ALHb;;;;;;;;;;;;;;;;AAmBA;;;;;;;UMCiB,aAAA;EAEf,IAAA;EACA,IAAA;EACA,QAAA;EACA,MAAA;EACA,MAAA;EACA,IAAA;EACA,IAAA;EACA,QAAA;EACA,IAAA;EACA,MAAA;EACA,QAAA;EACA,SAAA;EACA,MAAA;EACA,MAAA;EACA,KAAA;;;;;EAOA,IAAA;EACA,KAAA;EACA,WAAA;EACA,WAAA;;ALpBF;;;;;;EK4BE,YAAA;EL5B4D;AAAA;AAC9D;;;EKmCE,KAAA,GAAQ,KAAA,UAAe,iBAAA,IAAqB,oBAAA;ELnCb;;;;EKyC/B,UAAA;EJ9DyB;;;AAAA;;EIqEzB,cAAA,eAEM,KAAA;IAAoB,KAAA;IAAe,KAAA;EAAA;;;AHjFtB;AACrB;;;;AAA6B;AAW7B;EGiFE,KAAA;;;;;EAOA,MAAA;EACA,QAAA;EACA,QAAA;;;;;EAOA,GAAA;EACA,MAAA;EH1F2B;AAAA;;;;ACb7B;;;;EEmHE,MAAA;IAGM,KAAA;IACA,MAAA;IACA,OAAA;IACA,MAAA;EAAA;EAIN,UAAA;IACE,aAAA;MAA4B,KAAA;MAAgB,OAAA;IAAA,GDpH/C;ICsHG,aAAA,IAAiB,CAAA,UAAW,KAAA;IAC5B,QAAA;IACA,WAAA;IAEA,SAAA;EAAA;EAAA,CAID,GAAA;AAAA;AAAA,UAGc,iBAAA;EACf,KAAA;EACA,KAAA;EACA,WAAA;EACA,GAAA;AAAA;AAAA,KAGU,oBAAA,IACV,KAAA,aAEE,KAAA,UAAe,iBAAA,IACf,OAAA,CAAQ,KAAA,UAAe,iBAAA;;;;;;KAOf,eAAA,IAAmB,OAAA;EAC7B,IAAA,EAAM,SAAA;EACN,KAAA;AAAA,MACI,OAAA,CAAQ,aAAA;AAAA,KAEF,mBAAA,GAAsB,aAAA,GAAgB,eAAe;;;;;cAMpD,oBAAA,GACX,GAAA,WACA,OAAA;EAAW,IAAA,EAAM,SAAA;EAAgB,KAAA;AAAA,MAChC,OAAA,CAAQ,aAAA;AAAA;EAAA,UAkBC,cAAA;IAlJV;;;;IAuJE,QAAA,GAAW,mBAAmB;EAAA;AAAA;;;;;;;ANrMlC;;;;;;;;cOoBa,aAAA;EACX,EAAA,kCAAE,uBAAA,mBAAA,OAAA;;;;;;;EAQF,IAAA,8BAAI,aAAA;AAAA;;;;YCjBa,KAAA;IACf,iBAAA,EAAmB,OAAA;IACnB,wBAAA,EAA0B,WAAW;EAAA;AAAA;;;;;ARKzC;;;;cQSa,aAAA,mBAAa,OAAA,kBAAA,MAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/react/ui/atoms/uiThemeListAtom.ts","../../../src/react/ui/atoms/uiAtom.ts","../../../src/react/ui/services/UiPersistence.ts","../../../src/react/ui/hooks/useColorMode.ts","../../../src/react/ui/hooks/useTheme.ts","../../../src/react/ui/components/ColorScheme.tsx","../../../src/react/ui/hooks/useSidebarState.ts","../../../src/react/ui/services/SchemaControl.ts","../../../src/react/ui/index.ts"],"sourcesContent":["import { $atom, type Static, t } from \"alepha\";\n\n/**\n * Available themes the user can pick from. Apps populate this atom on boot\n * (e.g. `alepha.store.set(uiThemeListAtom, MY_THEMES)`); UI consumers like\n * `<ButtonTheme/>` read it to render a picker. The selected theme id is\n * persisted separately in `uiAtom.theme`.\n *\n * Defaults to a single `\"default\"` entry so the registry stays usable when\n * an app doesn't declare its own list.\n */\nexport const uiThemeListAtom = $atom({\n name: \"alepha.react.ui.themes\",\n schema: t.array(\n t.object({\n /** Stable id stored in `uiAtom.theme`. Mapped to a CSS class on `<html>`. */\n id: t.string(),\n /** Human-readable label shown in the picker. */\n label: t.string(),\n /**\n * Optional 4-color preview swatch in 2×2 order (TL, TR, BL, BR). Any\n * CSS-valid color string.\n */\n swatch: t.optional(t.array(t.string(), { minItems: 4, maxItems: 4 })),\n /**\n * Optional stylesheet URL (typically Google Fonts) loaded lazily when\n * the theme is selected.\n */\n fontHref: t.optional(t.string()),\n }),\n ),\n default: [{ id: \"default\", label: \"Default\" }],\n});\n\nexport type UiThemeList = Static<typeof uiThemeListAtom.schema>;\nexport type UiTheme = UiThemeList[number];\n","import { $atom, type Static, t } from \"alepha\";\n\n/**\n * Persisted UI state — color mode, theme palette, sidebar collapsed state, etc.\n *\n * The atom is bound to a single `alepha-ui` cookie via {@link UiPersistence},\n * so values survive page reloads and are available during SSR.\n */\nexport const uiAtom = $atom({\n name: \"alepha.react.ui\",\n schema: t.object({\n /** Color mode preference. `\"system\"` follows the OS-level setting. */\n mode: t.enum([\"light\", \"dark\", \"system\"]),\n /** Theme palette name. UI consumers map this to a CSS class on the root. */\n theme: t.string(),\n /** Sidebar UI state. */\n sidebar: t.object({\n collapsed: t.boolean(),\n }),\n }),\n default: {\n mode: \"system\",\n theme: \"default\",\n sidebar: { collapsed: false },\n },\n});\n\nexport type UiState = Static<typeof uiAtom.schema>;\n","import { $head } from \"alepha/react/head\";\nimport { $cookie } from \"alepha/server/cookies\";\nimport { uiAtom } from \"../atoms/uiAtom.ts\";\n\n/**\n * Inline `<script>` rendered by SSR into the document `<head>`. Runs\n * synchronously before any CSS or React hydration: reads the `alepha-ui`\n * cookie, resolves `mode === \"system\"` via `prefers-color-scheme`, and\n * applies `class=\"dark\"` (and optional `theme-<name>`) on `<html>`.\n *\n * This is what kills the flash-of-wrong-theme (FOUC) you'd otherwise get\n * with React-effect-based theming. Failures are swallowed silently — at\n * worst the page paints in light mode for one frame.\n */\nconst colorSchemeBoot = `(function(){try{var m=document.cookie.match(/(?:^|;\\\\s*)alepha-ui=([^;]+)/);var s=m?JSON.parse(decodeURIComponent(m[1])):{};var mode=s.mode||\"system\";var dark=mode===\"dark\"||(mode===\"system\"&&window.matchMedia&&window.matchMedia(\"(prefers-color-scheme: dark)\").matches);var r=document.documentElement;if(dark)r.classList.add(\"dark\");if(s.theme&&s.theme!==\"default\")r.classList.add(\"theme-\"+s.theme);}catch(e){}})();`;\n\n/**\n * Binds the {@link uiAtom} to an `alepha-ui` cookie + injects an inline\n * boot script into the SSR head to prevent FOUC on first paint.\n *\n * Reading flow: on app boot the cookie is parsed and pushed into the atom\n * (via the `key` option on `$cookie`). Writing flow: every time the atom\n * mutates, the cookie is rewritten — a single `useStore(uiAtom)` call is\n * enough to persist UI preferences across reloads.\n *\n * Persists for 365 days; SameSite=lax so it travels on top-level navigation\n * but not on cross-origin requests.\n */\nexport class UiPersistence {\n ui = $cookie({\n name: \"alepha-ui\",\n key: uiAtom.key,\n schema: uiAtom.schema,\n ttl: [365, \"days\"],\n sameSite: \"lax\",\n });\n\n head = $head({\n script: [{ content: colorSchemeBoot }],\n });\n}\n","import { useStore } from \"alepha/react\";\nimport { useEffect, useState } from \"react\";\nimport { uiAtom } from \"../atoms/uiAtom.ts\";\n\nexport type ColorMode = \"light\" | \"dark\" | \"system\";\nexport type ResolvedColorMode = \"light\" | \"dark\";\n\n/**\n * Read and update the user's color-mode preference. `\"system\"` resolves to\n * the OS preference and updates live as the OS toggles between light/dark.\n *\n * @example\n * const { mode, setMode, resolved } = useColorMode();\n * setMode(\"dark\");\n * document.documentElement.classList.toggle(\"dark\", resolved === \"dark\");\n */\nexport const useColorMode = () => {\n const [state, set] = useStore(uiAtom);\n const mode = (state?.mode ?? \"system\") as ColorMode;\n const resolved = useResolvedColorMode(mode);\n\n return {\n mode,\n resolved,\n setMode: (next: ColorMode) => {\n set({ ...(state ?? uiAtom.options.default!), mode: next });\n },\n };\n};\n\nconst useResolvedColorMode = (mode: ColorMode): ResolvedColorMode => {\n const [systemDark, setSystemDark] = useState<boolean>(() => {\n if (typeof window === \"undefined\") return false;\n return window.matchMedia?.(\"(prefers-color-scheme: dark)\").matches ?? false;\n });\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const mq = window.matchMedia?.(\"(prefers-color-scheme: dark)\");\n if (!mq) return;\n const onChange = (ev: MediaQueryListEvent) => setSystemDark(ev.matches);\n mq.addEventListener(\"change\", onChange);\n return () => mq.removeEventListener(\"change\", onChange);\n }, []);\n\n if (mode === \"dark\") return \"dark\";\n if (mode === \"light\") return \"light\";\n return systemDark ? \"dark\" : \"light\";\n};\n","import { useStore } from \"alepha/react\";\nimport { uiAtom } from \"../atoms/uiAtom.ts\";\n\n/**\n * Read and update the active theme palette name. UI consumers typically map\n * the value to a class on the document root (e.g. `theme-claude`).\n *\n * @example\n * const { theme, setTheme } = useTheme();\n * setTheme(\"claude\");\n */\nexport const useTheme = () => {\n const [state, set] = useStore(uiAtom);\n const theme = state?.theme ?? \"default\";\n\n return {\n theme,\n setTheme: (next: string) => {\n set({ ...(state ?? uiAtom.options.default!), theme: next });\n },\n };\n};\n","import { useEffect } from \"react\";\nimport { useColorMode } from \"../hooks/useColorMode.ts\";\nimport { useTheme } from \"../hooks/useTheme.ts\";\n\n/**\n * Applies `class=\"dark\"` and an optional theme palette class\n * (`theme-<name>`) to the document root, syncing whenever the underlying\n * atom mutates.\n *\n * Mount once near the root of your tree (typically inside the layout).\n *\n * @example\n * <ColorScheme />\n */\nexport function ColorScheme() {\n const { resolved } = useColorMode();\n const { theme } = useTheme();\n\n useEffect(() => {\n if (typeof document === \"undefined\") return;\n document.documentElement.classList.toggle(\"dark\", resolved === \"dark\");\n }, [resolved]);\n\n useEffect(() => {\n if (typeof document === \"undefined\") return;\n const root = document.documentElement;\n const previous: string[] = [];\n root.classList.forEach((cls) => {\n if (cls.startsWith(\"theme-\")) previous.push(cls);\n });\n for (const cls of previous) root.classList.remove(cls);\n if (theme && theme !== \"default\") root.classList.add(`theme-${theme}`);\n }, [theme]);\n\n return null;\n}\n","import { useStore } from \"alepha/react\";\nimport { uiAtom } from \"../atoms/uiAtom.ts\";\n\n/**\n * Read and update the sidebar collapsed state. The value is persisted via the\n * `alepha-ui` cookie so it survives reloads and is available during SSR — no\n * flash of expanded-then-collapsed when the user prefers a collapsed shell.\n *\n * @example\n * const { collapsed, setCollapsed, toggle } = useSidebarState();\n */\nexport const useSidebarState = () => {\n const [state, set] = useStore(uiAtom);\n const collapsed = state?.sidebar.collapsed ?? false;\n\n const setCollapsed = (next: boolean) => {\n const base = state ?? uiAtom.options.default!;\n set({ ...base, sidebar: { ...base.sidebar, collapsed: next } });\n };\n\n return {\n collapsed,\n setCollapsed,\n toggle: () => setCollapsed(!collapsed),\n };\n};\n","import type { FormModel } from \"alepha/react/form\";\n\n/**\n * Schema-bound metadata read by `<Control>` (in `@alepha/ui-registry`) to\n * configure how a field renders. Place under `$control` on any TypeBox\n * schema option.\n *\n * Two forms:\n *\n * 1. **Object** — static configuration baked into the schema:\n * ```ts\n * t.string({ $control: { password: true, icon: \"key\" } })\n * ```\n *\n * 2. **Function** — dynamic, computed from current form state:\n * ```ts\n * t.string({\n * $control: ({ form, value }) => {\n * if (form.currentValues.kind !== \"advanced\") return false; // hide\n * return { items: () => fetchOptions(form.currentValues.kind) };\n * },\n * })\n * ```\n *\n * The function may return:\n * - a partial `SchemaControl` to merge with explicit `<Control>` props\n * - `false` to hide the control entirely\n * - `undefined` to leave the field as-is\n */\nexport interface SchemaControl {\n // ── Variant forcing ────────────────────────────────────────────────\n text?: boolean;\n area?: boolean;\n password?: boolean;\n switch?: boolean;\n number?: boolean;\n file?: boolean;\n date?: boolean;\n datetime?: boolean;\n time?: boolean;\n select?: boolean;\n combobox?: boolean;\n segmented?: boolean;\n slider?: boolean;\n object?: boolean;\n array?: boolean;\n\n // ── Labels / hints ────────────────────────────────────────────────\n /**\n * Icon name. The registry control maps this to its icon set\n * (lucide-react). Pass `null` to suppress the schema-inferred icon.\n */\n icon?: string | null;\n label?: string;\n description?: string;\n placeholder?: string;\n /**\n * HTML `autocomplete` attribute. Use standard tokens like\n * `\"username\"`, `\"email\"`, `\"new-password\"`, `\"current-password\"`,\n * `\"street-address\"`, `\"address-line1\"`, `\"address-level2\"` (city),\n * `\"postal-code\"`, `\"country\"`, `\"cc-number\"`, `\"cc-exp\"`,\n * `\"cc-csc\"`, `\"cc-name\"`, `\"tel\"`, etc.\n */\n autoComplete?: string;\n\n // ── Data ──────────────────────────────────────────────────────────\n /**\n * Static or async option list for select / combobox / multi-select.\n * Each item is either a bare string (used as both value & label) or a\n * `{ value, label, description?, tag? }` object.\n */\n items?: Array<string | SchemaControlItem> | SchemaControlItemsFn;\n\n /**\n * Re-fetch `items` (when async) whenever any of these reference values\n * change. Useful for cascading selects.\n */\n itemsWatch?: unknown[];\n\n /**\n * Allow the user to create a new option by typing into a select /\n * multi-select. Pass `true` for `{ value: query, label: query }`, or a\n * function returning a custom option built from the query.\n */\n createNewEntry?:\n | boolean\n | ((query: string) => { value: string; label: string });\n\n // ── Layout ────────────────────────────────────────────────────────\n /**\n * Width slot inside an `<AutoForm>` group. Mapped to a grid column span.\n * - `100` → full row\n * - `75` → 3/4 row\n * - `66` → 2/3 row\n * - `50` → half\n * - `33` → one third (default for plain primitives)\n * - `25` → one quarter\n */\n width?: 100 | 75 | 66 | 50 | 33 | 25;\n\n // ── Behavior ─────────────────────────────────────────────────────\n /**\n * Render `null` (hide) when truthy. Equivalent to a function `$control`\n * returning `false`, but available as a static value.\n */\n hidden?: boolean;\n disabled?: boolean;\n readOnly?: boolean;\n\n // ── Slots ─────────────────────────────────────────────────────────\n /**\n * Render before/after the field. Both receive the resolved input.\n * Typed loosely — UI layer narrows to `ReactNode`.\n */\n top?: unknown;\n bottom?: unknown;\n\n // ── File upload ───────────────────────────────────────────────────\n /**\n * Render a managed upload control (image preview, multi, drag-drop)\n * that posts to the file API and stores the resulting file ID(s) in\n * the form. Pass `true` for defaults or an options object:\n *\n * ```ts\n * $control: { upload: { multi: true, accept: \"image/*\", maxSize: 5_000_000 } }\n * ```\n */\n upload?:\n | boolean\n | {\n multi?: boolean;\n accept?: string;\n maxSize?: number;\n bucket?: string;\n };\n\n // ── Array specifics ───────────────────────────────────────────────\n arrayProps?: {\n confirmDelete?: boolean | { title?: string; message?: string };\n /** Computed label for each tab when an array uses tabs mode. */\n renderTabName?: (i: number, value: unknown) => string;\n sortable?: boolean;\n collapsible?: boolean;\n /** Force grouped (CreateForm-style) tabs even for short arrays. */\n forceTabs?: boolean;\n };\n\n // ── Open extension ────────────────────────────────────────────────\n [key: string]: unknown;\n}\n\nexport interface SchemaControlItem {\n value: string | number | boolean;\n label: string;\n description?: string;\n tag?: string;\n}\n\nexport type SchemaControlItemsFn = (\n query: string,\n) =>\n | Array<string | SchemaControlItem>\n | Promise<Array<string | SchemaControlItem>>;\n\n/**\n * Function form of `$control`. Receives the live form model + the current\n * field value, and returns a partial config (merged with explicit props),\n * `false` to hide, or `undefined` to leave as-is.\n */\nexport type SchemaControlFn = (context: {\n form: FormModel<any>;\n value: unknown;\n}) => Partial<SchemaControl> | false | undefined;\n\nexport type SchemaControlOption = SchemaControl | SchemaControlFn;\n\n/**\n * Resolve a raw `$control` value (object or function) into a concrete\n * partial config. Returns `null` when the field should be hidden.\n */\nexport const resolveSchemaControl = (\n raw: unknown,\n context: { form: FormModel<any>; value: unknown },\n): Partial<SchemaControl> | null => {\n if (raw == null) return {};\n if (typeof raw === \"function\") {\n const result = (raw as SchemaControlFn)(context);\n if (result === false) return null;\n if (!result) return {};\n if (result.hidden) return null;\n return result;\n }\n if (typeof raw === \"object\") {\n const obj = raw as SchemaControl;\n if (obj.hidden) return null;\n return obj;\n }\n return {};\n};\n\ndeclare module \"typebox\" {\n interface TSchemaOptions {\n /**\n * UI metadata read by `<Control>` from `@alepha/ui-registry`. See\n * {@link SchemaControl}.\n */\n $control?: SchemaControlOption;\n }\n}\n","import { $module } from \"alepha\";\nimport type { UiState } from \"./atoms/uiAtom.ts\";\nimport type { UiThemeList } from \"./atoms/uiThemeListAtom.ts\";\nimport { uiThemeListAtom } from \"./atoms/uiThemeListAtom.ts\";\nimport { UiPersistence } from \"./services/UiPersistence.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./atoms/uiAtom.ts\";\nexport * from \"./atoms/uiThemeListAtom.ts\";\nexport * from \"./components/ColorScheme.tsx\";\nexport * from \"./hooks/useColorMode.ts\";\nexport * from \"./hooks/useSidebarState.ts\";\nexport * from \"./hooks/useTheme.ts\";\nexport * from \"./services/SchemaControl.ts\";\nexport * from \"./services/UiPersistence.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"alepha\" {\n export interface State {\n \"alepha.react.ui\": UiState;\n \"alepha.react.ui.themes\": UiThemeList;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Persisted UI state: color mode, theme palette, sidebar collapsed state.\n *\n * Backed by an `alepha-ui` cookie so preferences survive reloads and are\n * available during SSR (no flash of wrong theme).\n *\n * @module alepha.react.ui\n */\nexport const AlephaReactUi = $module({\n name: \"alepha.react.ui\",\n atoms: [uiThemeListAtom],\n services: [UiPersistence],\n});\n"],"mappings":";;;;;;;;;;;;;;;AAWA,MAAa,kBAAkB,MAAM;CACnC,MAAM;CACN,QAAQ,EAAE,MACR,EAAE,OAAO;;EAEP,IAAI,EAAE,QAAQ;;EAEd,OAAO,EAAE,QAAQ;;;;;EAKjB,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE;GAAE,UAAU;GAAG,UAAU;GAAG,CAAC,CAAC;;;;;EAKrE,UAAU,EAAE,SAAS,EAAE,QAAQ,CAAC;EACjC,CAAC,CACH;CACD,SAAS,CAAC;EAAE,IAAI;EAAW,OAAO;EAAW,CAAC;CAC/C,CAAC;;;;;;;;;ACxBF,MAAa,SAAS,MAAM;CAC1B,MAAM;CACN,QAAQ,EAAE,OAAO;;EAEf,MAAM,EAAE,KAAK;GAAC;GAAS;GAAQ;GAAS,CAAC;;EAEzC,OAAO,EAAE,QAAQ;;EAEjB,SAAS,EAAE,OAAO,EAChB,WAAW,EAAE,SAAS,EACvB,CAAC;EACH,CAAC;CACF,SAAS;EACP,MAAM;EACN,OAAO;EACP,SAAS,EAAE,WAAW,OAAO;EAC9B;CACF,CAAC;;;;;;;;;;;;;ACXF,MAAM,kBAAkB;;;;;;;;;;;;;AAcxB,IAAa,gBAAb,MAA2B;CACzB,KAAK,QAAQ;EACX,MAAM;EACN,KAAK,OAAO;EACZ,QAAQ,OAAO;EACf,KAAK,CAAC,KAAK,OAAO;EAClB,UAAU;EACX,CAAC;CAEF,OAAO,MAAM,EACX,QAAQ,CAAC,EAAE,SAAS,iBAAiB,CAAC,EACvC,CAAC;;;;;;;;;;;;;ACvBJ,MAAa,qBAAqB;CAChC,MAAM,CAAC,OAAO,OAAO,SAAS,OAAO;CACrC,MAAM,OAAQ,OAAO,QAAQ;CAG7B,OAAO;EACL;EACA,UAJe,qBAAqB,KAI5B;EACR,UAAU,SAAoB;GAC5B,IAAI;IAAE,GAAI,SAAS,OAAO,QAAQ;IAAW,MAAM;IAAM,CAAC;;EAE7D;;AAGH,MAAM,wBAAwB,SAAuC;CACnE,MAAM,CAAC,YAAY,iBAAiB,eAAwB;EAC1D,IAAI,OAAO,WAAW,aAAa,OAAO;EAC1C,OAAO,OAAO,aAAa,+BAA+B,CAAC,WAAW;GACtE;CAEF,gBAAgB;EACd,IAAI,OAAO,WAAW,aAAa;EACnC,MAAM,KAAK,OAAO,aAAa,+BAA+B;EAC9D,IAAI,CAAC,IAAI;EACT,MAAM,YAAY,OAA4B,cAAc,GAAG,QAAQ;EACvE,GAAG,iBAAiB,UAAU,SAAS;EACvC,aAAa,GAAG,oBAAoB,UAAU,SAAS;IACtD,EAAE,CAAC;CAEN,IAAI,SAAS,QAAQ,OAAO;CAC5B,IAAI,SAAS,SAAS,OAAO;CAC7B,OAAO,aAAa,SAAS;;;;;;;;;;;;ACpC/B,MAAa,iBAAiB;CAC5B,MAAM,CAAC,OAAO,OAAO,SAAS,OAAO;CAGrC,OAAO;EACL,OAHY,OAAO,SAAS;EAI5B,WAAW,SAAiB;GAC1B,IAAI;IAAE,GAAI,SAAS,OAAO,QAAQ;IAAW,OAAO;IAAM,CAAC;;EAE9D;;;;;;;;;;;;;;ACNH,SAAgB,cAAc;CAC5B,MAAM,EAAE,aAAa,cAAc;CACnC,MAAM,EAAE,UAAU,UAAU;CAE5B,gBAAgB;EACd,IAAI,OAAO,aAAa,aAAa;EACrC,SAAS,gBAAgB,UAAU,OAAO,QAAQ,aAAa,OAAO;IACrE,CAAC,SAAS,CAAC;CAEd,gBAAgB;EACd,IAAI,OAAO,aAAa,aAAa;EACrC,MAAM,OAAO,SAAS;EACtB,MAAM,WAAqB,EAAE;EAC7B,KAAK,UAAU,SAAS,QAAQ;GAC9B,IAAI,IAAI,WAAW,SAAS,EAAE,SAAS,KAAK,IAAI;IAChD;EACF,KAAK,MAAM,OAAO,UAAU,KAAK,UAAU,OAAO,IAAI;EACtD,IAAI,SAAS,UAAU,WAAW,KAAK,UAAU,IAAI,SAAS,QAAQ;IACrE,CAAC,MAAM,CAAC;CAEX,OAAO;;;;;;;;;;;;ACvBT,MAAa,wBAAwB;CACnC,MAAM,CAAC,OAAO,OAAO,SAAS,OAAO;CACrC,MAAM,YAAY,OAAO,QAAQ,aAAa;CAE9C,MAAM,gBAAgB,SAAkB;EACtC,MAAM,OAAO,SAAS,OAAO,QAAQ;EACrC,IAAI;GAAE,GAAG;GAAM,SAAS;IAAE,GAAG,KAAK;IAAS,WAAW;IAAM;GAAE,CAAC;;CAGjE,OAAO;EACL;EACA;EACA,cAAc,aAAa,CAAC,UAAU;EACvC;;;;;;;;AC4JH,MAAa,wBACX,KACA,YACkC;CAClC,IAAI,OAAO,MAAM,OAAO,EAAE;CAC1B,IAAI,OAAO,QAAQ,YAAY;EAC7B,MAAM,SAAU,IAAwB,QAAQ;EAChD,IAAI,WAAW,OAAO,OAAO;EAC7B,IAAI,CAAC,QAAQ,OAAO,EAAE;EACtB,IAAI,OAAO,QAAQ,OAAO;EAC1B,OAAO;;CAET,IAAI,OAAO,QAAQ,UAAU;EAC3B,MAAM,MAAM;EACZ,IAAI,IAAI,QAAQ,OAAO;EACvB,OAAO;;CAET,OAAO,EAAE;;;;;;;;;;;;ACjKX,MAAa,gBAAgB,QAAQ;CACnC,MAAM;CACN,OAAO,CAAC,gBAAgB;CACxB,UAAU,CAAC,cAAc;CAC1B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/react/ui/atoms/uiThemeListAtom.ts","../../../src/react/ui/atoms/uiAtom.ts","../../../src/react/ui/services/UiPersistence.ts","../../../src/react/ui/hooks/useColorMode.ts","../../../src/react/ui/hooks/useTheme.ts","../../../src/react/ui/components/ColorScheme.tsx","../../../src/react/ui/hooks/useSidebarState.ts","../../../src/react/ui/services/SchemaControl.ts","../../../src/react/ui/index.ts"],"sourcesContent":["import { $atom, type Static, t } from \"alepha\";\n\n/**\n * Available themes the user can pick from. Apps populate this atom on boot\n * (e.g. `alepha.store.set(uiThemeListAtom, MY_THEMES)`); UI consumers like\n * `<ButtonTheme/>` read it to render a picker. The selected theme id is\n * persisted separately in `uiAtom.theme`.\n *\n * Defaults to a single `\"default\"` entry so the registry stays usable when\n * an app doesn't declare its own list.\n */\nexport const uiThemeListAtom = $atom({\n name: \"alepha.react.ui.themes\",\n schema: t.array(\n t.object({\n /** Stable id stored in `uiAtom.theme`. Mapped to a CSS class on `<html>`. */\n id: t.string(),\n /** Human-readable label shown in the picker. */\n label: t.string(),\n /**\n * Optional 4-color preview swatch in 2×2 order (TL, TR, BL, BR). Any\n * CSS-valid color string.\n */\n swatch: t.optional(t.array(t.string(), { minItems: 4, maxItems: 4 })),\n /**\n * Optional stylesheet URL (typically Google Fonts) loaded lazily when\n * the theme is selected.\n */\n fontHref: t.optional(t.string()),\n }),\n ),\n default: [{ id: \"default\", label: \"Default\" }],\n});\n\nexport type UiThemeList = Static<typeof uiThemeListAtom.schema>;\nexport type UiTheme = UiThemeList[number];\n","import { $atom, type Static, t } from \"alepha\";\n\n/**\n * Persisted UI state — color mode, theme palette, sidebar collapsed state, etc.\n *\n * The atom is bound to a single `alepha-ui` cookie via {@link UiPersistence},\n * so values survive page reloads and are available during SSR.\n */\nexport const uiAtom = $atom({\n name: \"alepha.react.ui\",\n schema: t.object({\n /** Color mode preference. `\"system\"` follows the OS-level setting. */\n mode: t.enum([\"light\", \"dark\", \"system\"]),\n /** Theme palette name. UI consumers map this to a CSS class on the root. */\n theme: t.string(),\n /** Sidebar UI state. */\n sidebar: t.object({\n collapsed: t.boolean(),\n }),\n }),\n default: {\n mode: \"system\",\n theme: \"default\",\n sidebar: { collapsed: false },\n },\n});\n\nexport type UiState = Static<typeof uiAtom.schema>;\n","import { $head } from \"alepha/react/head\";\nimport { $cookie } from \"alepha/server/cookies\";\nimport { uiAtom } from \"../atoms/uiAtom.ts\";\n\n/**\n * Inline `<script>` rendered by SSR into the document `<head>`. Runs\n * synchronously before any CSS or React hydration: reads the `alepha-ui`\n * cookie, resolves `mode === \"system\"` via `prefers-color-scheme`, and\n * applies `class=\"dark\"` (and optional `theme-<name>`) on `<html>`.\n *\n * This is what kills the flash-of-wrong-theme (FOUC) you'd otherwise get\n * with React-effect-based theming. Failures are swallowed silently — at\n * worst the page paints in light mode for one frame.\n */\nconst colorSchemeBoot = `(function(){try{var m=document.cookie.match(/(?:^|;\\\\s*)alepha-ui=([^;]+)/);var s=m?JSON.parse(decodeURIComponent(m[1])):{};var mode=s.mode||\"system\";var dark=mode===\"dark\"||(mode===\"system\"&&window.matchMedia&&window.matchMedia(\"(prefers-color-scheme: dark)\").matches);var r=document.documentElement;if(dark)r.classList.add(\"dark\");if(s.theme&&s.theme!==\"default\")r.classList.add(\"theme-\"+s.theme);}catch(e){}})();`;\n\n/**\n * Binds the {@link uiAtom} to an `alepha-ui` cookie + injects an inline\n * boot script into the SSR head to prevent FOUC on first paint.\n *\n * Reading flow: on app boot the cookie is parsed and pushed into the atom\n * (via the `key` option on `$cookie`). Writing flow: every time the atom\n * mutates, the cookie is rewritten — a single `useStore(uiAtom)` call is\n * enough to persist UI preferences across reloads.\n *\n * Persists for 365 days; SameSite=lax so it travels on top-level navigation\n * but not on cross-origin requests.\n */\nexport class UiPersistence {\n ui = $cookie({\n name: \"alepha-ui\",\n key: uiAtom.key,\n schema: uiAtom.schema,\n ttl: [365, \"days\"],\n sameSite: \"lax\",\n });\n\n head = $head({\n script: [{ content: colorSchemeBoot }],\n });\n}\n","import { useStore } from \"alepha/react\";\nimport { useEffect, useState } from \"react\";\nimport { uiAtom } from \"../atoms/uiAtom.ts\";\n\nexport type ColorMode = \"light\" | \"dark\" | \"system\";\nexport type ResolvedColorMode = \"light\" | \"dark\";\n\n/**\n * Read and update the user's color-mode preference. `\"system\"` resolves to\n * the OS preference and updates live as the OS toggles between light/dark.\n *\n * @example\n * const { mode, setMode, resolved } = useColorMode();\n * setMode(\"dark\");\n * document.documentElement.classList.toggle(\"dark\", resolved === \"dark\");\n */\nexport const useColorMode = () => {\n const [state, set] = useStore(uiAtom);\n const mode = (state?.mode ?? \"system\") as ColorMode;\n const resolved = useResolvedColorMode(mode);\n\n return {\n mode,\n resolved,\n setMode: (next: ColorMode) => {\n set({ ...(state ?? uiAtom.options.default!), mode: next });\n },\n };\n};\n\nconst useResolvedColorMode = (mode: ColorMode): ResolvedColorMode => {\n const [systemDark, setSystemDark] = useState<boolean>(() => {\n if (typeof window === \"undefined\") return false;\n return window.matchMedia?.(\"(prefers-color-scheme: dark)\").matches ?? false;\n });\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const mq = window.matchMedia?.(\"(prefers-color-scheme: dark)\");\n if (!mq) return;\n const onChange = (ev: MediaQueryListEvent) => setSystemDark(ev.matches);\n mq.addEventListener(\"change\", onChange);\n return () => mq.removeEventListener(\"change\", onChange);\n }, []);\n\n if (mode === \"dark\") return \"dark\";\n if (mode === \"light\") return \"light\";\n return systemDark ? \"dark\" : \"light\";\n};\n","import { useStore } from \"alepha/react\";\nimport { uiAtom } from \"../atoms/uiAtom.ts\";\n\n/**\n * Read and update the active theme palette name. UI consumers typically map\n * the value to a class on the document root (e.g. `theme-claude`).\n *\n * @example\n * const { theme, setTheme } = useTheme();\n * setTheme(\"claude\");\n */\nexport const useTheme = () => {\n const [state, set] = useStore(uiAtom);\n const theme = state?.theme ?? \"default\";\n\n return {\n theme,\n setTheme: (next: string) => {\n set({ ...(state ?? uiAtom.options.default!), theme: next });\n },\n };\n};\n","import { useEffect } from \"react\";\nimport { useColorMode } from \"../hooks/useColorMode.ts\";\nimport { useTheme } from \"../hooks/useTheme.ts\";\n\n/**\n * Applies `class=\"dark\"` and an optional theme palette class\n * (`theme-<name>`) to the document root, syncing whenever the underlying\n * atom mutates.\n *\n * Mount once near the root of your tree (typically inside the layout).\n *\n * @example\n * <ColorScheme />\n */\nexport function ColorScheme() {\n const { resolved } = useColorMode();\n const { theme } = useTheme();\n\n useEffect(() => {\n if (typeof document === \"undefined\") return;\n document.documentElement.classList.toggle(\"dark\", resolved === \"dark\");\n }, [resolved]);\n\n useEffect(() => {\n if (typeof document === \"undefined\") return;\n const root = document.documentElement;\n const previous: string[] = [];\n root.classList.forEach((cls) => {\n if (cls.startsWith(\"theme-\")) previous.push(cls);\n });\n for (const cls of previous) root.classList.remove(cls);\n if (theme && theme !== \"default\") root.classList.add(`theme-${theme}`);\n }, [theme]);\n\n return null;\n}\n","import { useStore } from \"alepha/react\";\nimport { uiAtom } from \"../atoms/uiAtom.ts\";\n\n/**\n * Read and update the sidebar collapsed state. The value is persisted via the\n * `alepha-ui` cookie so it survives reloads and is available during SSR — no\n * flash of expanded-then-collapsed when the user prefers a collapsed shell.\n *\n * @example\n * const { collapsed, setCollapsed, toggle } = useSidebarState();\n */\nexport const useSidebarState = () => {\n const [state, set] = useStore(uiAtom);\n const collapsed = state?.sidebar.collapsed ?? false;\n\n const setCollapsed = (next: boolean) => {\n const base = state ?? uiAtom.options.default!;\n set({ ...base, sidebar: { ...base.sidebar, collapsed: next } });\n };\n\n return {\n collapsed,\n setCollapsed,\n toggle: () => setCollapsed(!collapsed),\n };\n};\n","import type { FormModel } from \"alepha/react/form\";\n\n/**\n * Schema-bound metadata read by `<Control>` (in `@alepha/ui`) to configure\n * how a field renders. Place under `$control` on any TypeBox schema option.\n *\n * Two forms:\n *\n * 1. **Object** — static configuration baked into the schema:\n * ```ts\n * t.string({ $control: { password: true, icon: \"key\" } })\n * ```\n *\n * 2. **Function** — dynamic, computed from current form state:\n * ```ts\n * t.string({\n * $control: ({ form, value }) => {\n * if (form.currentValues.kind !== \"advanced\") return false; // hide\n * return { items: () => fetchOptions(form.currentValues.kind) };\n * },\n * })\n * ```\n *\n * The function may return:\n * - a partial `SchemaControl` to merge with explicit `<Control>` props\n * - `false` to hide the control entirely\n * - `undefined` to leave the field as-is\n */\nexport interface SchemaControl {\n // ── Variant forcing ────────────────────────────────────────────────\n text?: boolean;\n area?: boolean;\n password?: boolean;\n switch?: boolean;\n number?: boolean;\n file?: boolean;\n date?: boolean;\n datetime?: boolean;\n time?: boolean;\n select?: boolean;\n combobox?: boolean;\n segmented?: boolean;\n slider?: boolean;\n object?: boolean;\n array?: boolean;\n\n // ── Labels / hints ────────────────────────────────────────────────\n /**\n * Icon name. The registry control maps this to its icon set\n * (lucide-react). Pass `null` to suppress the schema-inferred icon.\n */\n icon?: string | null;\n label?: string;\n description?: string;\n placeholder?: string;\n /**\n * HTML `autocomplete` attribute. Use standard tokens like\n * `\"username\"`, `\"email\"`, `\"new-password\"`, `\"current-password\"`,\n * `\"street-address\"`, `\"address-line1\"`, `\"address-level2\"` (city),\n * `\"postal-code\"`, `\"country\"`, `\"cc-number\"`, `\"cc-exp\"`,\n * `\"cc-csc\"`, `\"cc-name\"`, `\"tel\"`, etc.\n */\n autoComplete?: string;\n\n // ── Data ──────────────────────────────────────────────────────────\n /**\n * Static or async option list for select / combobox / multi-select.\n * Each item is either a bare string (used as both value & label) or a\n * `{ value, label, description?, tag? }` object.\n */\n items?: Array<string | SchemaControlItem> | SchemaControlItemsFn;\n\n /**\n * Re-fetch `items` (when async) whenever any of these reference values\n * change. Useful for cascading selects.\n */\n itemsWatch?: unknown[];\n\n /**\n * Allow the user to create a new option by typing into a select /\n * multi-select. Pass `true` for `{ value: query, label: query }`, or a\n * function returning a custom option built from the query.\n */\n createNewEntry?:\n | boolean\n | ((query: string) => { value: string; label: string });\n\n // ── Layout ────────────────────────────────────────────────────────\n /**\n * Width slot inside an `<AutoForm>` group. Mapped to a grid column span.\n * - `100` → full row\n * - `75` → 3/4 row\n * - `66` → 2/3 row\n * - `50` → half\n * - `33` → one third (default for plain primitives)\n * - `25` → one quarter\n */\n width?: 100 | 75 | 66 | 50 | 33 | 25;\n\n // ── Behavior ─────────────────────────────────────────────────────\n /**\n * Render `null` (hide) when truthy. Equivalent to a function `$control`\n * returning `false`, but available as a static value.\n */\n hidden?: boolean;\n disabled?: boolean;\n readOnly?: boolean;\n\n // ── Slots ─────────────────────────────────────────────────────────\n /**\n * Render before/after the field. Both receive the resolved input.\n * Typed loosely — UI layer narrows to `ReactNode`.\n */\n top?: unknown;\n bottom?: unknown;\n\n // ── File upload ───────────────────────────────────────────────────\n /**\n * Render a managed upload control (image preview, multi, drag-drop)\n * that posts to the file API and stores the resulting file ID(s) in\n * the form. Pass `true` for defaults or an options object:\n *\n * ```ts\n * $control: { upload: { multi: true, accept: \"image/*\", maxSize: 5_000_000 } }\n * ```\n */\n upload?:\n | boolean\n | {\n multi?: boolean;\n accept?: string;\n maxSize?: number;\n bucket?: string;\n };\n\n // ── Array specifics ───────────────────────────────────────────────\n arrayProps?: {\n confirmDelete?: boolean | { title?: string; message?: string };\n /** Computed label for each tab when an array uses tabs mode. */\n renderTabName?: (i: number, value: unknown) => string;\n sortable?: boolean;\n collapsible?: boolean;\n /** Force grouped (CreateForm-style) tabs even for short arrays. */\n forceTabs?: boolean;\n };\n\n // ── Open extension ────────────────────────────────────────────────\n [key: string]: unknown;\n}\n\nexport interface SchemaControlItem {\n value: string | number | boolean;\n label: string;\n description?: string;\n tag?: string;\n}\n\nexport type SchemaControlItemsFn = (\n query: string,\n) =>\n | Array<string | SchemaControlItem>\n | Promise<Array<string | SchemaControlItem>>;\n\n/**\n * Function form of `$control`. Receives the live form model + the current\n * field value, and returns a partial config (merged with explicit props),\n * `false` to hide, or `undefined` to leave as-is.\n */\nexport type SchemaControlFn = (context: {\n form: FormModel<any>;\n value: unknown;\n}) => Partial<SchemaControl> | false | undefined;\n\nexport type SchemaControlOption = SchemaControl | SchemaControlFn;\n\n/**\n * Resolve a raw `$control` value (object or function) into a concrete\n * partial config. Returns `null` when the field should be hidden.\n */\nexport const resolveSchemaControl = (\n raw: unknown,\n context: { form: FormModel<any>; value: unknown },\n): Partial<SchemaControl> | null => {\n if (raw == null) return {};\n if (typeof raw === \"function\") {\n const result = (raw as SchemaControlFn)(context);\n if (result === false) return null;\n if (!result) return {};\n if (result.hidden) return null;\n return result;\n }\n if (typeof raw === \"object\") {\n const obj = raw as SchemaControl;\n if (obj.hidden) return null;\n return obj;\n }\n return {};\n};\n\ndeclare module \"typebox\" {\n interface TSchemaOptions {\n /**\n * UI metadata read by `<Control>` from `@alepha/ui`. See\n * {@link SchemaControl}.\n */\n $control?: SchemaControlOption;\n }\n}\n","import { $module } from \"alepha\";\nimport type { UiState } from \"./atoms/uiAtom.ts\";\nimport type { UiThemeList } from \"./atoms/uiThemeListAtom.ts\";\nimport { uiThemeListAtom } from \"./atoms/uiThemeListAtom.ts\";\nimport { UiPersistence } from \"./services/UiPersistence.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./atoms/uiAtom.ts\";\nexport * from \"./atoms/uiThemeListAtom.ts\";\nexport * from \"./components/ColorScheme.tsx\";\nexport * from \"./hooks/useColorMode.ts\";\nexport * from \"./hooks/useSidebarState.ts\";\nexport * from \"./hooks/useTheme.ts\";\nexport * from \"./services/SchemaControl.ts\";\nexport * from \"./services/UiPersistence.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"alepha\" {\n export interface State {\n \"alepha.react.ui\": UiState;\n \"alepha.react.ui.themes\": UiThemeList;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Persisted UI state: color mode, theme palette, sidebar collapsed state.\n *\n * Backed by an `alepha-ui` cookie so preferences survive reloads and are\n * available during SSR (no flash of wrong theme).\n *\n * @module alepha.react.ui\n */\nexport const AlephaReactUi = $module({\n name: \"alepha.react.ui\",\n atoms: [uiThemeListAtom],\n services: [UiPersistence],\n});\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.bun.js","names":[],"sources":["../../src/redis/providers/RedisProvider.ts","../../src/redis/providers/BunRedisProvider.ts","../../src/redis/providers/RedisSubscriberProvider.ts","../../src/redis/providers/BunRedisSubscriberProvider.ts","../../src/redis/index.bun.ts"],"sourcesContent":["/**\n * Abstract Redis provider interface.\n *\n * This abstract class defines the common interface for Redis operations.\n * Implementations include:\n * - {@link NodeRedisProvider} - Uses `@redis/client` for Node.js runtime\n * - {@link BunRedisProvider} - Uses Bun's native `RedisClient` for Bun runtime\n *\n * @example\n * ```ts\n * // Inject the abstract provider - runtime selects the implementation\n * const redis = alepha.inject(RedisProvider);\n *\n * // Use common operations\n * await redis.set(\"key\", \"value\");\n * const value = await redis.get(\"key\");\n * ```\n */\nexport abstract class RedisProvider {\n /**\n * Whether the Redis client is ready to accept commands.\n */\n public abstract readonly isReady: boolean;\n\n /**\n * Connect to the Redis server.\n */\n public abstract connect(): Promise<void>;\n\n /**\n * Close the connection to the Redis server.\n */\n public abstract close(): Promise<void>;\n\n /**\n * Get the value of a key.\n *\n * @param key The key to get.\n * @returns The value as a Buffer, or undefined if the key does not exist.\n */\n public abstract get(key: string): Promise<Buffer | undefined>;\n\n /**\n * Set the value of a key.\n *\n * @param key The key to set.\n * @param value The value to set (Buffer or string).\n * @param options Optional set options (EX, PX, NX, XX, etc.).\n * @returns The value as a Buffer.\n */\n public abstract set(\n key: string,\n value: Buffer | string,\n options?: RedisSetOptions,\n ): Promise<Buffer>;\n\n /**\n * Check if a key exists.\n *\n * @param key The key to check.\n * @returns True if the key exists.\n */\n public abstract has(key: string): Promise<boolean>;\n\n /**\n * Get all keys matching a pattern.\n *\n * @param pattern The glob-style pattern to match.\n * @returns Array of matching key names.\n */\n public abstract keys(pattern: string): Promise<string[]>;\n\n /**\n * Delete one or more keys.\n *\n * @param keys The keys to delete.\n */\n public abstract del(keys: string[]): Promise<void>;\n\n // ---------------------------------------------------------\n // Queue operations (for alepha/queue-redis)\n // ---------------------------------------------------------\n\n /**\n * Push a value to the left (head) of a list.\n *\n * @param key The list key.\n * @param value The value to push.\n */\n public abstract lpush(key: string, value: string): Promise<void>;\n\n /**\n * Pop a value from the right (tail) of a list.\n *\n * @param key The list key.\n * @returns The value, or undefined if the list is empty.\n */\n public abstract rpop(key: string): Promise<string | undefined>;\n\n // ---------------------------------------------------------\n // Pub/Sub operations (for alepha/topic-redis)\n // ---------------------------------------------------------\n\n /**\n * Publish a message to a channel.\n *\n * @param channel The channel name.\n * @param message The message to publish.\n */\n public abstract publish(channel: string, message: string): Promise<void>;\n\n // ---------------------------------------------------------\n // Counter operations\n // ---------------------------------------------------------\n\n /**\n * Increment the integer value of a key by the given amount.\n *\n * If the key does not exist, it is set to 0 before performing the operation.\n * This operation is atomic.\n *\n * @param key The key to increment.\n * @param amount The amount to increment by.\n * @returns The new value after incrementing.\n */\n public abstract incr(key: string, amount: number): Promise<number>;\n}\n\n/**\n * Common Redis SET command options.\n * Compatible with @redis/client SetOptions format.\n */\nexport interface RedisSetOptions {\n /**\n * Set the specified expire time, in seconds.\n */\n EX?: number;\n /**\n * Set the specified expire time, in milliseconds.\n */\n PX?: number;\n /**\n * Set the specified Unix time at which the key will expire, in seconds.\n */\n EXAT?: number;\n /**\n * Set the specified Unix time at which the key will expire, in milliseconds.\n */\n PXAT?: number;\n /**\n * Only set the key if it does not already exist.\n */\n NX?: boolean;\n /**\n * Only set the key if it already exists.\n */\n XX?: boolean;\n /**\n * Retain the time to live associated with the key.\n */\n KEEPTTL?: boolean;\n /**\n * Return the old string stored at key, or nil if key did not exist.\n */\n GET?: boolean;\n /**\n * Alternative expiration format (compatible with @redis/client).\n */\n expiration?: {\n type: \"EX\" | \"PX\" | \"EXAT\" | \"PXAT\" | \"KEEPTTL\";\n value: number;\n };\n /**\n * Alternative condition format (compatible with @redis/client).\n */\n condition?: \"NX\" | \"XX\";\n}\n","import {\n $env,\n $hook,\n $inject,\n Alepha,\n AlephaError,\n type Static,\n t,\n} from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { RedisProvider, type RedisSetOptions } from \"./RedisProvider.ts\";\n\nconst envSchema = t.object({\n REDIS_URL: t.text({\n default: \"redis://localhost:6379\",\n description: \"Redis connection URL\",\n }),\n});\n\ndeclare module \"alepha\" {\n interface Env extends Partial<Static<typeof envSchema>> {}\n}\n\n/**\n * Bun Redis client provider using Bun's native Redis client.\n *\n * This provider uses Bun's built-in `RedisClient` class for Redis connections,\n * which provides excellent performance (7.9x faster than ioredis) on the Bun runtime.\n *\n * @example\n * ```ts\n * // Set REDIS_URL environment variable (default: redis://localhost:6379)\n * // REDIS_URL=redis://:password@myredis.example.com:6379\n *\n * // Or configure programmatically\n * alepha.with({\n * provide: RedisProvider,\n * use: BunRedisProvider,\n * });\n * ```\n */\nexport class BunRedisProvider extends RedisProvider {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly env = $env(envSchema);\n protected client?: Bun.RedisClient;\n\n public get publisher(): Bun.RedisClient {\n if (!this.client?.connected) {\n throw new AlephaError(\"Redis client is not ready\");\n }\n\n return this.client;\n }\n\n public override get isReady(): boolean {\n return this.client?.connected ?? false;\n }\n\n protected readonly start = $hook({\n on: \"start\",\n handler: () => this.connect(),\n });\n\n protected readonly stop = $hook({\n on: \"stop\",\n handler: () => this.close(),\n });\n\n /**\n * Connect to the Redis server.\n */\n public override async connect(): Promise<void> {\n // Check if we're running in Bun\n if (!this.alepha.isBun()) {\n throw new AlephaError(\n \"BunRedisProvider requires the Bun runtime. Use NodeRedisProvider for Node.js.\",\n );\n }\n\n this.log.debug(\"Connecting...\");\n\n this.client = new Bun.RedisClient(this.getUrl(), {\n autoReconnect: true,\n enableAutoPipelining: true,\n });\n\n this.client.onconnect = () => {\n this.log.trace(\"Redis connected\");\n };\n\n this.client.onclose = (error) => {\n if (this.alepha.isStarted() && error) {\n this.log.error(\"Redis connection closed\", error);\n }\n };\n\n await this.client.connect();\n\n this.log.info(\"Connection OK\");\n }\n\n /**\n * Close the connection to the Redis server.\n */\n public override async close(): Promise<void> {\n if (this.client) {\n this.log.debug(\"Closing connection...\");\n this.client.close();\n this.client = undefined;\n this.log.info(\"Connection closed\");\n }\n }\n\n /**\n * Create a duplicate connection for pub/sub or other isolated operations.\n */\n public async duplicate(): Promise<Bun.RedisClient> {\n if (typeof Bun === \"undefined\") {\n throw new AlephaError(\"BunRedisProvider requires the Bun runtime.\");\n }\n\n const client = new Bun.RedisClient(this.getUrl(), {\n autoReconnect: true,\n enableAutoPipelining: true,\n });\n\n client.onclose = (error) => {\n if (this.alepha.isStarted() && error) {\n this.log.error(\"Redis duplicate connection closed\", error);\n }\n };\n\n await client.connect();\n\n return client;\n }\n\n public override async get(key: string): Promise<Buffer | undefined> {\n this.log.trace(`Getting key ${key}`);\n const resp = await this.publisher.getBuffer(key);\n\n if (resp === null) {\n return undefined;\n }\n\n return Buffer.from(resp);\n }\n\n public override async set(\n key: string,\n value: Buffer | string,\n options?: RedisSetOptions,\n ): Promise<Buffer> {\n const buf = Buffer.isBuffer(value) ? value : Buffer.from(value, \"utf-8\");\n\n // Build SET command arguments\n const args: string[] = [key, buf.toString(\"binary\")];\n\n // Handle expiration object format (from alepha/cache-redis, alepha/lock-redis)\n if (options?.expiration) {\n if (options.expiration.type === \"KEEPTTL\") {\n args.push(\"KEEPTTL\");\n } else {\n args.push(options.expiration.type, String(options.expiration.value));\n }\n }\n\n // Handle direct expiration properties\n if (options?.EX !== undefined) {\n args.push(\"EX\", String(options.EX));\n }\n if (options?.PX !== undefined) {\n args.push(\"PX\", String(options.PX));\n }\n if (options?.EXAT !== undefined) {\n args.push(\"EXAT\", String(options.EXAT));\n }\n if (options?.PXAT !== undefined) {\n args.push(\"PXAT\", String(options.PXAT));\n }\n if (options?.KEEPTTL) {\n args.push(\"KEEPTTL\");\n }\n\n // Handle condition object format\n if (options?.condition === \"NX\") {\n args.push(\"NX\");\n } else if (options?.condition === \"XX\") {\n args.push(\"XX\");\n }\n\n // Handle direct condition properties\n if (options?.NX) {\n args.push(\"NX\");\n }\n if (options?.XX) {\n args.push(\"XX\");\n }\n if (options?.GET) {\n args.push(\"GET\");\n }\n\n if (args.length === 2) {\n // Simple set without options\n await this.publisher.set(key, buf);\n } else {\n // Set with options via raw command\n await this.publisher.send(\"SET\", args);\n }\n\n return buf;\n }\n\n public override async has(key: string): Promise<boolean> {\n return this.publisher.exists(key);\n }\n\n public override async keys(pattern: string): Promise<string[]> {\n const keys = await this.publisher.send(\"KEYS\", [pattern]);\n if (!Array.isArray(keys)) {\n return [];\n }\n return keys.map((key) =>\n key instanceof Uint8Array ? Buffer.from(key).toString() : String(key),\n );\n }\n\n public override async del(keys: string[]): Promise<void> {\n if (keys.length === 0) {\n return;\n }\n\n await this.publisher.send(\"DEL\", keys);\n }\n\n // ---------------------------------------------------------\n // Queue operations\n // ---------------------------------------------------------\n\n public override async lpush(key: string, value: string): Promise<void> {\n await this.publisher.send(\"LPUSH\", [key, value]);\n }\n\n public override async rpop(key: string): Promise<string | undefined> {\n const value = await this.publisher.send(\"RPOP\", [key]);\n if (value == null) {\n return undefined;\n }\n if (value instanceof Uint8Array) {\n return Buffer.from(value).toString();\n }\n return String(value);\n }\n\n // ---------------------------------------------------------\n // Pub/Sub operations\n // ---------------------------------------------------------\n\n public override async publish(\n channel: string,\n message: string,\n ): Promise<void> {\n await this.publisher.publish(channel, message);\n }\n\n // ---------------------------------------------------------\n // Counter operations\n // ---------------------------------------------------------\n\n public override async incr(key: string, amount: number): Promise<number> {\n const result = await this.publisher.send(\"INCRBY\", [key, String(amount)]);\n return Number(result);\n }\n\n /**\n * Get the Redis connection URL.\n */\n protected getUrl(): string {\n return this.env.REDIS_URL;\n }\n}\n","/**\n * Abstract Redis subscriber provider interface.\n *\n * This abstract class defines the common interface for Redis pub/sub subscriptions.\n * Implementations include:\n * - {@link NodeRedisSubscriberProvider} - Uses `@redis/client` for Node.js runtime\n * - {@link BunRedisSubscriberProvider} - Uses Bun's native `RedisClient` for Bun runtime\n *\n * Redis requires separate connections for pub/sub operations, so this provider\n * creates a dedicated connection for subscriptions.\n *\n * @example\n * ```ts\n * // Inject the abstract provider - runtime selects the implementation\n * const subscriber = alepha.inject(RedisSubscriberProvider);\n *\n * // Subscribe to a channel\n * await subscriber.subscribe(\"my-channel\", (message, channel) => {\n * console.log(`Received: ${message} on ${channel}`);\n * });\n * ```\n */\nexport abstract class RedisSubscriberProvider {\n /**\n * Whether the Redis subscriber client is ready to accept commands.\n */\n public abstract readonly isReady: boolean;\n\n /**\n * Connect to the Redis server for subscriptions.\n */\n public abstract connect(): Promise<void>;\n\n /**\n * Close the subscriber connection.\n */\n public abstract close(): Promise<void>;\n\n /**\n * Subscribe to a channel.\n *\n * @param channel The channel name.\n * @param callback The callback to invoke when a message is received.\n */\n public abstract subscribe(\n channel: string,\n callback: SubscribeCallback,\n ): Promise<void>;\n\n /**\n * Unsubscribe from a channel.\n *\n * @param channel The channel name.\n * @param callback Optional specific callback to remove.\n */\n public abstract unsubscribe(\n channel: string,\n callback?: SubscribeCallback,\n ): Promise<void>;\n}\n\n/**\n * Callback for subscription messages.\n */\nexport type SubscribeCallback = (message: string, channel: string) => void;\n","import { $hook, $inject, Alepha, AlephaError } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { BunRedisProvider } from \"./BunRedisProvider.ts\";\nimport {\n RedisSubscriberProvider,\n type SubscribeCallback,\n} from \"./RedisSubscriberProvider.ts\";\n\n/**\n * Bun Redis subscriber provider for pub/sub operations.\n *\n * This provider creates a dedicated Redis connection for subscriptions,\n * as Redis requires separate connections for pub/sub operations.\n *\n * @example\n * ```ts\n * const subscriber = alepha.inject(RedisSubscriberProvider);\n * await subscriber.subscribe(\"channel\", (message, channel) => {\n * console.log(`Received: ${message} on ${channel}`);\n * });\n * ```\n */\nexport class BunRedisSubscriberProvider extends RedisSubscriberProvider {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly redisProvider = $inject(BunRedisProvider);\n protected client?: Bun.RedisClient;\n\n public get subscriber(): Bun.RedisClient {\n if (!this.client?.connected) {\n throw new AlephaError(\"Redis subscriber client is not ready\");\n }\n\n return this.client;\n }\n\n public override get isReady(): boolean {\n return this.client?.connected ?? false;\n }\n\n protected readonly start = $hook({\n on: \"start\",\n handler: () => this.connect(),\n });\n\n protected readonly stop = $hook({\n on: \"stop\",\n handler: () => this.close(),\n });\n\n /**\n * Connect to the Redis server for subscriptions.\n */\n public override async connect(): Promise<void> {\n this.log.debug(\"Connecting subscriber...\");\n this.client = await this.redisProvider.duplicate();\n this.log.info(\"Subscriber connection OK\");\n }\n\n /**\n * Close the subscriber connection.\n */\n public override async close(): Promise<void> {\n if (this.client) {\n this.log.debug(\"Closing subscriber connection...\");\n this.client.close();\n this.client = undefined;\n this.log.info(\"Subscriber connection closed\");\n }\n }\n\n public override async subscribe(\n channel: string,\n callback: SubscribeCallback,\n ): Promise<void> {\n await this.subscriber.subscribe(channel, (message, ch) => {\n // Bun's callback provides Buffer or string, normalize to string\n const msg =\n typeof message === \"object\" && message !== null\n ? Buffer.from(message as Uint8Array).toString()\n : String(message);\n callback(msg, ch);\n });\n }\n\n public override async unsubscribe(\n channel: string,\n _callback?: SubscribeCallback,\n ): Promise<void> {\n // Bun's unsubscribe doesn't support callback filtering\n await this.subscriber.unsubscribe(channel);\n }\n}\n","import { $module, type Alepha } from \"alepha\";\nimport { BunRedisProvider } from \"./providers/BunRedisProvider.ts\";\nimport { BunRedisSubscriberProvider } from \"./providers/BunRedisSubscriberProvider.ts\";\nimport { RedisProvider } from \"./providers/RedisProvider.ts\";\nimport { RedisSubscriberProvider } from \"./providers/RedisSubscriberProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./providers/BunRedisProvider.ts\";\nexport * from \"./providers/BunRedisSubscriberProvider.ts\";\nexport * from \"./providers/RedisProvider.ts\";\nexport * from \"./providers/RedisSubscriberProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport const AlephaRedis = $module({\n name: \"alepha.redis\",\n services: [RedisProvider, RedisSubscriberProvider],\n variants: [BunRedisProvider, BunRedisSubscriberProvider],\n register: (alepha: Alepha) => {\n alepha\n .with({\n provide: RedisProvider,\n use: BunRedisProvider,\n })\n .with({\n provide: RedisSubscriberProvider,\n use: BunRedisSubscriberProvider,\n });\n },\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.bun.js","names":[],"sources":["../../src/redis/providers/RedisProvider.ts","../../src/redis/providers/BunRedisProvider.ts","../../src/redis/providers/RedisSubscriberProvider.ts","../../src/redis/providers/BunRedisSubscriberProvider.ts","../../src/redis/index.bun.ts"],"sourcesContent":["/**\n * Abstract Redis provider interface.\n *\n * This abstract class defines the common interface for Redis operations.\n * Implementations include:\n * - {@link NodeRedisProvider} - Uses `@redis/client` for Node.js runtime\n * - {@link BunRedisProvider} - Uses Bun's native `RedisClient` for Bun runtime\n *\n * @example\n * ```ts\n * // Inject the abstract provider - runtime selects the implementation\n * const redis = alepha.inject(RedisProvider);\n *\n * // Use common operations\n * await redis.set(\"key\", \"value\");\n * const value = await redis.get(\"key\");\n * ```\n */\nexport abstract class RedisProvider {\n /**\n * Whether the Redis client is ready to accept commands.\n */\n public abstract readonly isReady: boolean;\n\n /**\n * Connect to the Redis server.\n */\n public abstract connect(): Promise<void>;\n\n /**\n * Close the connection to the Redis server.\n */\n public abstract close(): Promise<void>;\n\n /**\n * Get the value of a key.\n *\n * @param key The key to get.\n * @returns The value as a Buffer, or undefined if the key does not exist.\n */\n public abstract get(key: string): Promise<Buffer | undefined>;\n\n /**\n * Set the value of a key.\n *\n * @param key The key to set.\n * @param value The value to set (Buffer or string).\n * @param options Optional set options (EX, PX, NX, XX, etc.).\n * @returns The value as a Buffer.\n */\n public abstract set(\n key: string,\n value: Buffer | string,\n options?: RedisSetOptions,\n ): Promise<Buffer>;\n\n /**\n * Check if a key exists.\n *\n * @param key The key to check.\n * @returns True if the key exists.\n */\n public abstract has(key: string): Promise<boolean>;\n\n /**\n * Get all keys matching a pattern.\n *\n * @param pattern The glob-style pattern to match.\n * @returns Array of matching key names.\n */\n public abstract keys(pattern: string): Promise<string[]>;\n\n /**\n * Delete one or more keys.\n *\n * @param keys The keys to delete.\n */\n public abstract del(keys: string[]): Promise<void>;\n\n // ---------------------------------------------------------\n // Queue operations (for alepha/queue-redis)\n // ---------------------------------------------------------\n\n /**\n * Push a value to the left (head) of a list.\n *\n * @param key The list key.\n * @param value The value to push.\n */\n public abstract lpush(key: string, value: string): Promise<void>;\n\n /**\n * Pop a value from the right (tail) of a list.\n *\n * @param key The list key.\n * @returns The value, or undefined if the list is empty.\n */\n public abstract rpop(key: string): Promise<string | undefined>;\n\n // ---------------------------------------------------------\n // Pub/Sub operations (for alepha/topic-redis)\n // ---------------------------------------------------------\n\n /**\n * Publish a message to a channel.\n *\n * @param channel The channel name.\n * @param message The message to publish.\n */\n public abstract publish(channel: string, message: string): Promise<void>;\n\n // ---------------------------------------------------------\n // Counter operations\n // ---------------------------------------------------------\n\n /**\n * Increment the integer value of a key by the given amount.\n *\n * If the key does not exist, it is set to 0 before performing the operation.\n * This operation is atomic.\n *\n * @param key The key to increment.\n * @param amount The amount to increment by.\n * @returns The new value after incrementing.\n */\n public abstract incr(key: string, amount: number): Promise<number>;\n}\n\n/**\n * Common Redis SET command options.\n * Compatible with @redis/client SetOptions format.\n */\nexport interface RedisSetOptions {\n /**\n * Set the specified expire time, in seconds.\n */\n EX?: number;\n /**\n * Set the specified expire time, in milliseconds.\n */\n PX?: number;\n /**\n * Set the specified Unix time at which the key will expire, in seconds.\n */\n EXAT?: number;\n /**\n * Set the specified Unix time at which the key will expire, in milliseconds.\n */\n PXAT?: number;\n /**\n * Only set the key if it does not already exist.\n */\n NX?: boolean;\n /**\n * Only set the key if it already exists.\n */\n XX?: boolean;\n /**\n * Retain the time to live associated with the key.\n */\n KEEPTTL?: boolean;\n /**\n * Return the old string stored at key, or nil if key did not exist.\n */\n GET?: boolean;\n /**\n * Alternative expiration format (compatible with @redis/client).\n */\n expiration?: {\n type: \"EX\" | \"PX\" | \"EXAT\" | \"PXAT\" | \"KEEPTTL\";\n value: number;\n };\n /**\n * Alternative condition format (compatible with @redis/client).\n */\n condition?: \"NX\" | \"XX\";\n}\n","import {\n $env,\n $hook,\n $inject,\n Alepha,\n AlephaError,\n type Static,\n t,\n} from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { RedisProvider, type RedisSetOptions } from \"./RedisProvider.ts\";\n\nconst envSchema = t.object({\n REDIS_URL: t.text({\n default: \"redis://localhost:6379\",\n description: \"Redis connection URL\",\n }),\n});\n\ndeclare module \"alepha\" {\n interface Env extends Partial<Static<typeof envSchema>> {}\n}\n\n/**\n * Bun Redis client provider using Bun's native Redis client.\n *\n * This provider uses Bun's built-in `RedisClient` class for Redis connections,\n * which provides excellent performance (7.9x faster than ioredis) on the Bun runtime.\n *\n * @example\n * ```ts\n * // Set REDIS_URL environment variable (default: redis://localhost:6379)\n * // REDIS_URL=redis://:password@myredis.example.com:6379\n *\n * // Or configure programmatically\n * alepha.with({\n * provide: RedisProvider,\n * use: BunRedisProvider,\n * });\n * ```\n */\nexport class BunRedisProvider extends RedisProvider {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly env = $env(envSchema);\n protected client?: Bun.RedisClient;\n\n public get publisher(): Bun.RedisClient {\n if (!this.client?.connected) {\n throw new AlephaError(\"Redis client is not ready\");\n }\n\n return this.client;\n }\n\n public override get isReady(): boolean {\n return this.client?.connected ?? false;\n }\n\n protected readonly start = $hook({\n on: \"start\",\n handler: () => this.connect(),\n });\n\n protected readonly stop = $hook({\n on: \"stop\",\n handler: () => this.close(),\n });\n\n /**\n * Connect to the Redis server.\n */\n public override async connect(): Promise<void> {\n // Check if we're running in Bun\n if (!this.alepha.isBun()) {\n throw new AlephaError(\n \"BunRedisProvider requires the Bun runtime. Use NodeRedisProvider for Node.js.\",\n );\n }\n\n this.log.debug(\"Connecting...\");\n\n this.client = new Bun.RedisClient(this.getUrl(), {\n autoReconnect: true,\n enableAutoPipelining: true,\n });\n\n this.client.onconnect = () => {\n this.log.trace(\"Redis connected\");\n };\n\n this.client.onclose = (error) => {\n if (this.alepha.isStarted() && error) {\n this.log.error(\"Redis connection closed\", error);\n }\n };\n\n await this.client.connect();\n\n this.log.info(\"Connection OK\");\n }\n\n /**\n * Close the connection to the Redis server.\n */\n public override async close(): Promise<void> {\n if (this.client) {\n this.log.debug(\"Closing connection...\");\n this.client.close();\n this.client = undefined;\n this.log.info(\"Connection closed\");\n }\n }\n\n /**\n * Create a duplicate connection for pub/sub or other isolated operations.\n */\n public async duplicate(): Promise<Bun.RedisClient> {\n if (typeof Bun === \"undefined\") {\n throw new AlephaError(\"BunRedisProvider requires the Bun runtime.\");\n }\n\n const client = new Bun.RedisClient(this.getUrl(), {\n autoReconnect: true,\n enableAutoPipelining: true,\n });\n\n client.onclose = (error) => {\n if (this.alepha.isStarted() && error) {\n this.log.error(\"Redis duplicate connection closed\", error);\n }\n };\n\n await client.connect();\n\n return client;\n }\n\n public override async get(key: string): Promise<Buffer | undefined> {\n this.log.trace(`Getting key ${key}`);\n const resp = await this.publisher.getBuffer(key);\n\n if (resp === null) {\n return undefined;\n }\n\n return Buffer.from(resp);\n }\n\n public override async set(\n key: string,\n value: Buffer | string,\n options?: RedisSetOptions,\n ): Promise<Buffer> {\n const buf = Buffer.isBuffer(value) ? value : Buffer.from(value, \"utf-8\");\n\n // Build SET command arguments\n const args: string[] = [key, buf.toString(\"binary\")];\n\n // Handle expiration object format (from alepha/cache-redis, alepha/lock-redis)\n if (options?.expiration) {\n if (options.expiration.type === \"KEEPTTL\") {\n args.push(\"KEEPTTL\");\n } else {\n args.push(options.expiration.type, String(options.expiration.value));\n }\n }\n\n // Handle direct expiration properties\n if (options?.EX !== undefined) {\n args.push(\"EX\", String(options.EX));\n }\n if (options?.PX !== undefined) {\n args.push(\"PX\", String(options.PX));\n }\n if (options?.EXAT !== undefined) {\n args.push(\"EXAT\", String(options.EXAT));\n }\n if (options?.PXAT !== undefined) {\n args.push(\"PXAT\", String(options.PXAT));\n }\n if (options?.KEEPTTL) {\n args.push(\"KEEPTTL\");\n }\n\n // Handle condition object format\n if (options?.condition === \"NX\") {\n args.push(\"NX\");\n } else if (options?.condition === \"XX\") {\n args.push(\"XX\");\n }\n\n // Handle direct condition properties\n if (options?.NX) {\n args.push(\"NX\");\n }\n if (options?.XX) {\n args.push(\"XX\");\n }\n if (options?.GET) {\n args.push(\"GET\");\n }\n\n if (args.length === 2) {\n // Simple set without options\n await this.publisher.set(key, buf);\n } else {\n // Set with options via raw command\n await this.publisher.send(\"SET\", args);\n }\n\n return buf;\n }\n\n public override async has(key: string): Promise<boolean> {\n return this.publisher.exists(key);\n }\n\n public override async keys(pattern: string): Promise<string[]> {\n const keys = await this.publisher.send(\"KEYS\", [pattern]);\n if (!Array.isArray(keys)) {\n return [];\n }\n return keys.map((key) =>\n key instanceof Uint8Array ? Buffer.from(key).toString() : String(key),\n );\n }\n\n public override async del(keys: string[]): Promise<void> {\n if (keys.length === 0) {\n return;\n }\n\n await this.publisher.send(\"DEL\", keys);\n }\n\n // ---------------------------------------------------------\n // Queue operations\n // ---------------------------------------------------------\n\n public override async lpush(key: string, value: string): Promise<void> {\n await this.publisher.send(\"LPUSH\", [key, value]);\n }\n\n public override async rpop(key: string): Promise<string | undefined> {\n const value = await this.publisher.send(\"RPOP\", [key]);\n if (value == null) {\n return undefined;\n }\n if (value instanceof Uint8Array) {\n return Buffer.from(value).toString();\n }\n return String(value);\n }\n\n // ---------------------------------------------------------\n // Pub/Sub operations\n // ---------------------------------------------------------\n\n public override async publish(\n channel: string,\n message: string,\n ): Promise<void> {\n await this.publisher.publish(channel, message);\n }\n\n // ---------------------------------------------------------\n // Counter operations\n // ---------------------------------------------------------\n\n public override async incr(key: string, amount: number): Promise<number> {\n const result = await this.publisher.send(\"INCRBY\", [key, String(amount)]);\n return Number(result);\n }\n\n /**\n * Get the Redis connection URL.\n */\n protected getUrl(): string {\n return this.env.REDIS_URL;\n }\n}\n","/**\n * Abstract Redis subscriber provider interface.\n *\n * This abstract class defines the common interface for Redis pub/sub subscriptions.\n * Implementations include:\n * - {@link NodeRedisSubscriberProvider} - Uses `@redis/client` for Node.js runtime\n * - {@link BunRedisSubscriberProvider} - Uses Bun's native `RedisClient` for Bun runtime\n *\n * Redis requires separate connections for pub/sub operations, so this provider\n * creates a dedicated connection for subscriptions.\n *\n * @example\n * ```ts\n * // Inject the abstract provider - runtime selects the implementation\n * const subscriber = alepha.inject(RedisSubscriberProvider);\n *\n * // Subscribe to a channel\n * await subscriber.subscribe(\"my-channel\", (message, channel) => {\n * console.log(`Received: ${message} on ${channel}`);\n * });\n * ```\n */\nexport abstract class RedisSubscriberProvider {\n /**\n * Whether the Redis subscriber client is ready to accept commands.\n */\n public abstract readonly isReady: boolean;\n\n /**\n * Connect to the Redis server for subscriptions.\n */\n public abstract connect(): Promise<void>;\n\n /**\n * Close the subscriber connection.\n */\n public abstract close(): Promise<void>;\n\n /**\n * Subscribe to a channel.\n *\n * @param channel The channel name.\n * @param callback The callback to invoke when a message is received.\n */\n public abstract subscribe(\n channel: string,\n callback: SubscribeCallback,\n ): Promise<void>;\n\n /**\n * Unsubscribe from a channel.\n *\n * @param channel The channel name.\n * @param callback Optional specific callback to remove.\n */\n public abstract unsubscribe(\n channel: string,\n callback?: SubscribeCallback,\n ): Promise<void>;\n}\n\n/**\n * Callback for subscription messages.\n */\nexport type SubscribeCallback = (message: string, channel: string) => void;\n","import { $hook, $inject, Alepha, AlephaError } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { BunRedisProvider } from \"./BunRedisProvider.ts\";\nimport {\n RedisSubscriberProvider,\n type SubscribeCallback,\n} from \"./RedisSubscriberProvider.ts\";\n\n/**\n * Bun Redis subscriber provider for pub/sub operations.\n *\n * This provider creates a dedicated Redis connection for subscriptions,\n * as Redis requires separate connections for pub/sub operations.\n *\n * @example\n * ```ts\n * const subscriber = alepha.inject(RedisSubscriberProvider);\n * await subscriber.subscribe(\"channel\", (message, channel) => {\n * console.log(`Received: ${message} on ${channel}`);\n * });\n * ```\n */\nexport class BunRedisSubscriberProvider extends RedisSubscriberProvider {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly redisProvider = $inject(BunRedisProvider);\n protected client?: Bun.RedisClient;\n\n public get subscriber(): Bun.RedisClient {\n if (!this.client?.connected) {\n throw new AlephaError(\"Redis subscriber client is not ready\");\n }\n\n return this.client;\n }\n\n public override get isReady(): boolean {\n return this.client?.connected ?? false;\n }\n\n protected readonly start = $hook({\n on: \"start\",\n handler: () => this.connect(),\n });\n\n protected readonly stop = $hook({\n on: \"stop\",\n handler: () => this.close(),\n });\n\n /**\n * Connect to the Redis server for subscriptions.\n */\n public override async connect(): Promise<void> {\n this.log.debug(\"Connecting subscriber...\");\n this.client = await this.redisProvider.duplicate();\n this.log.info(\"Subscriber connection OK\");\n }\n\n /**\n * Close the subscriber connection.\n */\n public override async close(): Promise<void> {\n if (this.client) {\n this.log.debug(\"Closing subscriber connection...\");\n this.client.close();\n this.client = undefined;\n this.log.info(\"Subscriber connection closed\");\n }\n }\n\n public override async subscribe(\n channel: string,\n callback: SubscribeCallback,\n ): Promise<void> {\n await this.subscriber.subscribe(channel, (message, ch) => {\n // Bun's callback provides Buffer or string, normalize to string\n const msg =\n typeof message === \"object\" && message !== null\n ? Buffer.from(message as Uint8Array).toString()\n : String(message);\n callback(msg, ch);\n });\n }\n\n public override async unsubscribe(\n channel: string,\n _callback?: SubscribeCallback,\n ): Promise<void> {\n // Bun's unsubscribe doesn't support callback filtering\n await this.subscriber.unsubscribe(channel);\n }\n}\n","import { $module, type Alepha } from \"alepha\";\nimport { BunRedisProvider } from \"./providers/BunRedisProvider.ts\";\nimport { BunRedisSubscriberProvider } from \"./providers/BunRedisSubscriberProvider.ts\";\nimport { RedisProvider } from \"./providers/RedisProvider.ts\";\nimport { RedisSubscriberProvider } from \"./providers/RedisSubscriberProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./providers/BunRedisProvider.ts\";\nexport * from \"./providers/BunRedisSubscriberProvider.ts\";\nexport * from \"./providers/RedisProvider.ts\";\nexport * from \"./providers/RedisSubscriberProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport const AlephaRedis = $module({\n name: \"alepha.redis\",\n services: [RedisProvider, RedisSubscriberProvider],\n variants: [BunRedisProvider, BunRedisSubscriberProvider],\n register: (alepha: Alepha) => {\n alepha\n .with({\n provide: RedisProvider,\n use: BunRedisProvider,\n })\n .with({\n provide: RedisSubscriberProvider,\n use: BunRedisSubscriberProvider,\n });\n },\n});\n"],"mappings":"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"}
|
package/dist/redis/index.d.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import * as _$alepha from "alepha";
|
|
2
1
|
import { Alepha, Static } from "alepha";
|
|
3
|
-
import * as _$alepha_logger0 from "alepha/logger";
|
|
4
2
|
import { RedisClientType, createClient } from "@redis/client";
|
|
5
3
|
|
|
6
4
|
//#region ../../src/redis/providers/RedisProvider.d.ts
|
|
@@ -155,8 +153,8 @@ interface RedisSetOptions {
|
|
|
155
153
|
}
|
|
156
154
|
//#endregion
|
|
157
155
|
//#region ../../src/redis/providers/BunRedisProvider.d.ts
|
|
158
|
-
declare const envSchema$1:
|
|
159
|
-
REDIS_URL:
|
|
156
|
+
declare const envSchema$1: import("alepha").TObject<{
|
|
157
|
+
REDIS_URL: import("alepha").TString;
|
|
160
158
|
}>;
|
|
161
159
|
declare module "alepha" {
|
|
162
160
|
interface Env extends Partial<Static<typeof envSchema$1>> {}
|
|
@@ -180,7 +178,7 @@ declare module "alepha" {
|
|
|
180
178
|
* ```
|
|
181
179
|
*/
|
|
182
180
|
declare class BunRedisProvider extends RedisProvider {
|
|
183
|
-
protected readonly log:
|
|
181
|
+
protected readonly log: import("alepha/logger").Logger;
|
|
184
182
|
protected readonly alepha: Alepha;
|
|
185
183
|
protected readonly env: {
|
|
186
184
|
REDIS_URL: string;
|
|
@@ -188,8 +186,8 @@ declare class BunRedisProvider extends RedisProvider {
|
|
|
188
186
|
protected client?: Bun.RedisClient;
|
|
189
187
|
get publisher(): Bun.RedisClient;
|
|
190
188
|
get isReady(): boolean;
|
|
191
|
-
protected readonly start:
|
|
192
|
-
protected readonly stop:
|
|
189
|
+
protected readonly start: import("alepha").HookPrimitive<"start">;
|
|
190
|
+
protected readonly stop: import("alepha").HookPrimitive<"stop">;
|
|
193
191
|
/**
|
|
194
192
|
* Connect to the Redis server.
|
|
195
193
|
*/
|
|
@@ -289,14 +287,14 @@ type SubscribeCallback = (message: string, channel: string) => void;
|
|
|
289
287
|
* ```
|
|
290
288
|
*/
|
|
291
289
|
declare class BunRedisSubscriberProvider extends RedisSubscriberProvider {
|
|
292
|
-
protected readonly log:
|
|
290
|
+
protected readonly log: import("alepha/logger").Logger;
|
|
293
291
|
protected readonly alepha: Alepha;
|
|
294
292
|
protected readonly redisProvider: BunRedisProvider;
|
|
295
293
|
protected client?: Bun.RedisClient;
|
|
296
294
|
get subscriber(): Bun.RedisClient;
|
|
297
295
|
get isReady(): boolean;
|
|
298
|
-
protected readonly start:
|
|
299
|
-
protected readonly stop:
|
|
296
|
+
protected readonly start: import("alepha").HookPrimitive<"start">;
|
|
297
|
+
protected readonly stop: import("alepha").HookPrimitive<"stop">;
|
|
300
298
|
/**
|
|
301
299
|
* Connect to the Redis server for subscriptions.
|
|
302
300
|
*/
|
|
@@ -310,8 +308,8 @@ declare class BunRedisSubscriberProvider extends RedisSubscriberProvider {
|
|
|
310
308
|
}
|
|
311
309
|
//#endregion
|
|
312
310
|
//#region ../../src/redis/providers/NodeRedisProvider.d.ts
|
|
313
|
-
declare const envSchema:
|
|
314
|
-
REDIS_URL:
|
|
311
|
+
declare const envSchema: import("alepha").TObject<{
|
|
312
|
+
REDIS_URL: import("alepha").TString;
|
|
315
313
|
}>;
|
|
316
314
|
declare module "alepha" {
|
|
317
315
|
interface Env extends Partial<Static<typeof envSchema>> {}
|
|
@@ -338,7 +336,7 @@ type NodeRedisClientOptions = Parameters<typeof createClient>[0];
|
|
|
338
336
|
* ```
|
|
339
337
|
*/
|
|
340
338
|
declare class NodeRedisProvider extends RedisProvider {
|
|
341
|
-
protected readonly log:
|
|
339
|
+
protected readonly log: import("alepha/logger").Logger;
|
|
342
340
|
protected readonly alepha: Alepha;
|
|
343
341
|
protected readonly env: {
|
|
344
342
|
REDIS_URL: string;
|
|
@@ -346,8 +344,8 @@ declare class NodeRedisProvider extends RedisProvider {
|
|
|
346
344
|
protected readonly client: NodeRedisClient;
|
|
347
345
|
get publisher(): NodeRedisClient;
|
|
348
346
|
get isReady(): boolean;
|
|
349
|
-
protected readonly start:
|
|
350
|
-
protected readonly stop:
|
|
347
|
+
protected readonly start: import("alepha").HookPrimitive<"start">;
|
|
348
|
+
protected readonly stop: import("alepha").HookPrimitive<"stop">;
|
|
351
349
|
/**
|
|
352
350
|
* Connect to the Redis server.
|
|
353
351
|
*/
|
|
@@ -392,14 +390,14 @@ declare class NodeRedisProvider extends RedisProvider {
|
|
|
392
390
|
* ```
|
|
393
391
|
*/
|
|
394
392
|
declare class NodeRedisSubscriberProvider extends RedisSubscriberProvider {
|
|
395
|
-
protected readonly log:
|
|
393
|
+
protected readonly log: import("alepha/logger").Logger;
|
|
396
394
|
protected readonly alepha: Alepha;
|
|
397
395
|
protected readonly redisProvider: NodeRedisProvider;
|
|
398
396
|
protected readonly client: NodeRedisClient;
|
|
399
397
|
get subscriber(): NodeRedisClient;
|
|
400
398
|
get isReady(): boolean;
|
|
401
|
-
protected readonly start:
|
|
402
|
-
protected readonly stop:
|
|
399
|
+
protected readonly start: import("alepha").HookPrimitive<"start">;
|
|
400
|
+
protected readonly stop: import("alepha").HookPrimitive<"stop">;
|
|
403
401
|
connect(): Promise<void>;
|
|
404
402
|
close(): Promise<void>;
|
|
405
403
|
subscribe(channel: string, callback: SubscribeCallback): Promise<void>;
|
|
@@ -422,7 +420,7 @@ declare class NodeRedisSubscriberProvider extends RedisSubscriberProvider {
|
|
|
422
420
|
*
|
|
423
421
|
* @module alepha.redis
|
|
424
422
|
*/
|
|
425
|
-
declare const AlephaRedis:
|
|
423
|
+
declare const AlephaRedis: import("alepha").Service<import("alepha").Module>;
|
|
426
424
|
//#endregion
|
|
427
425
|
export { AlephaRedis, BunRedisProvider, BunRedisSubscriberProvider, NodeRedisClient, NodeRedisClientOptions, NodeRedisProvider, NodeRedisSubscriberProvider, RedisProvider, RedisSetOptions, RedisSubscriberProvider, SubscribeCallback };
|
|
428
426
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/redis/providers/RedisProvider.ts","../../src/redis/providers/BunRedisProvider.ts","../../src/redis/providers/RedisSubscriberProvider.ts","../../src/redis/providers/BunRedisSubscriberProvider.ts","../../src/redis/providers/NodeRedisProvider.ts","../../src/redis/providers/NodeRedisSubscriberProvider.ts","../../src/redis/index.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/redis/providers/RedisProvider.ts","../../src/redis/providers/BunRedisProvider.ts","../../src/redis/providers/RedisSubscriberProvider.ts","../../src/redis/providers/BunRedisSubscriberProvider.ts","../../src/redis/providers/NodeRedisProvider.ts","../../src/redis/providers/NodeRedisSubscriberProvider.ts","../../src/redis/index.ts"],"mappings":"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"}
|