alepha 0.19.1 → 0.19.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +6 -9
- package/dist/api/audits/index.d.ts +378 -346
- package/dist/api/audits/index.d.ts.map +1 -1
- package/dist/api/files/index.d.ts +216 -184
- package/dist/api/files/index.d.ts.map +1 -1
- package/dist/api/jobs/index.d.ts +528 -496
- package/dist/api/jobs/index.d.ts.map +1 -1
- package/dist/api/jobs/index.js +3 -3
- package/dist/api/jobs/index.js.map +1 -1
- package/dist/api/keys/index.d.ts +207 -207
- package/dist/api/keys/index.d.ts.map +1 -1
- package/dist/api/notifications/index.d.ts +152 -152
- package/dist/api/notifications/index.d.ts.map +1 -1
- package/dist/api/organizations/index.browser.js +48 -0
- package/dist/api/organizations/index.browser.js.map +1 -0
- package/dist/api/organizations/index.d.ts +516 -0
- package/dist/api/organizations/index.d.ts.map +1 -0
- package/dist/api/organizations/index.js +202 -0
- package/dist/api/organizations/index.js.map +1 -0
- package/dist/api/parameters/index.d.ts +391 -358
- package/dist/api/parameters/index.d.ts.map +1 -1
- package/dist/api/parameters/index.js +5 -1
- package/dist/api/parameters/index.js.map +1 -1
- package/dist/api/users/index.browser.js +7 -5
- package/dist/api/users/index.browser.js.map +1 -1
- package/dist/api/users/index.d.ts +978 -913
- package/dist/api/users/index.d.ts.map +1 -1
- package/dist/api/users/index.js +160 -112
- package/dist/api/users/index.js.map +1 -1
- package/dist/api/verifications/index.d.ts +135 -135
- package/dist/api/verifications/index.d.ts.map +1 -1
- package/dist/api/verifications/index.js +2 -2
- package/dist/api/verifications/index.js.map +1 -1
- package/dist/batch/index.d.ts +6 -6
- package/dist/batch/index.d.ts.map +1 -1
- package/dist/billing/index.d.ts +1048 -0
- package/dist/billing/index.d.ts.map +1 -0
- package/dist/billing/index.js +713 -0
- package/dist/billing/index.js.map +1 -0
- package/dist/bin/index.js +0 -2
- package/dist/bin/index.js.map +1 -1
- package/dist/bucket/index.d.ts +10 -10
- package/dist/bucket/index.d.ts.map +1 -1
- package/dist/bucket/index.js +2 -2
- package/dist/bucket/index.js.map +1 -1
- package/dist/cache/core/index.d.ts +9 -9
- package/dist/cache/core/index.d.ts.map +1 -1
- package/dist/cache/core/index.js +2 -2
- package/dist/cache/core/index.js.map +1 -1
- package/dist/cache/core/index.workerd.js +2 -2
- package/dist/cache/core/index.workerd.js.map +1 -1
- package/dist/cache/redis/index.d.ts +6 -6
- package/dist/cache/redis/index.d.ts.map +1 -1
- package/dist/cache/redis/index.js +2 -2
- package/dist/cache/redis/index.js.map +1 -1
- package/dist/cli/config/index.d.ts +12 -2
- package/dist/cli/config/index.d.ts.map +1 -1
- package/dist/cli/config/index.js +4 -0
- package/dist/cli/config/index.js.map +1 -1
- package/dist/cli/core/index.d.ts +183 -140
- package/dist/cli/core/index.d.ts.map +1 -1
- package/dist/cli/core/index.js +279 -89
- package/dist/cli/core/index.js.map +1 -1
- package/dist/cli/devtools/index.d.ts +45 -0
- package/dist/cli/devtools/index.d.ts.map +1 -0
- package/dist/cli/devtools/index.js +170 -0
- package/dist/cli/devtools/index.js.map +1 -0
- package/dist/cli/platform/index.d.ts +383 -492
- package/dist/cli/platform/index.d.ts.map +1 -1
- package/dist/cli/platform/index.js +42 -511
- package/dist/cli/platform/index.js.map +1 -1
- package/dist/cli/vendor/index.d.ts +196 -0
- package/dist/cli/vendor/index.d.ts.map +1 -0
- package/dist/cli/vendor/index.js +384 -0
- package/dist/cli/vendor/index.js.map +1 -0
- package/dist/command/index.d.ts +18 -18
- package/dist/command/index.d.ts.map +1 -1
- package/dist/command/index.js +2 -2
- package/dist/command/index.js.map +1 -1
- package/dist/core/index.browser.js +4 -4
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +10 -10
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +4 -4
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js +4 -4
- package/dist/core/index.native.js.map +1 -1
- package/dist/core/index.workerd.js +4 -4
- package/dist/core/index.workerd.js.map +1 -1
- package/dist/crypto/index.d.ts +7 -7
- package/dist/crypto/index.d.ts.map +1 -1
- package/dist/datetime/index.d.ts +4 -4
- package/dist/datetime/index.d.ts.map +1 -1
- package/dist/email/brevo/index.d.ts +4 -4
- package/dist/email/brevo/index.d.ts.map +1 -1
- package/dist/email/core/index.d.ts +15 -11
- package/dist/email/core/index.d.ts.map +1 -1
- package/dist/email/core/index.js +12 -35
- package/dist/email/core/index.js.map +1 -1
- package/dist/email/smtp/index.d.ts +12 -12
- package/dist/email/smtp/index.d.ts.map +1 -1
- package/dist/email/smtp/index.js +7 -4
- package/dist/email/smtp/index.js.map +1 -1
- package/dist/fake/index.d.ts +4 -8
- package/dist/fake/index.d.ts.map +1 -1
- package/dist/fake/index.js +55 -889
- package/dist/fake/index.js.map +1 -1
- package/dist/lock/core/index.d.ts +13 -13
- package/dist/lock/core/index.d.ts.map +1 -1
- package/dist/lock/core/index.js +2 -2
- package/dist/lock/core/index.js.map +1 -1
- package/dist/lock/redis/index.d.ts +4 -4
- package/dist/lock/redis/index.d.ts.map +1 -1
- package/dist/logger/index.d.ts +16 -15
- package/dist/logger/index.d.ts.map +1 -1
- package/dist/logger/index.js +5 -2
- package/dist/logger/index.js.map +1 -1
- package/dist/mcp/index.d.ts +11 -11
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +2 -2
- package/dist/mcp/index.js.map +1 -1
- package/dist/orm/core/index.browser.js +11 -1
- package/dist/orm/core/index.browser.js.map +1 -1
- package/dist/orm/core/index.bun.js +53 -16
- package/dist/orm/core/index.bun.js.map +1 -1
- package/dist/orm/core/index.d.ts +95 -51
- package/dist/orm/core/index.d.ts.map +1 -1
- package/dist/orm/core/index.js +55 -14
- package/dist/orm/core/index.js.map +1 -1
- package/dist/orm/postgres/index.d.ts +18 -17
- package/dist/orm/postgres/index.d.ts.map +1 -1
- package/dist/queue/core/index.d.ts +14 -14
- package/dist/queue/core/index.d.ts.map +1 -1
- package/dist/queue/core/index.js +2 -2
- package/dist/queue/core/index.js.map +1 -1
- package/dist/queue/core/index.workerd.js +2 -2
- package/dist/queue/core/index.workerd.js.map +1 -1
- package/dist/queue/redis/index.d.ts +4 -4
- package/dist/queue/redis/index.d.ts.map +1 -1
- package/dist/queue/redis/index.js +2 -2
- package/dist/queue/redis/index.js.map +1 -1
- package/dist/react/auth/index.d.ts +9 -9
- package/dist/react/auth/index.d.ts.map +1 -1
- package/dist/react/core/index.d.ts +6 -6
- package/dist/react/core/index.d.ts.map +1 -1
- package/dist/react/core/index.js +5 -4
- package/dist/react/core/index.js.map +1 -1
- package/dist/react/form/index.d.ts +4 -4
- package/dist/react/form/index.d.ts.map +1 -1
- package/dist/react/head/index.d.ts +4 -4
- package/dist/react/head/index.d.ts.map +1 -1
- package/dist/react/i18n/index.d.ts +9 -9
- package/dist/react/i18n/index.d.ts.map +1 -1
- package/dist/react/intro/index.d.ts +2 -2
- package/dist/react/intro/index.d.ts.map +1 -1
- package/dist/react/intro/index.js +1 -1
- package/dist/react/intro/index.js.map +1 -1
- package/dist/react/router/index.browser.js +4 -5
- package/dist/react/router/index.browser.js.map +1 -1
- package/dist/react/router/index.d.ts +215 -215
- package/dist/react/router/index.d.ts.map +1 -1
- package/dist/react/router/index.js +6 -7
- package/dist/react/router/index.js.map +1 -1
- package/dist/react/testing/index.d.ts +2 -2
- package/dist/react/testing/index.d.ts.map +1 -1
- package/dist/react/testing/index.js +2 -4
- package/dist/react/testing/index.js.map +1 -1
- package/dist/redis/index.d.ts +19 -19
- package/dist/redis/index.d.ts.map +1 -1
- package/dist/retry/index.d.ts +4 -4
- package/dist/retry/index.d.ts.map +1 -1
- package/dist/scheduler/index.d.ts +13 -13
- package/dist/scheduler/index.d.ts.map +1 -1
- package/dist/scheduler/index.js +2 -2
- package/dist/scheduler/index.js.map +1 -1
- package/dist/scheduler/index.workerd.js +2 -2
- package/dist/scheduler/index.workerd.js.map +1 -1
- package/dist/security/index.browser.js +1 -1
- package/dist/security/index.browser.js.map +1 -1
- package/dist/security/index.d.ts +47 -47
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +9 -12
- package/dist/security/index.js.map +1 -1
- package/dist/server/auth/index.d.ts +170 -169
- package/dist/server/auth/index.d.ts.map +1 -1
- package/dist/server/auth/index.js +16 -2
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/cookies/index.d.ts +7 -7
- package/dist/server/cookies/index.d.ts.map +1 -1
- package/dist/server/core/index.d.ts +76 -76
- package/dist/server/core/index.d.ts.map +1 -1
- package/dist/server/core/index.js +23 -17
- package/dist/server/core/index.js.map +1 -1
- package/dist/server/cors/index.d.ts +13 -13
- package/dist/server/cors/index.d.ts.map +1 -1
- package/dist/server/cors/index.js +2 -2
- package/dist/server/cors/index.js.map +1 -1
- package/dist/server/etag/index.d.ts +9 -9
- package/dist/server/etag/index.d.ts.map +1 -1
- package/dist/server/health/index.d.ts +20 -20
- package/dist/server/health/index.d.ts.map +1 -1
- package/dist/server/links/index.browser.js +2 -2
- package/dist/server/links/index.browser.js.map +1 -1
- package/dist/server/links/index.d.ts +66 -66
- package/dist/server/links/index.d.ts.map +1 -1
- package/dist/server/links/index.js +4 -4
- package/dist/server/links/index.js.map +1 -1
- package/dist/server/metrics/index.d.ts +7 -7
- package/dist/server/metrics/index.d.ts.map +1 -1
- package/dist/server/proxy/index.d.ts +5 -5
- package/dist/server/proxy/index.d.ts.map +1 -1
- package/dist/server/rate-limit/index.d.ts +12 -12
- package/dist/server/rate-limit/index.d.ts.map +1 -1
- package/dist/server/rate-limit/index.js +2 -2
- package/dist/server/rate-limit/index.js.map +1 -1
- package/dist/server/static/index.d.ts +5 -5
- package/dist/server/static/index.d.ts.map +1 -1
- package/dist/server/swagger/index.d.ts +7 -7
- package/dist/server/swagger/index.d.ts.map +1 -1
- package/dist/server/swagger/index.js +2 -2
- package/dist/server/swagger/index.js.map +1 -1
- package/dist/sms/index.d.ts +11 -7
- package/dist/sms/index.d.ts.map +1 -1
- package/dist/sms/index.js +9 -15
- package/dist/sms/index.js.map +1 -1
- package/dist/system/index.d.ts +4 -4
- package/dist/system/index.d.ts.map +1 -1
- package/dist/topic/core/index.d.ts +6 -6
- package/dist/topic/core/index.d.ts.map +1 -1
- package/dist/topic/redis/index.d.ts +7 -7
- package/dist/topic/redis/index.d.ts.map +1 -1
- package/dist/topic/redis/index.js +2 -2
- package/dist/topic/redis/index.js.map +1 -1
- package/dist/websocket/index.d.ts +36 -36
- package/dist/websocket/index.d.ts.map +1 -1
- package/dist/websocket/index.js +2 -2
- package/dist/websocket/index.js.map +1 -1
- package/package.json +36 -14
- package/src/api/jobs/{services → __tests__}/JobService.spec.ts +1 -1
- package/src/api/jobs/providers/JobProvider.ts +3 -3
- package/src/api/keys/{services → __tests__}/ApiKeyService.spec.ts +1 -1
- package/src/api/organizations/__tests__/OrganizationService.spec.ts +193 -0
- package/src/api/organizations/controllers/AdminOrganizationController.ts +103 -0
- package/src/api/organizations/entities/organizations.ts +20 -0
- package/src/api/organizations/index.browser.ts +10 -0
- package/src/api/organizations/index.ts +31 -0
- package/src/api/organizations/schemas/createOrganizationSchema.ts +10 -0
- package/src/api/organizations/schemas/organizationQuerySchema.ts +10 -0
- package/src/api/organizations/schemas/organizationResourceSchema.ts +6 -0
- package/src/api/organizations/schemas/updateOrganizationSchema.ts +7 -0
- package/src/api/organizations/services/OrganizationService.ts +75 -0
- package/src/api/parameters/services/ParameterProvider.ts +6 -1
- package/src/api/users/{services → __tests__}/SessionService.spec.ts +67 -0
- package/src/api/users/{jobs → __tests__}/UserJobs.spec.ts +1 -1
- package/src/api/users/entities/users.ts +9 -3
- package/src/api/users/index.ts +23 -4
- package/src/api/users/primitives/$realm.ts +6 -4
- package/src/api/users/providers/RealmProvider.ts +1 -1
- package/src/api/users/services/RegistrationService.ts +1 -1
- package/src/api/users/services/SessionService.ts +92 -5
- package/src/api/users/services/UserService.ts +1 -1
- package/src/api/verifications/{jobs → __tests__}/VerificationJobs.spec.ts +4 -2
- package/src/api/verifications/parameters/VerificationParameters.ts +2 -2
- package/src/billing/__tests__/BillingService.spec.ts +136 -0
- package/src/billing/__tests__/PaymentMethodService.spec.ts +78 -0
- package/src/billing/controllers/AdminBillingController.ts +149 -0
- package/src/billing/controllers/BillingController.ts +108 -0
- package/src/billing/entities/paymentIntents.ts +34 -0
- package/src/billing/entities/paymentMethods.ts +24 -0
- package/src/billing/entities/refunds.ts +22 -0
- package/src/billing/errors/BillingError.ts +5 -0
- package/src/billing/index.ts +76 -0
- package/src/billing/providers/BillingProvider.ts +79 -0
- package/src/billing/providers/MemoryBillingProvider.ts +139 -0
- package/src/billing/schemas/intentSchemas.ts +60 -0
- package/src/billing/schemas/paymentMethodSchemas.ts +13 -0
- package/src/billing/schemas/refundSchemas.ts +6 -0
- package/src/billing/services/BillingService.ts +325 -0
- package/src/billing/services/PaymentMethodService.ts +82 -0
- package/src/bin/index.ts +0 -2
- package/src/bucket/providers/LocalFileStorageProvider.ts +2 -2
- package/src/cache/core/{primitives → __tests__}/$cache.middleware.spec.ts +1 -1
- package/src/cache/core/{providers → __tests__}/MemoryCacheProvider.spec.ts +1 -1
- package/src/cache/core/primitives/$cache.ts +2 -2
- package/src/cache/redis/providers/RedisCacheProvider.ts +2 -2
- package/src/cli/config/defineConfig.ts +20 -0
- package/src/cli/core/{services → __tests__}/ProjectScaffolder.spec.ts +1 -1
- package/src/cli/core/{commands/gen → __tests__}/changelog.spec.ts +1 -1
- package/src/cli/core/{commands → __tests__}/init.spec.ts +2 -8
- package/src/cli/core/atoms/devOptions.ts +0 -5
- package/src/cli/core/commands/build.ts +2 -2
- package/src/cli/core/commands/dev.ts +165 -30
- package/src/cli/core/commands/gen/changelog.ts +2 -2
- package/src/cli/core/commands/init.ts +2 -7
- package/src/cli/core/commands/verify.ts +0 -1
- package/src/cli/core/providers/AppEntryProvider.ts +2 -2
- package/src/cli/core/providers/ViteDevServerProvider.ts +54 -66
- package/src/cli/core/services/PackageManagerUtils.ts +8 -3
- package/src/cli/core/services/ProjectScaffolder.ts +18 -18
- package/src/cli/core/tasks/BuildClientTask.ts +8 -0
- package/src/cli/core/tasks/BuildServerTask.ts +17 -4
- package/src/cli/core/templates/alephaConfigTs.ts +0 -6
- package/src/cli/core/templates/webAdminDashboardTsx.ts +17 -0
- package/src/cli/core/templates/webAppRouterTs.ts +85 -2
- package/src/cli/devtools/atoms/devtoolsOptions.ts +26 -0
- package/src/cli/devtools/index.ts +194 -0
- package/src/cli/platform/{adapters → __tests__}/CloudflareAdapter.spec.ts +2 -2
- package/src/cli/platform/{providers → __tests__}/GitHubSecretStore.spec.ts +1 -1
- package/src/cli/platform/{services → __tests__}/NamingService.spec.ts +1 -1
- package/src/cli/platform/{providers → __tests__}/PlatformCacheProvider.spec.ts +1 -1
- package/src/cli/platform/{services → __tests__}/PlatformInspector.spec.ts +1 -1
- package/src/cli/platform/{services → __tests__}/PlatformOrchestrator.spec.ts +3 -3
- package/src/cli/platform/{services → __tests__}/SecretFilterService.spec.ts +1 -1
- package/src/cli/platform/{commands → __tests__}/SecretsCommand.spec.ts +1 -1
- package/src/cli/platform/{adapters → __tests__}/VercelAdapter.spec.ts +2 -2
- package/src/cli/platform/atoms/platformOptions.ts +2 -10
- package/src/cli/platform/commands/SecretsCommand.ts +2 -2
- package/src/cli/platform/commands/platform.ts +2 -11
- package/src/cli/platform/index.ts +34 -11
- package/src/cli/platform/services/PlatformInspector.ts +2 -2
- package/src/cli/platform/services/PlatformOrchestrator.ts +0 -9
- package/src/cli/vendor/__tests__/VendorService.spec.ts +407 -0
- package/src/cli/vendor/atoms/vendorOptions.ts +41 -0
- package/src/cli/vendor/commands/VendorCommand.ts +204 -0
- package/src/cli/vendor/index.ts +43 -0
- package/src/cli/vendor/services/VendorService.ts +338 -0
- package/src/command/{providers → __tests__}/CliProvider.spec.ts +1 -1
- package/src/command/{helpers → __tests__}/EnvUtils.spec.ts +1 -1
- package/src/command/providers/CliProvider.ts +2 -2
- package/src/core/{primitives → __tests__}/$atom.spec.ts +2 -2
- package/src/core/{primitives → __tests__}/$memoize.spec.ts +1 -1
- package/src/core/{primitives → __tests__}/$mode.spec.ts +1 -1
- package/src/core/{primitives → __tests__}/$pipeline.spec.ts +1 -1
- package/src/core/{primitives → __tests__}/$scope.spec.ts +2 -2
- package/src/core/{providers → __tests__}/KeylessJsonSchemaCodec.spec.ts +1 -1
- package/src/core/{providers → __tests__}/SchemaValidator.spec.ts +1 -1
- package/src/core/{helpers → __tests__}/jsonSchemaToTypeBox.spec.ts +1 -1
- package/src/core/index.shared.ts +1 -1
- package/src/core/primitives/{$use.ts → $state.ts} +4 -4
- package/src/crypto/{providers → __tests__}/BrowserCryptoProvider.browser.spec.ts +1 -1
- package/src/crypto/{providers → __tests__}/CryptoProvider.spec.ts +1 -1
- package/src/datetime/{primitives → __tests__}/$debounce.spec.ts +1 -1
- package/src/datetime/{primitives → __tests__}/$throttle.spec.ts +1 -1
- package/src/datetime/{primitives → __tests__}/$timeout.spec.ts +1 -1
- package/src/email/brevo/{providers → __tests__}/BrevoEmailProvider.spec.ts +1 -1
- package/src/email/core/{providers → __tests__}/LocalEmailProvider.spec.ts +39 -150
- package/src/email/core/providers/LocalEmailProvider.ts +13 -51
- package/src/email/smtp/providers/NodemailerEmailProvider.ts +2 -2
- package/src/lock/core/{primitives → __tests__}/$lock.middleware.spec.ts +1 -1
- package/src/lock/core/primitives/$lock.ts +2 -2
- package/src/logger/index.ts +10 -4
- package/src/mcp/transports/SseMcpTransport.ts +2 -2
- package/src/orm/__tests__/ModelBuilder-tests.ts +53 -0
- package/src/orm/__tests__/ModelBuilder.spec.ts +80 -0
- package/src/orm/__tests__/organization-tests.ts +200 -0
- package/src/orm/__tests__/organization.spec.ts +103 -0
- package/src/orm/core/{providers/drivers → __tests__}/BunSqliteProvider.bun.spec.ts +5 -2
- package/src/orm/core/constants/PG_SYMBOLS.ts +2 -0
- package/src/orm/core/index.shared.ts +1 -0
- package/src/orm/core/primitives/$entity.ts +31 -0
- package/src/orm/core/providers/DatabaseTypeProvider.ts +11 -0
- package/src/orm/core/providers/DrizzleKitProvider.ts +1 -1
- package/src/orm/core/providers/drivers/BunSqliteProvider.ts +2 -2
- package/src/orm/core/providers/drivers/NodeSqliteProvider.ts +3 -3
- package/src/orm/core/services/ModelBuilder.ts +11 -0
- package/src/orm/core/services/QueryManager.ts +16 -2
- package/src/orm/core/services/Repository.ts +70 -10
- package/src/orm/postgres/{providers → __tests__}/BunPostgresProvider.bun.spec.ts +1 -1
- package/src/queue/core/providers/WorkerProvider.ts +2 -2
- package/src/queue/redis/providers/RedisQueueProvider.ts +2 -2
- package/src/react/core/{hooks → __tests__}/useAction.browser.spec.tsx +1 -1
- package/src/react/core/hooks/useAction.ts +7 -6
- package/src/react/head/{providers → __tests__}/BrowserHeadProvider.browser.spec.ts +1 -1
- package/src/react/head/{helpers → __tests__}/SeoExpander.spec.ts +1 -1
- package/src/react/i18n/{providers → __tests__}/I18nProvider.spec.ts +1 -1
- package/src/react/i18n/{hooks → __tests__}/useI18n.browser.spec.tsx +1 -1
- package/src/react/intro/components/GettingStartedDevtoolsSlide.tsx +1 -1
- package/src/react/router/{providers → __tests__}/ReactBrowserProvider.browser.spec.ts +1 -1
- package/src/react/router/providers/ReactBrowserProvider.ts +2 -2
- package/src/react/router/providers/ReactPageProvider.ts +2 -2
- package/src/react/router/providers/ReactServerProvider.ts +3 -3
- package/src/redis/{providers → __tests__}/BunRedisProvider.bun.spec.ts +4 -4
- package/src/retry/{primitives → __tests__}/$retry.middleware.spec.ts +1 -1
- package/src/router/{TemplatedPathParser.spec.ts → __tests__/TemplatedPathParser.spec.ts} +1 -1
- package/src/scheduler/primitives/$scheduler.ts +2 -2
- package/src/security/{primitives → __tests__}/$secure-browser.spec.ts +1 -1
- package/src/security/{primitives → __tests__}/$secure.spec.ts +1 -1
- package/src/security/primitives/$issuer.ts +1 -1
- package/src/security/providers/JwtProvider.ts +6 -10
- package/src/security/providers/SecurityProvider.ts +6 -11
- package/src/security/schemas/userAccountInfoSchema.ts +3 -3
- package/src/server/auth/providers/ServerAuthProvider.ts +24 -2
- package/src/server/cookies/{services → __tests__}/CookieParser.spec.ts +1 -1
- package/src/server/core/{primitives → __tests__}/$circuit.spec.ts +1 -1
- package/src/server/core/{providers → __tests__}/NodeHttpServerProvider.spec.ts +1 -1
- package/src/server/core/{providers → __tests__}/ServerBodyParserProvider.spec.ts +31 -1
- package/src/server/core/{providers → __tests__}/ServerCompressProvider.spec.ts +1 -1
- package/src/server/core/{providers → __tests__}/ServerHelmetProvider.spec.ts +4 -1
- package/src/server/core/{providers → __tests__}/ServerMultipartProvider.spec.ts +1 -1
- package/src/server/core/{services → __tests__}/ServerRequestParser.spec.ts +1 -1
- package/src/server/core/primitives/$action.ts +2 -2
- package/src/server/core/primitives/$sse.ts +2 -2
- package/src/server/core/providers/ServerBodyParserProvider.ts +21 -12
- package/src/server/core/providers/ServerCompressProvider.ts +2 -2
- package/src/server/core/providers/ServerHelmetProvider.ts +2 -2
- package/src/server/core/providers/ServerMultipartProvider.ts +2 -2
- package/src/server/core/providers/ServerRouterProvider.ts +1 -5
- package/src/server/cors/{primitives → __tests__}/$cors.spec.ts +1 -1
- package/src/server/cors/providers/ServerCorsProvider.ts +2 -2
- package/src/server/links/{services → __tests__}/BatchCollector.spec.ts +1 -1
- package/src/server/links/providers/LinkProvider.ts +2 -2
- package/src/server/links/providers/RemotePrimitiveProvider.ts +2 -2
- package/src/server/links/providers/ServerLinksProvider.ts +2 -2
- package/src/server/rate-limit/{primitives → __tests__}/$rateLimit.spec.ts +1 -1
- package/src/server/rate-limit/providers/ServerRateLimitProvider.ts +2 -2
- package/src/server/swagger/providers/ServerSwaggerProvider.ts +2 -2
- package/src/sms/{providers → __tests__}/LocalSmsProvider.spec.ts +35 -29
- package/src/sms/providers/LocalSmsProvider.ts +13 -24
- package/src/system/{providers → __tests__}/MemoryFileSystemProvider.spec.ts +1 -1
- package/src/system/{providers → __tests__}/MemoryShellProvider.spec.ts +1 -1
- package/src/topic/redis/providers/RedisTopicProvider.ts +2 -2
- package/src/websocket/{services → __tests__}/RoomManager.spec.ts +1 -1
- package/src/websocket/providers/NodeWebSocketServerProvider.ts +2 -2
- package/tsconfig.base.json +1 -0
- package/src/cli/platform/adapters/DockerAdapter.spec.ts +0 -378
- package/src/cli/platform/adapters/DockerAdapter.ts +0 -417
- package/src/cli/platform/services/DockerComposeGenerator.spec.ts +0 -490
- package/src/cli/platform/services/DockerComposeGenerator.ts +0 -353
- package/src/cli/platform/services/DockerSshService.spec.ts +0 -47
- package/src/cli/platform/services/DockerSshService.ts +0 -61
- /package/src/api/audits/{primitives → __tests__}/$audit.spec.ts +0 -0
- /package/src/api/audits/{services → __tests__}/AuditService.spec.ts +0 -0
- /package/src/api/files/{controllers → __tests__}/AdminFileStatsController.spec.ts +0 -0
- /package/src/api/files/{controllers → __tests__}/FileController.spec.ts +0 -0
- /package/src/api/files/{jobs → __tests__}/FileJobs.spec.ts +0 -0
- /package/src/api/files/{services → __tests__}/FileService.spec.ts +0 -0
- /package/src/api/jobs/{primitives → __tests__}/$job-middleware.spec.ts +0 -0
- /package/src/api/parameters/{primitives → __tests__}/$parameter.spec.ts +0 -0
- /package/src/api/users/{primitives → __tests__}/$realm.spec.ts +0 -0
- /package/src/api/users/{controllers → __tests__}/AdminIdentityController.spec.ts +0 -0
- /package/src/api/users/{controllers → __tests__}/AdminSessionController.spec.ts +0 -0
- /package/src/api/users/{controllers → __tests__}/AdminUserController.spec.ts +0 -0
- /package/src/api/users/{services → __tests__}/CredentialService.spec.ts +0 -0
- /package/src/api/users/{providers → __tests__}/RealmProvider.spec.ts +0 -0
- /package/src/api/users/{services → __tests__}/RegistrationService.spec.ts +0 -0
- /package/src/batch/{primitives → __tests__}/$batch.spec.ts +0 -0
- /package/src/batch/{providers → __tests__}/BatchProvider.spec.ts +0 -0
- /package/src/bucket/{primitives → __tests__}/$bucket.spec.ts +0 -0
- /package/src/bucket/{providers → __tests__}/FileStorageProvider.spec.ts +0 -0
- /package/src/bucket/{providers → __tests__}/LocalFileStorageProvider.spec.ts +0 -0
- /package/src/bucket/{providers → __tests__}/MemoryFileStorageProvider.spec.ts +0 -0
- /package/src/cache/core/{primitives → __tests__}/$cache.spec.ts +0 -0
- /package/src/cache/redis/{providers → __tests__}/RedisCacheProvider.spec.ts +0 -0
- /package/src/command/{primitives → __tests__}/$command.spec.ts +0 -0
- /package/src/command/{helpers → __tests__}/Asker.spec.ts +0 -0
- /package/src/command/{helpers → __tests__}/Runner.spec.ts +0 -0
- /package/src/core/{primitives → __tests__}/$context.spec.ts +0 -0
- /package/src/core/{primitives → __tests__}/$env.spec.ts +0 -0
- /package/src/core/{primitives → __tests__}/$hook.spec.ts +0 -0
- /package/src/core/{primitives → __tests__}/$inject.spec.ts +0 -0
- /package/src/core/{primitives → __tests__}/$module.spec.ts +0 -0
- /package/src/core/{providers → __tests__}/CodecManager.spec.ts +0 -0
- /package/src/core/{providers → __tests__}/EventManager.spec.ts +0 -0
- /package/src/core/{providers → __tests__}/StateManager.spec.ts +0 -0
- /package/src/core/{providers → __tests__}/TypeProvider.spec.ts +0 -0
- /package/src/datetime/{primitives → __tests__}/$interval.spec.ts +0 -0
- /package/src/datetime/{providers → __tests__}/DateTimeProvider.spec.ts +0 -0
- /package/src/email/core/{primitives → __tests__}/$email.spec.ts +0 -0
- /package/src/fake/{providers → __tests__}/FakeProvider.spec.ts +0 -0
- /package/src/lock/core/{providers → __tests__}/MemoryLockProvider.spec.ts +0 -0
- /package/src/lock/redis/{providers → __tests__}/RedisLockProvider.spec.ts +0 -0
- /package/src/logger/{primitives → __tests__}/$logger.spec.ts +0 -0
- /package/src/logger/{services → __tests__}/Logger.spec.ts +0 -0
- /package/src/mcp/{primitives → __tests__}/$prompt.spec.ts +0 -0
- /package/src/mcp/{primitives → __tests__}/$resource.spec.ts +0 -0
- /package/src/mcp/{primitives → __tests__}/$tool.spec.ts +0 -0
- /package/src/mcp/{providers → __tests__}/McpServerProvider.spec.ts +0 -0
- /package/src/mcp/{helpers → __tests__}/jsonrpc.spec.ts +0 -0
- /package/src/orm/core/{helpers → __tests__}/parseQueryString.spec.ts +0 -0
- /package/src/queue/core/{primitives → __tests__}/$consumer.spec.ts +0 -0
- /package/src/queue/core/{providers → __tests__}/MemoryQueueProvider.spec.ts +0 -0
- /package/src/queue/core/{providers → __tests__}/WorkerProvider.spec.ts +0 -0
- /package/src/queue/redis/{providers → __tests__}/RedisQueueProvider.spec.ts +0 -0
- /package/src/react/form/{hooks → __tests__}/useForm.browser.spec.tsx +0 -0
- /package/src/react/head/{hooks → __tests__}/useHead.spec.tsx +0 -0
- /package/src/react/i18n/{components → __tests__}/Localize.spec.tsx +0 -0
- /package/src/react/router/{primitives → __tests__}/$page.browser.spec.tsx +0 -0
- /package/src/react/router/{primitives → __tests__}/$page.middleware.spec.tsx +0 -0
- /package/src/react/router/{primitives → __tests__}/$page.spec.tsx +0 -0
- /package/src/react/router/{providers → __tests__}/ReactPreloadProvider.spec.ts +0 -0
- /package/src/react/router/{providers → __tests__}/ReactServerProvider.spec.tsx +0 -0
- /package/src/react/router/{providers → __tests__}/ReactServerTemplateProvider.spec.ts +0 -0
- /package/src/retry/{primitives → __tests__}/$retry.spec.ts +0 -0
- /package/src/retry/{providers → __tests__}/RetryProvider.spec.ts +0 -0
- /package/src/router/{providers → __tests__}/RouterProvider.spec.ts +0 -0
- /package/src/security/{primitives → __tests__}/$issuer.spec.ts +0 -0
- /package/src/security/{primitives → __tests__}/$permission.spec.ts +0 -0
- /package/src/security/{primitives → __tests__}/$role.spec.ts +0 -0
- /package/src/security/{primitives → __tests__}/$serviceAccount.spec.ts +0 -0
- /package/src/security/{providers → __tests__}/SecurityProvider.spec.ts +0 -0
- /package/src/server/cookies/{providers → __tests__}/ServerCookiesProvider.spec.ts +0 -0
- /package/src/server/core/{primitives → __tests__}/$action.spec.ts +0 -0
- /package/src/server/core/{primitives → __tests__}/$middleware.spec.ts +0 -0
- /package/src/server/core/{primitives → __tests__}/$route.spec.ts +0 -0
- /package/src/server/core/{primitives → __tests__}/$sse.spec.ts +0 -0
- /package/src/server/core/{providers → __tests__}/BunHttpServerProvider.bun.spec.ts +0 -0
- /package/src/server/core/{services → __tests__}/HttpClient.spec.ts +0 -0
- /package/src/server/core/{providers → __tests__}/ServerLoggerProvider.spec.ts +0 -0
- /package/src/server/core/{services → __tests__}/UserAgentParser.spec.ts +0 -0
- /package/src/server/cors/{providers → __tests__}/ServerCorsProvider.spec.ts +0 -0
- /package/src/server/etag/{providers → __tests__}/ServerEtagProvider.spec.ts +0 -0
- /package/src/server/health/{providers → __tests__}/ServerHealthProvider.spec.ts +0 -0
- /package/src/server/links/{primitives → __tests__}/$remote.spec.ts +0 -0
- /package/src/server/links/{services → __tests__}/BatchEndpoint.spec.ts +0 -0
- /package/src/server/links/{providers → __tests__}/LinkProvider.spec.ts +0 -0
- /package/src/server/links/{providers → __tests__}/ServerLinksProvider.spec.ts +0 -0
- /package/src/server/metrics/{providers → __tests__}/ServerMetricsProvider.spec.ts +0 -0
- /package/src/server/proxy/{primitives → __tests__}/$proxy.spec.ts +0 -0
- /package/src/server/rate-limit/{providers → __tests__}/ServerRateLimitProvider.spec.ts +0 -0
- /package/src/server/static/{primitives → __tests__}/$serve.spec.ts +0 -0
- /package/src/server/swagger/{primitives → __tests__}/$swagger.spec.ts +0 -0
- /package/src/sms/{primitives → __tests__}/$sms.spec.ts +0 -0
- /package/src/sms/{providers → __tests__}/MemorySmsProvider.spec.ts +0 -0
- /package/src/system/{services → __tests__}/FileDetector.spec.ts +0 -0
- /package/src/system/{providers → __tests__}/NodeFileSystemProvider.spec.ts +0 -0
- /package/src/topic/core/{primitives → __tests__}/$subscriber.spec.ts +0 -0
- /package/src/topic/core/{providers → __tests__}/MemoryTopicProvider.spec.ts +0 -0
- /package/src/topic/redis/{providers → __tests__}/RedisTopicProvider.spec.ts +0 -0
- /package/src/websocket/{primitives → __tests__}/$channel.spec.ts +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Alepha } from "alepha";
|
|
2
2
|
import { FileSystemProvider, MemoryFileSystemProvider } from "alepha/system";
|
|
3
|
-
import {
|
|
3
|
+
import { describe, expect, it, vi } from "vitest";
|
|
4
4
|
import { EmailError } from "../errors/EmailError.ts";
|
|
5
5
|
import {
|
|
6
6
|
LocalEmailProvider,
|
|
@@ -13,7 +13,7 @@ const DEFAULT_DIRECTORY = localEmailOptions.options.default.directory;
|
|
|
13
13
|
|
|
14
14
|
describe("LocalEmailProvider", () => {
|
|
15
15
|
describe("send", () => {
|
|
16
|
-
|
|
16
|
+
it("should successfully send email to local file", async () => {
|
|
17
17
|
const alepha = Alepha.create().with({
|
|
18
18
|
provide: FileSystemProvider,
|
|
19
19
|
use: MemoryFileSystemProvider,
|
|
@@ -35,10 +35,15 @@ describe("LocalEmailProvider", () => {
|
|
|
35
35
|
|
|
36
36
|
expect(memoryFs.writeFileCalls).toHaveLength(1);
|
|
37
37
|
expect(memoryFs.writeFileCalls[0].path).toContain("test@example.com");
|
|
38
|
-
|
|
38
|
+
|
|
39
|
+
const written = JSON.parse(memoryFs.writeFileCalls[0].data as string);
|
|
40
|
+
expect(written.to).toBe(to);
|
|
41
|
+
expect(written.subject).toBe(subject);
|
|
42
|
+
expect(written.body).toBe(body);
|
|
43
|
+
expect(written.sentAt).toBeDefined();
|
|
39
44
|
});
|
|
40
45
|
|
|
41
|
-
|
|
46
|
+
it("should create proper filename with sanitized email and timestamp", async () => {
|
|
42
47
|
const alepha = Alepha.create().with({
|
|
43
48
|
provide: FileSystemProvider,
|
|
44
49
|
use: MemoryFileSystemProvider,
|
|
@@ -65,13 +70,13 @@ describe("LocalEmailProvider", () => {
|
|
|
65
70
|
expect(memoryFs.joinCalls).toHaveLength(1);
|
|
66
71
|
expect(memoryFs.joinCalls[0]).toEqual([
|
|
67
72
|
DEFAULT_DIRECTORY,
|
|
68
|
-
"user_test@example.com
|
|
73
|
+
"user_test@example.com,2023-01-01T12-00-00-000Z.eml.json",
|
|
69
74
|
]);
|
|
70
75
|
|
|
71
76
|
vi.useRealTimers();
|
|
72
77
|
});
|
|
73
78
|
|
|
74
|
-
|
|
79
|
+
it("should sanitize special characters in email address", async () => {
|
|
75
80
|
const alepha = Alepha.create().with({
|
|
76
81
|
provide: FileSystemProvider,
|
|
77
82
|
use: MemoryFileSystemProvider,
|
|
@@ -93,11 +98,11 @@ describe("LocalEmailProvider", () => {
|
|
|
93
98
|
|
|
94
99
|
expect(memoryFs.joinCalls).toHaveLength(1);
|
|
95
100
|
expect(memoryFs.joinCalls[0][1]).toMatch(
|
|
96
|
-
/user_script_@example\.com
|
|
101
|
+
/user_script_@example\.com,.+\.eml\.json/,
|
|
97
102
|
);
|
|
98
103
|
});
|
|
99
104
|
|
|
100
|
-
|
|
105
|
+
it("should create proper JSON content", async () => {
|
|
101
106
|
const alepha = Alepha.create().with({
|
|
102
107
|
provide: FileSystemProvider,
|
|
103
108
|
use: MemoryFileSystemProvider,
|
|
@@ -107,6 +112,9 @@ describe("LocalEmailProvider", () => {
|
|
|
107
112
|
const memoryFs = alepha.inject(MemoryFileSystemProvider);
|
|
108
113
|
await alepha.start();
|
|
109
114
|
|
|
115
|
+
const mockDate = new Date("2023-01-01T12:00:00.000Z");
|
|
116
|
+
vi.setSystemTime(mockDate);
|
|
117
|
+
|
|
110
118
|
const to = "test@example.com";
|
|
111
119
|
const subject = "Test <Subject>";
|
|
112
120
|
const body = "<p>Test body with <strong>HTML</strong></p>";
|
|
@@ -117,18 +125,17 @@ describe("LocalEmailProvider", () => {
|
|
|
117
125
|
body,
|
|
118
126
|
});
|
|
119
127
|
|
|
120
|
-
const
|
|
128
|
+
const content = JSON.parse(memoryFs.writeFileCalls[0].data as string);
|
|
129
|
+
|
|
130
|
+
expect(content.to).toBe(to);
|
|
131
|
+
expect(content.subject).toBe(subject);
|
|
132
|
+
expect(content.body).toBe(body);
|
|
133
|
+
expect(content.sentAt).toBe("2023-01-01T12:00:00.000Z");
|
|
121
134
|
|
|
122
|
-
|
|
123
|
-
expect(htmlContent).toContain("Test <Subject>"); // escaped subject
|
|
124
|
-
expect(htmlContent).toContain("test@example.com");
|
|
125
|
-
expect(htmlContent).toContain(
|
|
126
|
-
"<p>Test body with <strong>HTML</strong></p>",
|
|
127
|
-
); // body not escaped
|
|
128
|
-
expect(htmlContent).toContain("Sent:");
|
|
135
|
+
vi.useRealTimers();
|
|
129
136
|
});
|
|
130
137
|
|
|
131
|
-
|
|
138
|
+
it("should throw EmailError when writeFile fails", async () => {
|
|
132
139
|
const alepha = Alepha.create().with({
|
|
133
140
|
provide: FileSystemProvider,
|
|
134
141
|
use: MemoryFileSystemProvider,
|
|
@@ -161,7 +168,7 @@ describe("LocalEmailProvider", () => {
|
|
|
161
168
|
).rejects.toThrow("Failed to save email to local file: Disk full");
|
|
162
169
|
});
|
|
163
170
|
|
|
164
|
-
|
|
171
|
+
it("should handle non-Error exceptions", async () => {
|
|
165
172
|
const alepha = Alepha.create().with({
|
|
166
173
|
provide: FileSystemProvider,
|
|
167
174
|
use: MemoryFileSystemProvider,
|
|
@@ -194,7 +201,7 @@ describe("LocalEmailProvider", () => {
|
|
|
194
201
|
).rejects.toThrow("Failed to save email to local file: String error");
|
|
195
202
|
});
|
|
196
203
|
|
|
197
|
-
|
|
204
|
+
it("should handle multiple recipients", async () => {
|
|
198
205
|
const alepha = Alepha.create().with({
|
|
199
206
|
provide: FileSystemProvider,
|
|
200
207
|
use: MemoryFileSystemProvider,
|
|
@@ -216,150 +223,32 @@ describe("LocalEmailProvider", () => {
|
|
|
216
223
|
});
|
|
217
224
|
});
|
|
218
225
|
|
|
219
|
-
describe("
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
beforeEach(async () => {
|
|
226
|
+
describe("createEmailJson", () => {
|
|
227
|
+
it("should return structured email data with sentAt timestamp", async () => {
|
|
223
228
|
const alepha = Alepha.create().with({
|
|
224
229
|
provide: FileSystemProvider,
|
|
225
230
|
use: MemoryFileSystemProvider,
|
|
226
231
|
});
|
|
227
|
-
provider = alepha.inject(LocalEmailProvider);
|
|
232
|
+
const provider = alepha.inject(LocalEmailProvider);
|
|
228
233
|
await alepha.start();
|
|
229
|
-
});
|
|
230
234
|
|
|
231
|
-
test("should create proper HTML structure", () => {
|
|
232
235
|
const mockDate = new Date("2023-01-01T12:00:00.000Z");
|
|
233
236
|
vi.setSystemTime(mockDate);
|
|
234
237
|
|
|
235
|
-
const
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
const html = provider.createEmailHtml({
|
|
240
|
-
to,
|
|
241
|
-
subject,
|
|
242
|
-
body,
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
expect(html).toContain("<!DOCTYPE html>");
|
|
246
|
-
expect(html).toContain('<html lang="en">');
|
|
247
|
-
expect(html).toContain("<head>");
|
|
248
|
-
expect(html).toContain("<body>");
|
|
249
|
-
expect(html).toContain("Test Subject");
|
|
250
|
-
expect(html).toContain("test@example.com");
|
|
251
|
-
expect(html).toContain("<p>Test body</p>");
|
|
252
|
-
expect(html).toContain("2023-01-01T12:00:00.000Z");
|
|
253
|
-
|
|
254
|
-
vi.useRealTimers();
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
test("should escape HTML in subject and email address", () => {
|
|
258
|
-
const to = "test<script>@example.com";
|
|
259
|
-
const subject = "Test <Subject> & More";
|
|
260
|
-
const body = "<p>Test body</p>";
|
|
261
|
-
|
|
262
|
-
const html = provider.createEmailHtml({
|
|
263
|
-
to,
|
|
264
|
-
subject,
|
|
265
|
-
body,
|
|
238
|
+
const result = provider.createEmailJson({
|
|
239
|
+
to: "test@example.com",
|
|
240
|
+
subject: "Test Subject",
|
|
241
|
+
body: "<p>Test body</p>",
|
|
266
242
|
});
|
|
267
243
|
|
|
268
|
-
expect(
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
test("should not escape HTML in body content", () => {
|
|
275
|
-
const to = "test@example.com";
|
|
276
|
-
const subject = "Test Subject";
|
|
277
|
-
const body = "<p>Test body with <strong>HTML</strong> & entities</p>";
|
|
278
|
-
|
|
279
|
-
const html = provider.createEmailHtml({
|
|
280
|
-
to,
|
|
281
|
-
subject,
|
|
282
|
-
body,
|
|
244
|
+
expect(result).toEqual({
|
|
245
|
+
to: "test@example.com",
|
|
246
|
+
subject: "Test Subject",
|
|
247
|
+
body: "<p>Test body</p>",
|
|
248
|
+
sentAt: "2023-01-01T12:00:00.000Z",
|
|
283
249
|
});
|
|
284
250
|
|
|
285
|
-
|
|
286
|
-
"<p>Test body with <strong>HTML</strong> & entities</p>",
|
|
287
|
-
);
|
|
288
|
-
});
|
|
289
|
-
|
|
290
|
-
test("should include CSS styles", () => {
|
|
291
|
-
const to = "test@example.com";
|
|
292
|
-
const subject = "Test Subject";
|
|
293
|
-
const body = "<p>Test body</p>";
|
|
294
|
-
|
|
295
|
-
const html = provider.createEmailHtml({
|
|
296
|
-
to,
|
|
297
|
-
subject,
|
|
298
|
-
body,
|
|
299
|
-
});
|
|
300
|
-
|
|
301
|
-
expect(html).toContain("<style>");
|
|
302
|
-
expect(html).toContain("font-family: Arial, sans-serif");
|
|
303
|
-
expect(html).toContain(".email-header");
|
|
304
|
-
expect(html).toContain(".email-body");
|
|
305
|
-
expect(html).toContain(".meta");
|
|
306
|
-
});
|
|
307
|
-
});
|
|
308
|
-
|
|
309
|
-
describe("escapeHtml", () => {
|
|
310
|
-
let provider: LocalEmailProvider;
|
|
311
|
-
|
|
312
|
-
beforeEach(async () => {
|
|
313
|
-
const alepha = Alepha.create().with({
|
|
314
|
-
provide: FileSystemProvider,
|
|
315
|
-
use: MemoryFileSystemProvider,
|
|
316
|
-
});
|
|
317
|
-
provider = alepha.inject(LocalEmailProvider);
|
|
318
|
-
await alepha.start();
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
test("should escape ampersands", () => {
|
|
322
|
-
const result = provider.escapeHtml("Tom & Jerry");
|
|
323
|
-
expect(result).toBe("Tom & Jerry");
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
test("should escape less than signs", () => {
|
|
327
|
-
const result = provider.escapeHtml("5 < 10");
|
|
328
|
-
expect(result).toBe("5 < 10");
|
|
329
|
-
});
|
|
330
|
-
|
|
331
|
-
test("should escape greater than signs", () => {
|
|
332
|
-
const result = provider.escapeHtml("10 > 5");
|
|
333
|
-
expect(result).toBe("10 > 5");
|
|
334
|
-
});
|
|
335
|
-
|
|
336
|
-
test("should escape double quotes", () => {
|
|
337
|
-
const result = provider.escapeHtml('Say "Hello"');
|
|
338
|
-
expect(result).toBe("Say "Hello"");
|
|
339
|
-
});
|
|
340
|
-
|
|
341
|
-
test("should escape single quotes", () => {
|
|
342
|
-
const result = provider.escapeHtml("Don't worry");
|
|
343
|
-
expect(result).toBe("Don't worry");
|
|
344
|
-
});
|
|
345
|
-
|
|
346
|
-
test("should escape multiple special characters", () => {
|
|
347
|
-
const result = provider.escapeHtml(
|
|
348
|
-
'<script>alert("Hello & goodbye")</script>',
|
|
349
|
-
);
|
|
350
|
-
expect(result).toBe(
|
|
351
|
-
"<script>alert("Hello & goodbye")</script>",
|
|
352
|
-
);
|
|
353
|
-
});
|
|
354
|
-
|
|
355
|
-
test("should handle empty string", () => {
|
|
356
|
-
const result = provider.escapeHtml("");
|
|
357
|
-
expect(result).toBe("");
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
test("should handle string with no special characters", () => {
|
|
361
|
-
const result = provider.escapeHtml("Hello World");
|
|
362
|
-
expect(result).toBe("Hello World");
|
|
251
|
+
vi.useRealTimers();
|
|
363
252
|
});
|
|
364
253
|
});
|
|
365
254
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $atom, $hook, $inject, $
|
|
1
|
+
import { $atom, $hook, $inject, $state, type Static, t } from "alepha";
|
|
2
2
|
import { $logger } from "alepha/logger";
|
|
3
3
|
import { FileSystemProvider } from "alepha/system";
|
|
4
4
|
import { EmailError } from "../errors/EmailError.ts";
|
|
@@ -34,7 +34,7 @@ declare module "alepha" {
|
|
|
34
34
|
export class LocalEmailProvider implements EmailProvider {
|
|
35
35
|
protected readonly log = $logger();
|
|
36
36
|
protected readonly fs = $inject(FileSystemProvider);
|
|
37
|
-
protected readonly options = $
|
|
37
|
+
protected readonly options = $state(localEmailOptions);
|
|
38
38
|
|
|
39
39
|
protected get directory(): string {
|
|
40
40
|
return this.options.directory;
|
|
@@ -69,22 +69,14 @@ export class LocalEmailProvider implements EmailProvider {
|
|
|
69
69
|
});
|
|
70
70
|
|
|
71
71
|
try {
|
|
72
|
-
// Create filename: emailcontact+date
|
|
73
72
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
74
73
|
for (const recipient of Array.isArray(to) ? to : [to]) {
|
|
75
74
|
const sanitizedEmail = recipient.replace(/[^a-zA-Z0-9@.-]/g, "_");
|
|
76
|
-
const filename = `${sanitizedEmail}
|
|
75
|
+
const filename = `${sanitizedEmail},${timestamp}.eml.json`;
|
|
77
76
|
const filepath = this.fs.join(this.directory, filename);
|
|
78
77
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
to: recipient,
|
|
82
|
-
subject,
|
|
83
|
-
body,
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
// Write to file
|
|
87
|
-
await this.fs.writeFile(filepath, htmlContent);
|
|
78
|
+
const content = this.createEmailJson({ to: recipient, subject, body });
|
|
79
|
+
await this.fs.writeFile(filepath, JSON.stringify(content, null, 2));
|
|
88
80
|
|
|
89
81
|
this.log.info("Email saved to local file", { filepath, to, subject });
|
|
90
82
|
}
|
|
@@ -95,46 +87,16 @@ export class LocalEmailProvider implements EmailProvider {
|
|
|
95
87
|
}
|
|
96
88
|
}
|
|
97
89
|
|
|
98
|
-
public
|
|
90
|
+
public createEmailJson(options: {
|
|
99
91
|
to: string;
|
|
100
92
|
subject: string;
|
|
101
93
|
body: string;
|
|
102
|
-
}): string {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
<meta charset="UTF-8">
|
|
110
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
111
|
-
<title>${this.escapeHtml(subject)}</title>
|
|
112
|
-
<style>
|
|
113
|
-
body { font-family: Arial, sans-serif; margin: 20px; }
|
|
114
|
-
.email-header { background-color: #f5f5f5; padding: 15px; border-radius: 5px; margin-bottom: 20px; }
|
|
115
|
-
.email-body { background-color: #ffffff; padding: 15px; border: 1px solid #ddd; border-radius: 5px; }
|
|
116
|
-
.meta { font-size: 12px; color: #666; margin-bottom: 10px; }
|
|
117
|
-
</style>
|
|
118
|
-
</head>
|
|
119
|
-
<body>
|
|
120
|
-
<div class="email-header">
|
|
121
|
-
<div class="meta">Sent: ${timestamp}</div>
|
|
122
|
-
<div class="meta">To: ${this.escapeHtml(to)}</div>
|
|
123
|
-
<h1>${this.escapeHtml(subject)}</h1>
|
|
124
|
-
</div>
|
|
125
|
-
<div class="email-body">
|
|
126
|
-
${body}
|
|
127
|
-
</div>
|
|
128
|
-
</body>
|
|
129
|
-
</html>`;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
public escapeHtml(text: string): string {
|
|
133
|
-
return text
|
|
134
|
-
.replace(/&/g, "&")
|
|
135
|
-
.replace(/</g, "<")
|
|
136
|
-
.replace(/>/g, ">")
|
|
137
|
-
.replace(/"/g, """)
|
|
138
|
-
.replace(/'/g, "'");
|
|
94
|
+
}): { to: string; subject: string; body: string; sentAt: string } {
|
|
95
|
+
return {
|
|
96
|
+
to: options.to,
|
|
97
|
+
subject: options.subject,
|
|
98
|
+
body: options.body,
|
|
99
|
+
sentAt: new Date().toISOString(),
|
|
100
|
+
};
|
|
139
101
|
}
|
|
140
102
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $atom, $env, $hook, $
|
|
1
|
+
import { $atom, $env, $hook, $state, type Static, t } from "alepha";
|
|
2
2
|
import {
|
|
3
3
|
EmailError,
|
|
4
4
|
type EmailProvider,
|
|
@@ -127,7 +127,7 @@ declare module "alepha" {
|
|
|
127
127
|
export class NodemailerEmailProvider implements EmailProvider {
|
|
128
128
|
protected readonly env = $env(envSchema);
|
|
129
129
|
protected readonly log = $logger();
|
|
130
|
-
protected readonly options = $
|
|
130
|
+
protected readonly options = $state(nodemailerEmailOptions);
|
|
131
131
|
protected transporter: Transporter | null = null;
|
|
132
132
|
|
|
133
133
|
protected get host(): string {
|
|
@@ -2,7 +2,7 @@ import { $pipeline, Alepha } from "alepha";
|
|
|
2
2
|
import { describe, test } from "vitest";
|
|
3
3
|
import { LockAcquireError } from "../errors/LockAcquireError.ts";
|
|
4
4
|
import { AlephaLock } from "../index.ts";
|
|
5
|
-
import { $lock } from "
|
|
5
|
+
import { $lock } from "../primitives/$lock.ts";
|
|
6
6
|
|
|
7
7
|
describe("$lock middleware", () => {
|
|
8
8
|
test("executes handler when lock is available", async ({ expect }) => {
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
$atom,
|
|
3
3
|
$context,
|
|
4
4
|
$inject,
|
|
5
|
-
$
|
|
5
|
+
$state,
|
|
6
6
|
AlephaError,
|
|
7
7
|
type AsyncFn,
|
|
8
8
|
createMiddleware,
|
|
@@ -391,7 +391,7 @@ export class LockPrimitive<TFunc extends AsyncFn> extends Primitive<
|
|
|
391
391
|
> {
|
|
392
392
|
protected readonly log = $logger();
|
|
393
393
|
protected readonly provider = $inject(LockProvider);
|
|
394
|
-
protected readonly settings = $
|
|
394
|
+
protected readonly settings = $state(lockOptions);
|
|
395
395
|
protected readonly dateTimeProvider = $inject(DateTimeProvider);
|
|
396
396
|
|
|
397
397
|
/**
|
package/src/logger/index.ts
CHANGED
|
@@ -57,14 +57,19 @@ export const AlephaLogger = $module({
|
|
|
57
57
|
const env = alepha.parseEnv(envSchema);
|
|
58
58
|
|
|
59
59
|
// Support DEBUG env var (debug package convention) as shorthand for LOG_LEVEL/LOG_FORMAT.
|
|
60
|
+
// DEBUG=1 → LOG_LEVEL=trace LOG_FORMAT=pretty
|
|
60
61
|
// DEBUG=alepha:* → LOG_LEVEL=alepha.*:debug,info LOG_FORMAT=pretty
|
|
61
62
|
let logLevel = env.LOG_LEVEL;
|
|
62
63
|
let logFormat = env.LOG_FORMAT;
|
|
63
64
|
if (env.DEBUG) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
if (env.DEBUG === "1" || env.DEBUG === "true") {
|
|
66
|
+
logLevel ??= "trace";
|
|
67
|
+
} else {
|
|
68
|
+
const patterns = env.DEBUG.split(",")
|
|
69
|
+
.map((p) => p.trim().replaceAll(":", "."))
|
|
70
|
+
.filter(Boolean);
|
|
71
|
+
logLevel ??= `${patterns.map((p) => `${p}:debug`).join(",")},info`;
|
|
72
|
+
}
|
|
68
73
|
logFormat ??= "pretty";
|
|
69
74
|
}
|
|
70
75
|
|
|
@@ -146,6 +151,7 @@ const envSchema = t.object({
|
|
|
146
151
|
* Enable debug logging for specific modules using the `debug` package convention.
|
|
147
152
|
*
|
|
148
153
|
* @example
|
|
154
|
+
* DEBUG=1 # Shorthand for LOG_LEVEL=trace LOG_FORMAT=pretty
|
|
149
155
|
* DEBUG=alepha:* # Enable debug logging for all alepha modules
|
|
150
156
|
* DEBUG=alepha:orm:* # Enable debug logging for alepha.orm modules
|
|
151
157
|
* DEBUG=* # Enable debug logging for all modules
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $atom, $inject, $
|
|
1
|
+
import { $atom, $inject, $state, t } from "alepha";
|
|
2
2
|
import { $logger } from "alepha/logger";
|
|
3
3
|
import { $route } from "alepha/server";
|
|
4
4
|
import {
|
|
@@ -60,7 +60,7 @@ export const mcpSseOptions = $atom({
|
|
|
60
60
|
*/
|
|
61
61
|
export class SseMcpTransport {
|
|
62
62
|
protected readonly log = $logger();
|
|
63
|
-
protected readonly options = $
|
|
63
|
+
protected readonly options = $state(mcpSseOptions);
|
|
64
64
|
protected readonly mcpServer = $inject(McpServerProvider);
|
|
65
65
|
|
|
66
66
|
/**
|
|
@@ -422,3 +422,56 @@ export const testComplexRelationships = async (alepha: Alepha) => {
|
|
|
422
422
|
await app.products.clear({ force: true });
|
|
423
423
|
await app.categories.clear({ force: true });
|
|
424
424
|
};
|
|
425
|
+
|
|
426
|
+
// ---------------------------------------------------------------------------
|
|
427
|
+
// Expression-based index: LOWER username uniqueness
|
|
428
|
+
// ---------------------------------------------------------------------------
|
|
429
|
+
|
|
430
|
+
const usersWithLowerIndex = $entity({
|
|
431
|
+
name: "users_lower",
|
|
432
|
+
schema: t.object({
|
|
433
|
+
id: db.primaryKey(),
|
|
434
|
+
realm: t.text(),
|
|
435
|
+
username: t.text(),
|
|
436
|
+
}),
|
|
437
|
+
indexes: [
|
|
438
|
+
{
|
|
439
|
+
expressions: (self) => [self.realm, sql`LOWER(${self.username})`],
|
|
440
|
+
unique: true,
|
|
441
|
+
name: "users_lower_realm_username_idx",
|
|
442
|
+
},
|
|
443
|
+
],
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
export const testExpressionIndex = async (alepha: Alepha) => {
|
|
447
|
+
class App {
|
|
448
|
+
users = $repository(usersWithLowerIndex);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
const app = alepha.inject(App);
|
|
452
|
+
await alepha.start();
|
|
453
|
+
|
|
454
|
+
// Insert first user
|
|
455
|
+
await app.users.create({ realm: "default", username: "JohnDoe" });
|
|
456
|
+
|
|
457
|
+
// Same username different case in same realm should fail (unique LOWER index)
|
|
458
|
+
try {
|
|
459
|
+
await app.users.create({ realm: "default", username: "johndoe" });
|
|
460
|
+
expect.fail("Should have thrown unique constraint error");
|
|
461
|
+
} catch (error) {
|
|
462
|
+
expect(error).toBeDefined();
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// Same username different realm should succeed
|
|
466
|
+
await app.users.create({ realm: "other", username: "JohnDoe" });
|
|
467
|
+
|
|
468
|
+
// Different username same realm should succeed
|
|
469
|
+
await app.users.create({ realm: "default", username: "JaneDoe" });
|
|
470
|
+
|
|
471
|
+
// Verify all 3 records exist
|
|
472
|
+
const all = await app.users.findMany({});
|
|
473
|
+
expect(all.length).toBe(3);
|
|
474
|
+
|
|
475
|
+
// Clean up
|
|
476
|
+
await app.users.clear({ force: true });
|
|
477
|
+
};
|
|
@@ -9,6 +9,7 @@ import { PostgresModelBuilder } from "../postgres/services/PostgresModelBuilder.
|
|
|
9
9
|
import {
|
|
10
10
|
testComplexRelationships,
|
|
11
11
|
testCustomConfig,
|
|
12
|
+
testExpressionIndex,
|
|
12
13
|
testModelBuilderFeatures,
|
|
13
14
|
} from "./ModelBuilder-tests.ts";
|
|
14
15
|
|
|
@@ -390,6 +391,51 @@ describe("ModelBuilder", () => {
|
|
|
390
391
|
expect(table.eventId.config.name).toBe("event_id");
|
|
391
392
|
});
|
|
392
393
|
|
|
394
|
+
it("should build table with expression-based index", () => {
|
|
395
|
+
const entity = $entity({
|
|
396
|
+
name: "users",
|
|
397
|
+
schema: t.object({
|
|
398
|
+
id: db.primaryKey(),
|
|
399
|
+
realm: t.text(),
|
|
400
|
+
username: t.text(),
|
|
401
|
+
}),
|
|
402
|
+
indexes: [
|
|
403
|
+
{
|
|
404
|
+
expressions: (self) => [self.realm, sql`LOWER(${self.username})`],
|
|
405
|
+
unique: true,
|
|
406
|
+
name: "users_realm_username_lower_idx",
|
|
407
|
+
},
|
|
408
|
+
],
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
builder.buildTable(entity, options);
|
|
412
|
+
|
|
413
|
+
expect(options.tables.has("users")).toBe(true);
|
|
414
|
+
const table = options.tables.get("users");
|
|
415
|
+
expect(table).toBeDefined();
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
it("should build table with expression-only index", () => {
|
|
419
|
+
const entity = $entity({
|
|
420
|
+
name: "users",
|
|
421
|
+
schema: t.object({
|
|
422
|
+
id: db.primaryKey(),
|
|
423
|
+
email: t.email(),
|
|
424
|
+
}),
|
|
425
|
+
indexes: [
|
|
426
|
+
{
|
|
427
|
+
expressions: (self) => [sql`LOWER(${self.email})`],
|
|
428
|
+
unique: true,
|
|
429
|
+
name: "users_email_lower_idx",
|
|
430
|
+
},
|
|
431
|
+
],
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
builder.buildTable(entity, options);
|
|
435
|
+
|
|
436
|
+
expect(options.tables.has("users")).toBe(true);
|
|
437
|
+
});
|
|
438
|
+
|
|
393
439
|
it("should not recreate table if it already exists", () => {
|
|
394
440
|
const entity = $entity({
|
|
395
441
|
name: "users",
|
|
@@ -560,6 +606,30 @@ describe("ModelBuilder", () => {
|
|
|
560
606
|
expect(table).toBeDefined();
|
|
561
607
|
});
|
|
562
608
|
|
|
609
|
+
it("should build table with expression-based index", () => {
|
|
610
|
+
const entity = $entity({
|
|
611
|
+
name: "users",
|
|
612
|
+
schema: t.object({
|
|
613
|
+
id: db.primaryKey(),
|
|
614
|
+
realm: t.text(),
|
|
615
|
+
username: t.text(),
|
|
616
|
+
}),
|
|
617
|
+
indexes: [
|
|
618
|
+
{
|
|
619
|
+
expressions: (self) => [self.realm, sql`LOWER(${self.username})`],
|
|
620
|
+
unique: true,
|
|
621
|
+
name: "users_realm_username_lower_idx",
|
|
622
|
+
},
|
|
623
|
+
],
|
|
624
|
+
});
|
|
625
|
+
|
|
626
|
+
builder.buildTable(entity, options);
|
|
627
|
+
|
|
628
|
+
expect(options.tables.has("users")).toBe(true);
|
|
629
|
+
const table = options.tables.get("users");
|
|
630
|
+
expect(table).toBeDefined();
|
|
631
|
+
});
|
|
632
|
+
|
|
563
633
|
it("should throw error for sequences", () => {
|
|
564
634
|
expect(() => {
|
|
565
635
|
builder.buildSequence({ name: "test_seq", options: {} } as any, {
|
|
@@ -832,5 +902,15 @@ describe("ModelBuilder", () => {
|
|
|
832
902
|
it("should handle complex nested relationships (postgres)", async () => {
|
|
833
903
|
await testComplexRelationships(Alepha.create().with(AlephaOrmPostgres));
|
|
834
904
|
});
|
|
905
|
+
|
|
906
|
+
it("should enforce LOWER expression unique index (sqlite)", async () => {
|
|
907
|
+
await testExpressionIndex(
|
|
908
|
+
Alepha.create({ env: { DATABASE_URL: "sqlite://:memory:" } }),
|
|
909
|
+
);
|
|
910
|
+
});
|
|
911
|
+
|
|
912
|
+
it("should enforce LOWER expression unique index (postgres)", async () => {
|
|
913
|
+
await testExpressionIndex(Alepha.create().with(AlephaOrmPostgres));
|
|
914
|
+
});
|
|
835
915
|
});
|
|
836
916
|
});
|