alepha 0.15.0 → 0.15.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -98
- package/dist/api/audits/index.d.ts +630 -653
- package/dist/api/audits/index.d.ts.map +1 -1
- package/dist/api/audits/index.js +12 -35
- package/dist/api/audits/index.js.map +1 -1
- package/dist/api/files/index.d.ts +365 -358
- package/dist/api/files/index.d.ts.map +1 -1
- package/dist/api/files/index.js +12 -5
- package/dist/api/files/index.js.map +1 -1
- package/dist/api/jobs/index.d.ts +255 -248
- package/dist/api/jobs/index.d.ts.map +1 -1
- package/dist/api/jobs/index.js +10 -3
- package/dist/api/jobs/index.js.map +1 -1
- package/dist/api/keys/index.d.ts +413 -0
- package/dist/api/keys/index.d.ts.map +1 -0
- package/dist/api/keys/index.js +476 -0
- package/dist/api/keys/index.js.map +1 -0
- package/dist/api/notifications/index.browser.js +4 -4
- package/dist/api/notifications/index.browser.js.map +1 -1
- package/dist/api/notifications/index.d.ts +84 -78
- package/dist/api/notifications/index.d.ts.map +1 -1
- package/dist/api/notifications/index.js +14 -8
- package/dist/api/notifications/index.js.map +1 -1
- package/dist/api/parameters/index.d.ts +528 -535
- package/dist/api/parameters/index.d.ts.map +1 -1
- package/dist/api/parameters/index.js +30 -37
- package/dist/api/parameters/index.js.map +1 -1
- package/dist/api/users/index.d.ts +1221 -910
- package/dist/api/users/index.d.ts.map +1 -1
- package/dist/api/users/index.js +2556 -248
- package/dist/api/users/index.js.map +1 -1
- package/dist/api/verifications/index.d.ts +142 -136
- package/dist/api/verifications/index.d.ts.map +1 -1
- package/dist/api/verifications/index.js +12 -4
- package/dist/api/verifications/index.js.map +1 -1
- package/dist/batch/index.d.ts +142 -162
- package/dist/batch/index.d.ts.map +1 -1
- package/dist/batch/index.js +31 -44
- package/dist/batch/index.js.map +1 -1
- package/dist/bucket/index.d.ts +595 -171
- package/dist/bucket/index.d.ts.map +1 -1
- package/dist/bucket/index.js +1856 -12
- package/dist/bucket/index.js.map +1 -1
- package/dist/cache/core/index.d.ts +225 -53
- package/dist/cache/core/index.d.ts.map +1 -1
- package/dist/cache/core/index.js +213 -7
- package/dist/cache/core/index.js.map +1 -1
- package/dist/cache/redis/index.d.ts +1 -0
- package/dist/cache/redis/index.d.ts.map +1 -1
- package/dist/cache/redis/index.js +6 -2
- package/dist/cache/redis/index.js.map +1 -1
- package/dist/cli/index.d.ts +834 -226
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +2872 -417
- package/dist/cli/index.js.map +1 -1
- package/dist/command/index.d.ts +458 -310
- package/dist/command/index.d.ts.map +1 -1
- package/dist/command/index.js +2011 -76
- package/dist/command/index.js.map +1 -1
- package/dist/core/index.browser.js +309 -97
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +796 -701
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +329 -97
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js +309 -97
- package/dist/core/index.native.js.map +1 -1
- package/dist/datetime/index.d.ts +59 -44
- package/dist/datetime/index.d.ts.map +1 -1
- package/dist/datetime/index.js +15 -0
- package/dist/datetime/index.js.map +1 -1
- package/dist/email/index.d.ts +314 -19
- package/dist/email/index.d.ts.map +1 -1
- package/dist/email/index.js +1852 -7
- package/dist/email/index.js.map +1 -1
- package/dist/fake/index.d.ts +5500 -5418
- package/dist/fake/index.d.ts.map +1 -1
- package/dist/fake/index.js +113 -42
- package/dist/fake/index.js.map +1 -1
- package/dist/lock/core/index.d.ts +219 -212
- package/dist/lock/core/index.d.ts.map +1 -1
- package/dist/lock/core/index.js +11 -4
- package/dist/lock/core/index.js.map +1 -1
- package/dist/lock/redis/index.d.ts.map +1 -1
- package/dist/logger/index.d.ts +41 -90
- package/dist/logger/index.d.ts.map +1 -1
- package/dist/logger/index.js +15 -68
- package/dist/logger/index.js.map +1 -1
- package/dist/mcp/index.d.ts +228 -230
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +32 -31
- package/dist/mcp/index.js.map +1 -1
- package/dist/orm/index.browser.js +12 -12
- package/dist/orm/index.browser.js.map +1 -1
- package/dist/orm/index.bun.js +90 -80
- package/dist/orm/index.bun.js.map +1 -1
- package/dist/orm/index.d.ts +1434 -1459
- package/dist/orm/index.d.ts.map +1 -1
- package/dist/orm/index.js +112 -130
- package/dist/orm/index.js.map +1 -1
- package/dist/queue/core/index.d.ts +262 -254
- package/dist/queue/core/index.d.ts.map +1 -1
- package/dist/queue/core/index.js +14 -6
- package/dist/queue/core/index.js.map +1 -1
- package/dist/queue/redis/index.d.ts.map +1 -1
- package/dist/react/auth/index.browser.js +108 -0
- package/dist/react/auth/index.browser.js.map +1 -0
- package/dist/react/auth/index.d.ts +100 -0
- package/dist/react/auth/index.d.ts.map +1 -0
- package/dist/react/auth/index.js +145 -0
- package/dist/react/auth/index.js.map +1 -0
- package/dist/react/core/index.d.ts +469 -0
- package/dist/react/core/index.d.ts.map +1 -0
- package/dist/react/core/index.js +464 -0
- package/dist/react/core/index.js.map +1 -0
- package/dist/react/form/index.d.ts +232 -0
- package/dist/react/form/index.d.ts.map +1 -0
- package/dist/react/form/index.js +432 -0
- package/dist/react/form/index.js.map +1 -0
- package/dist/react/head/index.browser.js +423 -0
- package/dist/react/head/index.browser.js.map +1 -0
- package/dist/react/head/index.d.ts +288 -0
- package/dist/react/head/index.d.ts.map +1 -0
- package/dist/react/head/index.js +465 -0
- package/dist/react/head/index.js.map +1 -0
- package/dist/react/i18n/index.d.ts +175 -0
- package/dist/react/i18n/index.d.ts.map +1 -0
- package/dist/react/i18n/index.js +224 -0
- package/dist/react/i18n/index.js.map +1 -0
- package/dist/react/router/index.browser.js +1980 -0
- package/dist/react/router/index.browser.js.map +1 -0
- package/dist/react/router/index.d.ts +2068 -0
- package/dist/react/router/index.d.ts.map +1 -0
- package/dist/react/router/index.js +4932 -0
- package/dist/react/router/index.js.map +1 -0
- package/dist/react/websocket/index.d.ts +117 -0
- package/dist/react/websocket/index.d.ts.map +1 -0
- package/dist/react/websocket/index.js +107 -0
- package/dist/react/websocket/index.js.map +1 -0
- package/dist/redis/index.bun.js +4 -0
- package/dist/redis/index.bun.js.map +1 -1
- package/dist/redis/index.d.ts +127 -130
- package/dist/redis/index.d.ts.map +1 -1
- package/dist/redis/index.js +16 -25
- package/dist/redis/index.js.map +1 -1
- package/dist/retry/index.d.ts +80 -71
- package/dist/retry/index.d.ts.map +1 -1
- package/dist/retry/index.js +11 -2
- package/dist/retry/index.js.map +1 -1
- package/dist/router/index.d.ts +6 -6
- package/dist/router/index.d.ts.map +1 -1
- package/dist/scheduler/index.d.ts +119 -28
- package/dist/scheduler/index.d.ts.map +1 -1
- package/dist/scheduler/index.js +404 -3
- package/dist/scheduler/index.js.map +1 -1
- package/dist/security/index.d.ts +642 -228
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +1579 -37
- package/dist/security/index.js.map +1 -1
- package/dist/server/auth/index.d.ts +1141 -111
- package/dist/server/auth/index.d.ts.map +1 -1
- package/dist/server/auth/index.js +1261 -25
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/cache/index.d.ts +63 -78
- package/dist/server/cache/index.d.ts.map +1 -1
- package/dist/server/cache/index.js +7 -22
- package/dist/server/cache/index.js.map +1 -1
- package/dist/server/compress/index.d.ts +13 -5
- package/dist/server/compress/index.d.ts.map +1 -1
- package/dist/server/compress/index.js +10 -2
- package/dist/server/compress/index.js.map +1 -1
- package/dist/server/cookies/index.d.ts +46 -22
- package/dist/server/cookies/index.d.ts.map +1 -1
- package/dist/server/cookies/index.js +7 -5
- package/dist/server/cookies/index.js.map +1 -1
- package/dist/server/core/index.d.ts +307 -196
- package/dist/server/core/index.d.ts.map +1 -1
- package/dist/server/core/index.js +271 -38
- package/dist/server/core/index.js.map +1 -1
- package/dist/server/cors/index.d.ts +24 -34
- package/dist/server/cors/index.d.ts.map +1 -1
- package/dist/server/cors/index.js +7 -21
- package/dist/server/cors/index.js.map +1 -1
- package/dist/server/health/index.d.ts +25 -19
- package/dist/server/health/index.d.ts.map +1 -1
- package/dist/server/health/index.js +8 -2
- package/dist/server/health/index.js.map +1 -1
- package/dist/server/helmet/index.d.ts +13 -5
- package/dist/server/helmet/index.d.ts.map +1 -1
- package/dist/server/helmet/index.js +11 -3
- package/dist/server/helmet/index.js.map +1 -1
- package/dist/server/links/index.browser.js +9 -1
- package/dist/server/links/index.browser.js.map +1 -1
- package/dist/server/links/index.d.ts +133 -128
- package/dist/server/links/index.d.ts.map +1 -1
- package/dist/server/links/index.js +24 -11
- package/dist/server/links/index.js.map +1 -1
- package/dist/server/metrics/index.d.ts +524 -4
- package/dist/server/metrics/index.d.ts.map +1 -1
- package/dist/server/metrics/index.js +4472 -7
- package/dist/server/metrics/index.js.map +1 -1
- package/dist/server/multipart/index.d.ts +15 -9
- package/dist/server/multipart/index.d.ts.map +1 -1
- package/dist/server/multipart/index.js +9 -3
- package/dist/server/multipart/index.js.map +1 -1
- package/dist/server/proxy/index.d.ts +110 -104
- package/dist/server/proxy/index.d.ts.map +1 -1
- package/dist/server/proxy/index.js +8 -2
- package/dist/server/proxy/index.js.map +1 -1
- package/dist/server/rate-limit/index.d.ts +46 -51
- package/dist/server/rate-limit/index.d.ts.map +1 -1
- package/dist/server/rate-limit/index.js +18 -55
- package/dist/server/rate-limit/index.js.map +1 -1
- package/dist/server/static/index.d.ts +181 -48
- package/dist/server/static/index.d.ts.map +1 -1
- package/dist/server/static/index.js +1848 -5
- package/dist/server/static/index.js.map +1 -1
- package/dist/server/swagger/index.d.ts +348 -53
- package/dist/server/swagger/index.d.ts.map +1 -1
- package/dist/server/swagger/index.js +1849 -6
- package/dist/server/swagger/index.js.map +1 -1
- package/dist/sms/index.d.ts +312 -18
- package/dist/sms/index.d.ts.map +1 -1
- package/dist/sms/index.js +1854 -10
- package/dist/sms/index.js.map +1 -1
- package/dist/system/index.browser.js +496 -0
- package/dist/system/index.browser.js.map +1 -0
- package/dist/system/index.d.ts +1158 -0
- package/dist/system/index.d.ts.map +1 -0
- package/dist/{file → system}/index.js +412 -20
- package/dist/system/index.js.map +1 -0
- package/dist/thread/index.d.ts +82 -73
- package/dist/thread/index.d.ts.map +1 -1
- package/dist/thread/index.js +13 -4
- package/dist/thread/index.js.map +1 -1
- package/dist/topic/core/index.d.ts +330 -323
- package/dist/topic/core/index.d.ts.map +1 -1
- package/dist/topic/core/index.js +12 -5
- package/dist/topic/core/index.js.map +1 -1
- package/dist/topic/redis/index.d.ts +6 -6
- package/dist/topic/redis/index.d.ts.map +1 -1
- package/dist/vite/index.d.ts +163 -5825
- package/dist/vite/index.d.ts.map +1 -1
- package/dist/vite/index.js +130 -477
- package/dist/vite/index.js.map +1 -1
- package/dist/websocket/index.browser.js +3 -3
- package/dist/websocket/index.browser.js.map +1 -1
- package/dist/websocket/index.d.ts +287 -283
- package/dist/websocket/index.d.ts.map +1 -1
- package/dist/websocket/index.js +15 -11
- package/dist/websocket/index.js.map +1 -1
- package/package.json +86 -17
- package/src/api/audits/index.ts +10 -33
- package/src/api/files/__tests__/$bucket.spec.ts +1 -1
- package/src/api/files/controllers/AdminFileStatsController.spec.ts +1 -1
- package/src/api/files/controllers/FileController.spec.ts +1 -1
- package/src/api/files/index.ts +10 -3
- package/src/api/files/jobs/FileJobs.spec.ts +1 -1
- package/src/api/files/services/FileService.spec.ts +1 -1
- package/src/api/jobs/index.ts +10 -3
- package/src/api/keys/controllers/AdminApiKeyController.ts +75 -0
- package/src/api/keys/controllers/ApiKeyController.ts +103 -0
- package/src/api/keys/entities/apiKeyEntity.ts +41 -0
- package/src/api/keys/index.ts +49 -0
- package/src/api/keys/schemas/adminApiKeyQuerySchema.ts +7 -0
- package/src/api/keys/schemas/adminApiKeyResourceSchema.ts +17 -0
- package/src/api/keys/schemas/createApiKeyBodySchema.ts +7 -0
- package/src/api/keys/schemas/createApiKeyResponseSchema.ts +11 -0
- package/src/api/keys/schemas/listApiKeyResponseSchema.ts +15 -0
- package/src/api/keys/schemas/revokeApiKeyParamsSchema.ts +5 -0
- package/src/api/keys/schemas/revokeApiKeyResponseSchema.ts +5 -0
- package/src/api/keys/services/ApiKeyService.spec.ts +553 -0
- package/src/api/keys/services/ApiKeyService.ts +306 -0
- package/src/api/logs/TODO.md +52 -0
- package/src/api/notifications/index.ts +10 -4
- package/src/api/parameters/index.ts +9 -30
- package/src/api/parameters/primitives/$config.ts +12 -4
- package/src/api/parameters/services/ConfigStore.ts +9 -3
- package/src/api/users/__tests__/ApiKeys-integration.spec.ts +1035 -0
- package/src/api/users/__tests__/ApiKeys.spec.ts +401 -0
- package/src/api/users/index.ts +14 -3
- package/src/api/users/primitives/$realm.ts +33 -5
- package/src/api/users/providers/RealmProvider.ts +1 -12
- package/src/api/users/services/SessionService.ts +1 -11
- package/src/api/verifications/controllers/VerificationController.ts +2 -0
- package/src/api/verifications/index.ts +10 -4
- package/src/batch/index.ts +9 -36
- package/src/batch/primitives/$batch.ts +0 -8
- package/src/batch/providers/BatchProvider.ts +29 -2
- package/src/bucket/__tests__/shared.ts +1 -1
- package/src/bucket/index.ts +13 -6
- package/src/bucket/primitives/$bucket.ts +1 -1
- package/src/bucket/providers/LocalFileStorageProvider.ts +1 -1
- package/src/bucket/providers/MemoryFileStorageProvider.ts +1 -1
- package/src/cache/core/__tests__/shared.ts +30 -0
- package/src/cache/core/index.ts +11 -6
- package/src/cache/core/primitives/$cache.spec.ts +5 -0
- package/src/cache/core/providers/CacheProvider.ts +17 -0
- package/src/cache/core/providers/MemoryCacheProvider.ts +300 -1
- package/src/cache/redis/__tests__/cache-redis.spec.ts +5 -0
- package/src/cache/redis/providers/RedisCacheProvider.ts +9 -0
- package/src/cli/apps/AlephaCli.ts +3 -16
- package/src/cli/apps/AlephaPackageBuilderCli.ts +10 -2
- package/src/cli/atoms/appEntryOptions.ts +13 -0
- package/src/cli/atoms/buildOptions.ts +1 -1
- package/src/cli/atoms/changelogOptions.ts +1 -1
- package/src/cli/commands/build.ts +64 -52
- package/src/cli/commands/db.ts +17 -11
- package/src/cli/commands/deploy.ts +1 -1
- package/src/cli/commands/dev.ts +13 -49
- package/src/cli/commands/gen/env.ts +6 -3
- package/src/cli/commands/gen/openapi.ts +5 -2
- package/src/cli/commands/init.spec.ts +544 -0
- package/src/cli/commands/init.ts +101 -58
- package/src/cli/commands/lint.ts +8 -2
- package/src/cli/commands/typecheck.ts +11 -0
- package/src/cli/defineConfig.ts +9 -0
- package/src/cli/index.ts +2 -1
- package/src/cli/providers/AppEntryProvider.ts +131 -0
- package/src/cli/providers/ViteBuildProvider.ts +40 -0
- package/src/cli/providers/ViteDevServerProvider.ts +378 -0
- package/src/cli/services/AlephaCliUtils.ts +39 -93
- package/src/cli/services/PackageManagerUtils.ts +140 -17
- package/src/cli/services/ProjectScaffolder.ts +169 -101
- package/src/cli/services/ViteUtils.ts +82 -0
- package/src/cli/{assets/claudeMd.ts → templates/agentMd.ts} +41 -28
- package/src/cli/{assets → templates}/apiHelloControllerTs.ts +2 -1
- package/src/cli/{assets → templates}/biomeJson.ts +2 -1
- package/src/cli/{assets → templates}/dummySpecTs.ts +2 -1
- package/src/cli/{assets → templates}/editorconfig.ts +2 -1
- package/src/cli/templates/gitignore.ts +39 -0
- package/src/cli/{assets → templates}/mainBrowserTs.ts +2 -1
- package/src/cli/templates/mainCss.ts +33 -0
- package/src/cli/templates/mainServerTs.ts +33 -0
- package/src/cli/{assets → templates}/tsconfigJson.ts +2 -1
- package/src/cli/templates/webAppRouterTs.ts +50 -0
- package/src/cli/templates/webHelloComponentTsx.ts +20 -0
- package/src/command/helpers/Runner.spec.ts +4 -0
- package/src/command/helpers/Runner.ts +3 -21
- package/src/command/index.ts +12 -4
- package/src/command/providers/CliProvider.spec.ts +1067 -0
- package/src/command/providers/CliProvider.ts +203 -40
- package/src/core/Alepha.ts +3 -9
- package/src/core/__tests__/Alepha-start.spec.ts +4 -4
- package/src/core/helpers/jsonSchemaToTypeBox.spec.ts +771 -0
- package/src/core/helpers/jsonSchemaToTypeBox.ts +62 -10
- package/src/core/index.shared.ts +1 -0
- package/src/core/index.ts +20 -0
- package/src/core/primitives/$module.ts +12 -0
- package/src/core/providers/EventManager.spec.ts +0 -71
- package/src/core/providers/EventManager.ts +3 -15
- package/src/core/providers/Json.ts +2 -14
- package/src/core/providers/KeylessJsonSchemaCodec.spec.ts +257 -0
- package/src/core/providers/KeylessJsonSchemaCodec.ts +396 -14
- package/src/core/providers/SchemaValidator.spec.ts +236 -0
- package/src/datetime/index.ts +15 -0
- package/src/email/index.ts +10 -5
- package/src/email/providers/LocalEmailProvider.spec.ts +1 -1
- package/src/email/providers/LocalEmailProvider.ts +1 -1
- package/src/fake/__tests__/keyName.example.ts +1 -1
- package/src/fake/__tests__/keyName.spec.ts +5 -5
- package/src/fake/index.ts +9 -6
- package/src/fake/providers/FakeProvider.spec.ts +258 -40
- package/src/fake/providers/FakeProvider.ts +133 -19
- package/src/lock/core/index.ts +11 -4
- package/src/logger/index.ts +17 -66
- package/src/logger/providers/PrettyFormatterProvider.ts +0 -9
- package/src/mcp/errors/McpError.ts +30 -0
- package/src/mcp/index.ts +13 -27
- package/src/mcp/transports/SseMcpTransport.ts +6 -7
- package/src/orm/__tests__/PostgresProvider.spec.ts +2 -2
- package/src/orm/index.browser.ts +2 -2
- package/src/orm/index.bun.ts +4 -2
- package/src/orm/index.ts +21 -47
- package/src/orm/providers/DrizzleKitProvider.ts +3 -5
- package/src/orm/providers/drivers/BunSqliteProvider.ts +1 -0
- package/src/orm/services/Repository.ts +18 -3
- package/src/queue/core/index.ts +14 -6
- package/src/react/auth/__tests__/$auth.spec.ts +202 -0
- package/src/react/auth/hooks/useAuth.ts +32 -0
- package/src/react/auth/index.browser.ts +13 -0
- package/src/react/auth/index.shared.ts +2 -0
- package/src/react/auth/index.ts +48 -0
- package/src/react/auth/providers/ReactAuthProvider.ts +16 -0
- package/src/react/auth/services/ReactAuth.ts +135 -0
- package/src/react/core/__tests__/Router.spec.tsx +169 -0
- package/src/react/core/components/ClientOnly.tsx +49 -0
- package/src/react/core/components/ErrorBoundary.tsx +73 -0
- package/src/react/core/contexts/AlephaContext.ts +7 -0
- package/src/react/core/contexts/AlephaProvider.tsx +42 -0
- package/src/react/core/hooks/useAction.browser.spec.tsx +569 -0
- package/src/react/core/hooks/useAction.ts +480 -0
- package/src/react/core/hooks/useAlepha.ts +26 -0
- package/src/react/core/hooks/useClient.ts +17 -0
- package/src/react/core/hooks/useEvents.ts +51 -0
- package/src/react/core/hooks/useInject.ts +12 -0
- package/src/react/core/hooks/useStore.ts +52 -0
- package/src/react/core/index.ts +90 -0
- package/src/react/form/components/FormState.tsx +17 -0
- package/src/react/form/errors/FormValidationError.ts +18 -0
- package/src/react/form/hooks/useForm.browser.spec.tsx +366 -0
- package/src/react/form/hooks/useForm.ts +47 -0
- package/src/react/form/hooks/useFormState.ts +130 -0
- package/src/react/form/index.ts +44 -0
- package/src/react/form/services/FormModel.ts +614 -0
- package/src/react/head/helpers/SeoExpander.spec.ts +203 -0
- package/src/react/head/helpers/SeoExpander.ts +142 -0
- package/src/react/head/hooks/useHead.spec.tsx +288 -0
- package/src/react/head/hooks/useHead.ts +62 -0
- package/src/react/head/index.browser.ts +26 -0
- package/src/react/head/index.ts +44 -0
- package/src/react/head/interfaces/Head.ts +105 -0
- package/src/react/head/primitives/$head.ts +25 -0
- package/src/react/head/providers/BrowserHeadProvider.browser.spec.ts +196 -0
- package/src/react/head/providers/BrowserHeadProvider.ts +212 -0
- package/src/react/head/providers/HeadProvider.ts +168 -0
- package/src/react/head/providers/ServerHeadProvider.ts +31 -0
- package/src/react/i18n/__tests__/integration.spec.tsx +239 -0
- package/src/react/i18n/components/Localize.spec.tsx +357 -0
- package/src/react/i18n/components/Localize.tsx +35 -0
- package/src/react/i18n/hooks/useI18n.browser.spec.tsx +438 -0
- package/src/react/i18n/hooks/useI18n.ts +18 -0
- package/src/react/i18n/index.ts +41 -0
- package/src/react/i18n/primitives/$dictionary.ts +69 -0
- package/src/react/i18n/providers/I18nProvider.spec.ts +389 -0
- package/src/react/i18n/providers/I18nProvider.ts +278 -0
- package/src/react/router/__tests__/page-head-browser.browser.spec.ts +95 -0
- package/src/react/router/__tests__/page-head.spec.ts +48 -0
- package/src/react/router/__tests__/seo-head.spec.ts +125 -0
- package/src/react/router/atoms/ssrManifestAtom.ts +58 -0
- package/src/react/router/components/ErrorViewer.tsx +872 -0
- package/src/react/router/components/Link.tsx +23 -0
- package/src/react/router/components/NestedView.tsx +223 -0
- package/src/react/router/components/NotFound.tsx +30 -0
- package/src/react/router/constants/PAGE_PRELOAD_KEY.ts +6 -0
- package/src/react/router/contexts/RouterLayerContext.ts +12 -0
- package/src/react/router/errors/Redirection.ts +28 -0
- package/src/react/router/hooks/useActive.ts +52 -0
- package/src/react/router/hooks/useQueryParams.ts +63 -0
- package/src/react/router/hooks/useRouter.ts +20 -0
- package/src/react/router/hooks/useRouterState.ts +11 -0
- package/src/react/router/index.browser.ts +45 -0
- package/src/react/router/index.shared.ts +19 -0
- package/src/react/router/index.ts +142 -0
- package/src/react/router/primitives/$page.browser.spec.tsx +851 -0
- package/src/react/router/primitives/$page.spec.tsx +708 -0
- package/src/react/router/primitives/$page.ts +497 -0
- package/src/react/router/providers/ReactBrowserProvider.ts +309 -0
- package/src/react/router/providers/ReactBrowserRendererProvider.ts +25 -0
- package/src/react/router/providers/ReactBrowserRouterProvider.ts +168 -0
- package/src/react/router/providers/ReactPageProvider.ts +726 -0
- package/src/react/router/providers/ReactServerProvider.spec.tsx +316 -0
- package/src/react/router/providers/ReactServerProvider.ts +558 -0
- package/src/react/router/providers/ReactServerTemplateProvider.ts +979 -0
- package/src/react/router/providers/SSRManifestProvider.ts +334 -0
- package/src/react/router/services/ReactPageServerService.ts +48 -0
- package/src/react/router/services/ReactPageService.ts +27 -0
- package/src/react/router/services/ReactRouter.ts +262 -0
- package/src/react/websocket/hooks/useRoom.tsx +242 -0
- package/src/react/websocket/index.ts +7 -0
- package/src/redis/__tests__/redis.spec.ts +13 -0
- package/src/redis/index.ts +9 -25
- package/src/redis/providers/BunRedisProvider.ts +9 -0
- package/src/redis/providers/NodeRedisProvider.ts +8 -0
- package/src/redis/providers/RedisProvider.ts +16 -0
- package/src/retry/index.ts +11 -2
- package/src/router/index.ts +15 -0
- package/src/scheduler/index.ts +11 -2
- package/src/security/__tests__/BasicAuth.spec.ts +2 -0
- package/src/security/__tests__/ServerSecurityProvider.spec.ts +13 -5
- package/src/security/index.ts +15 -10
- package/src/security/interfaces/IssuerResolver.ts +27 -0
- package/src/security/primitives/$issuer.ts +55 -0
- package/src/security/providers/SecurityProvider.ts +179 -0
- package/src/security/providers/ServerBasicAuthProvider.ts +6 -2
- package/src/security/providers/ServerSecurityProvider.ts +36 -22
- package/src/server/auth/index.ts +12 -7
- package/src/server/cache/index.ts +7 -22
- package/src/server/compress/index.ts +10 -2
- package/src/server/cookies/index.ts +7 -5
- package/src/server/cookies/primitives/$cookie.ts +33 -11
- package/src/server/core/index.ts +17 -7
- package/src/server/core/interfaces/ServerRequest.ts +83 -1
- package/src/server/core/primitives/$action.spec.ts +1 -1
- package/src/server/core/primitives/$action.ts +8 -3
- package/src/server/core/providers/BunHttpServerProvider.ts +1 -1
- package/src/server/core/providers/NodeHttpServerProvider.spec.ts +125 -0
- package/src/server/core/providers/NodeHttpServerProvider.ts +77 -22
- package/src/server/core/providers/ServerLoggerProvider.ts +2 -2
- package/src/server/core/providers/ServerProvider.ts +9 -12
- package/src/server/core/services/ServerRequestParser.spec.ts +520 -0
- package/src/server/core/services/ServerRequestParser.ts +306 -13
- package/src/server/cors/index.ts +7 -21
- package/src/server/cors/primitives/$cors.ts +6 -2
- package/src/server/health/index.ts +8 -2
- package/src/server/helmet/index.ts +11 -3
- package/src/server/links/atoms/apiLinksAtom.ts +7 -0
- package/src/server/links/index.browser.ts +2 -0
- package/src/server/links/index.ts +13 -6
- package/src/server/metrics/index.ts +10 -3
- package/src/server/multipart/index.ts +9 -3
- package/src/server/proxy/index.ts +8 -2
- package/src/server/rate-limit/index.ts +21 -25
- package/src/server/rate-limit/primitives/$rateLimit.ts +6 -2
- package/src/server/rate-limit/providers/ServerRateLimitProvider.spec.ts +38 -14
- package/src/server/rate-limit/providers/ServerRateLimitProvider.ts +22 -56
- package/src/server/static/index.ts +8 -2
- package/src/server/static/providers/ServerStaticProvider.ts +1 -1
- package/src/server/swagger/index.ts +9 -4
- package/src/server/swagger/providers/ServerSwaggerProvider.ts +1 -1
- package/src/sms/index.ts +9 -5
- package/src/sms/providers/LocalSmsProvider.spec.ts +1 -1
- package/src/sms/providers/LocalSmsProvider.ts +1 -1
- package/src/system/index.browser.ts +11 -0
- package/src/system/index.ts +62 -0
- package/src/{file → system}/providers/FileSystemProvider.ts +16 -0
- package/src/{file → system}/providers/MemoryFileSystemProvider.ts +116 -3
- package/src/system/providers/MemoryShellProvider.ts +164 -0
- package/src/{file → system}/providers/NodeFileSystemProvider.spec.ts +2 -2
- package/src/{file → system}/providers/NodeFileSystemProvider.ts +36 -0
- package/src/system/providers/NodeShellProvider.ts +184 -0
- package/src/system/providers/ShellProvider.ts +74 -0
- package/src/{file → system}/services/FileDetector.spec.ts +2 -2
- package/src/thread/index.ts +11 -2
- package/src/topic/core/index.ts +12 -5
- package/src/vite/index.ts +3 -2
- package/src/vite/tasks/buildClient.ts +2 -8
- package/src/vite/tasks/buildServer.ts +84 -21
- package/src/vite/tasks/copyAssets.ts +5 -4
- package/src/vite/tasks/generateSitemap.ts +64 -23
- package/src/vite/tasks/index.ts +0 -2
- package/src/vite/tasks/prerenderPages.ts +49 -24
- package/src/websocket/index.ts +12 -8
- package/dist/file/index.d.ts +0 -839
- package/dist/file/index.d.ts.map +0 -1
- package/dist/file/index.js.map +0 -1
- package/src/cli/assets/indexHtml.ts +0 -15
- package/src/cli/assets/mainServerTs.ts +0 -24
- package/src/cli/assets/webAppRouterTs.ts +0 -15
- package/src/cli/assets/webHelloComponentTsx.ts +0 -16
- package/src/cli/commands/format.ts +0 -23
- package/src/file/index.ts +0 -43
- package/src/vite/helpers/boot.ts +0 -117
- package/src/vite/plugins/viteAlephaDev.ts +0 -177
- package/src/vite/tasks/devServer.ts +0 -71
- package/src/vite/tasks/runAlepha.ts +0 -270
- /package/dist/orm/{chunk-DtkW-qnP.js → chunk-DH6iiROE.js} +0 -0
- /package/src/cli/{assets → templates}/apiIndexTs.ts +0 -0
- /package/src/cli/{assets → templates}/webIndexTs.ts +0 -0
- /package/src/{file → system}/errors/FileError.ts +0 -0
- /package/src/{file → system}/services/FileDetector.ts +0 -0
|
@@ -32,8 +32,11 @@ export interface JsonSchemaObject {
|
|
|
32
32
|
minItems?: number;
|
|
33
33
|
maxItems?: number;
|
|
34
34
|
uniqueItems?: boolean;
|
|
35
|
-
//
|
|
36
|
-
"~
|
|
35
|
+
// Alepha text options (trim, lowercase)
|
|
36
|
+
"~options"?: {
|
|
37
|
+
trim?: boolean;
|
|
38
|
+
lowercase?: boolean;
|
|
39
|
+
};
|
|
37
40
|
// Not supported
|
|
38
41
|
oneOf?: JsonSchemaObject[];
|
|
39
42
|
anyOf?: JsonSchemaObject[];
|
|
@@ -55,11 +58,13 @@ export interface JsonSchemaObject {
|
|
|
55
58
|
* - Nested objects with required/optional properties
|
|
56
59
|
* - Arrays with item schemas
|
|
57
60
|
* - Common validation options: minLength, maxLength, minimum, maximum, pattern
|
|
61
|
+
* - anyOf/oneOf/allOf with nullable patterns (e.g., `anyOf: [type, null]` → `t.nullable(type)`)
|
|
62
|
+
* - Alepha ~options (trim, lowercase) pass-through
|
|
58
63
|
*
|
|
59
64
|
* **Not supported:**
|
|
60
|
-
* - oneOf, anyOf, allOf, not (composition schemas)
|
|
61
65
|
* - $ref (references)
|
|
62
66
|
* - additionalProperties, patternProperties
|
|
67
|
+
* - Complex composition schemas (multiple non-null types in anyOf/oneOf/allOf)
|
|
63
68
|
*
|
|
64
69
|
* @param schema - JSON Schema object to convert
|
|
65
70
|
* @returns TypeBox TSchema
|
|
@@ -85,12 +90,7 @@ export interface JsonSchemaObject {
|
|
|
85
90
|
* // })
|
|
86
91
|
* ```
|
|
87
92
|
*/
|
|
88
|
-
export function jsonSchemaToTypeBox(schema: JsonSchemaObject):
|
|
89
|
-
// If it already has TypeBox marker, return as-is
|
|
90
|
-
if (schema["~kind"]) {
|
|
91
|
-
return schema as unknown as TSchema;
|
|
92
|
-
}
|
|
93
|
-
|
|
93
|
+
export function jsonSchemaToTypeBox(schema: JsonSchemaObject): any {
|
|
94
94
|
// Handle const (literal)
|
|
95
95
|
if (schema.const !== undefined) {
|
|
96
96
|
return t.const(schema.const as string | number | boolean);
|
|
@@ -115,6 +115,53 @@ export function jsonSchemaToTypeBox(schema: JsonSchemaObject): TSchema {
|
|
|
115
115
|
);
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
+
// Handle anyOf (typically used for nullable types: anyOf: [type, null])
|
|
119
|
+
if (schema.anyOf && Array.isArray(schema.anyOf)) {
|
|
120
|
+
const nullSchema = schema.anyOf.find((s) => s.type === "null");
|
|
121
|
+
const nonNullSchemas = schema.anyOf.filter((s) => s.type !== "null");
|
|
122
|
+
|
|
123
|
+
// If anyOf is [someType, null], convert to t.nullable(someType)
|
|
124
|
+
if (nullSchema && nonNullSchemas.length === 1) {
|
|
125
|
+
const converted = jsonSchemaToTypeBox(nonNullSchemas[0]);
|
|
126
|
+
return t.nullable(converted);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// For other anyOf cases, create a union
|
|
130
|
+
return t.union(schema.anyOf.map((s) => jsonSchemaToTypeBox(s)));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Handle allOf (merge schemas)
|
|
134
|
+
if (schema.allOf && Array.isArray(schema.allOf)) {
|
|
135
|
+
const nullSchema = schema.allOf.find((s) => s.type === "null");
|
|
136
|
+
const nonNullSchemas = schema.allOf.filter((s) => s.type !== "null");
|
|
137
|
+
|
|
138
|
+
// If allOf includes null, convert to nullable
|
|
139
|
+
if (nullSchema && nonNullSchemas.length === 1) {
|
|
140
|
+
const converted = jsonSchemaToTypeBox(nonNullSchemas[0]);
|
|
141
|
+
return t.nullable(converted);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// For other allOf cases, merge the first non-null schema (simplified)
|
|
145
|
+
if (nonNullSchemas.length > 0) {
|
|
146
|
+
return jsonSchemaToTypeBox(nonNullSchemas[0]);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Handle oneOf (similar to anyOf)
|
|
151
|
+
if (schema.oneOf && Array.isArray(schema.oneOf)) {
|
|
152
|
+
const nullSchema = schema.oneOf.find((s) => s.type === "null");
|
|
153
|
+
const nonNullSchemas = schema.oneOf.filter((s) => s.type !== "null");
|
|
154
|
+
|
|
155
|
+
// If oneOf is [someType, null], convert to t.nullable(someType)
|
|
156
|
+
if (nullSchema && nonNullSchemas.length === 1) {
|
|
157
|
+
const converted = jsonSchemaToTypeBox(nonNullSchemas[0]);
|
|
158
|
+
return t.nullable(converted);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// For other oneOf cases, create a union
|
|
162
|
+
return t.union(schema.oneOf.map((s) => jsonSchemaToTypeBox(s)));
|
|
163
|
+
}
|
|
164
|
+
|
|
118
165
|
// Handle type
|
|
119
166
|
const type = Array.isArray(schema.type) ? schema.type[0] : schema.type;
|
|
120
167
|
|
|
@@ -158,7 +205,7 @@ function filterUndefined<T extends Record<string, unknown>>(
|
|
|
158
205
|
* Convert JSON Schema string type to TypeBox.
|
|
159
206
|
*/
|
|
160
207
|
function convertString(schema: JsonSchemaObject): TSchema {
|
|
161
|
-
const
|
|
208
|
+
const baseOptions: TStringOptions = filterUndefined({
|
|
162
209
|
title: schema.title,
|
|
163
210
|
description: schema.description,
|
|
164
211
|
default: schema.default as string,
|
|
@@ -167,6 +214,11 @@ function convertString(schema: JsonSchemaObject): TSchema {
|
|
|
167
214
|
pattern: schema.pattern,
|
|
168
215
|
});
|
|
169
216
|
|
|
217
|
+
// Preserve ~options if present (for t.text() compatibility)
|
|
218
|
+
const options: TStringOptions = schema["~options"]
|
|
219
|
+
? { ...baseOptions, "~options": schema["~options"] }
|
|
220
|
+
: baseOptions;
|
|
221
|
+
|
|
170
222
|
switch (schema.format) {
|
|
171
223
|
case "email":
|
|
172
224
|
return t.email(options);
|
package/src/core/index.shared.ts
CHANGED
|
@@ -27,6 +27,7 @@ export * from "./primitives/$use.ts";
|
|
|
27
27
|
export * from "./providers/AlsProvider.ts";
|
|
28
28
|
export * from "./providers/CodecManager.ts";
|
|
29
29
|
export * from "./providers/EventManager.ts";
|
|
30
|
+
export * from "./providers/Json.ts";
|
|
30
31
|
export * from "./providers/JsonSchemaCodec.ts";
|
|
31
32
|
export * from "./providers/KeylessJsonSchemaCodec.ts";
|
|
32
33
|
export * from "./providers/SchemaCodec.ts";
|
package/src/core/index.ts
CHANGED
|
@@ -22,6 +22,26 @@ export * from "./index.shared.ts";
|
|
|
22
22
|
|
|
23
23
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* | type | quality | stability |
|
|
27
|
+
* |------|---------|-----------|
|
|
28
|
+
* | tooling | epic | stable |
|
|
29
|
+
*
|
|
30
|
+
* Foundation of the entire framework with dependency injection and lifecycle management.
|
|
31
|
+
*
|
|
32
|
+
* **Features:**
|
|
33
|
+
* - Dependency injection for services
|
|
34
|
+
* - Service substitution/mocking
|
|
35
|
+
* - Type-safe environment variable loading with TypeBox schemas
|
|
36
|
+
* - Lifecycle hooks (start, stop, log, etc.)
|
|
37
|
+
* - Module definitions and composition
|
|
38
|
+
* - Request-scoped context access via Async Local Storage (ALS)
|
|
39
|
+
* - Reactive state management with atoms
|
|
40
|
+
* - Cluster mode with automatic worker forking
|
|
41
|
+
* - Full TypeScript generics and type inference
|
|
42
|
+
*
|
|
43
|
+
* @module alepha.core
|
|
44
|
+
*/
|
|
25
45
|
export const AlephaCore = $module({
|
|
26
46
|
name: "alepha.core",
|
|
27
47
|
services: [
|
|
@@ -4,6 +4,7 @@ import { MODULE } from "../constants/MODULE.ts";
|
|
|
4
4
|
import { AlephaError } from "../errors/AlephaError.ts";
|
|
5
5
|
import type { PrimitiveFactoryLike } from "../helpers/primitive.ts";
|
|
6
6
|
import type { Service } from "../interfaces/Service.ts";
|
|
7
|
+
import type { Atom } from "./$atom.ts";
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Wrap Services and Primitives into a Module.
|
|
@@ -69,6 +70,12 @@ export const $module = <T extends object = {}>(
|
|
|
69
70
|
options = options;
|
|
70
71
|
|
|
71
72
|
register(alepha: Alepha): void {
|
|
73
|
+
if (options.atoms) {
|
|
74
|
+
for (const atom of options.atoms) {
|
|
75
|
+
alepha.store.register(atom);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
72
79
|
if (typeof options.register === "function") {
|
|
73
80
|
options.register(alepha);
|
|
74
81
|
return;
|
|
@@ -134,6 +141,11 @@ export interface ModulePrimitiveOptions {
|
|
|
134
141
|
* Again, if you declare 'register', you must handle the registration of ALL services manually.
|
|
135
142
|
*/
|
|
136
143
|
register?: (alepha: Alepha) => void;
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* List of atoms to register in the module.
|
|
147
|
+
*/
|
|
148
|
+
atoms?: Array<Atom<any>>;
|
|
137
149
|
}
|
|
138
150
|
|
|
139
151
|
/**
|
|
@@ -285,77 +285,6 @@ describe("EventManager", () => {
|
|
|
285
285
|
});
|
|
286
286
|
});
|
|
287
287
|
|
|
288
|
-
describe("reverse execution order", () => {
|
|
289
|
-
it("should execute hooks in reverse order when reverse option is true", async () => {
|
|
290
|
-
const eventManager = new EventManager();
|
|
291
|
-
const order: number[] = [];
|
|
292
|
-
|
|
293
|
-
eventManager.on("echo", async () => {
|
|
294
|
-
order.push(1);
|
|
295
|
-
});
|
|
296
|
-
eventManager.on("echo", async () => {
|
|
297
|
-
order.push(2);
|
|
298
|
-
});
|
|
299
|
-
eventManager.on("echo", async () => {
|
|
300
|
-
order.push(3);
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
await eventManager.emit("echo", {}, { reverse: true });
|
|
304
|
-
|
|
305
|
-
expect(order).toEqual([3, 2, 1]);
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
it("should reverse priorities correctly", async () => {
|
|
309
|
-
const eventManager = new EventManager();
|
|
310
|
-
const order: string[] = [];
|
|
311
|
-
|
|
312
|
-
eventManager.on("echo", {
|
|
313
|
-
callback: async () => {
|
|
314
|
-
order.push("first");
|
|
315
|
-
},
|
|
316
|
-
priority: "first",
|
|
317
|
-
});
|
|
318
|
-
eventManager.on("echo", async () => {
|
|
319
|
-
order.push("normal");
|
|
320
|
-
});
|
|
321
|
-
eventManager.on("echo", {
|
|
322
|
-
callback: async () => {
|
|
323
|
-
order.push("last");
|
|
324
|
-
},
|
|
325
|
-
priority: "last",
|
|
326
|
-
});
|
|
327
|
-
|
|
328
|
-
await eventManager.emit("echo", {}, { reverse: true });
|
|
329
|
-
|
|
330
|
-
// Reversed: last -> normal -> first
|
|
331
|
-
expect(order).toEqual(["last", "normal", "first"]);
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
it("should work with stop lifecycle event", async () => {
|
|
335
|
-
const alepha = Alepha.create();
|
|
336
|
-
const order: string[] = [];
|
|
337
|
-
|
|
338
|
-
alepha.events.on("start", async () => {
|
|
339
|
-
order.push("start-1");
|
|
340
|
-
});
|
|
341
|
-
alepha.events.on("start", async () => {
|
|
342
|
-
order.push("start-2");
|
|
343
|
-
});
|
|
344
|
-
alepha.events.on("stop", async () => {
|
|
345
|
-
order.push("stop-1");
|
|
346
|
-
});
|
|
347
|
-
alepha.events.on("stop", async () => {
|
|
348
|
-
order.push("stop-2");
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
await alepha.start();
|
|
352
|
-
await alepha.stop();
|
|
353
|
-
|
|
354
|
-
// Start should be in order, stop should be reversed
|
|
355
|
-
expect(order).toEqual(["start-1", "start-2", "stop-2", "stop-1"]);
|
|
356
|
-
});
|
|
357
|
-
});
|
|
358
|
-
|
|
359
288
|
describe("error handling", () => {
|
|
360
289
|
it("should throw error when callback throws", async () => {
|
|
361
290
|
const eventManager = new EventManager();
|
|
@@ -189,13 +189,6 @@ export class EventManager {
|
|
|
189
189
|
func: T,
|
|
190
190
|
payload: Hooks[T],
|
|
191
191
|
options: {
|
|
192
|
-
/**
|
|
193
|
-
* If true, the hooks will be executed in reverse order.
|
|
194
|
-
* This is useful for "stop" hooks that should be executed in reverse order.
|
|
195
|
-
*
|
|
196
|
-
* @default false
|
|
197
|
-
*/
|
|
198
|
-
reverse?: boolean;
|
|
199
192
|
/**
|
|
200
193
|
* If true, the hooks will be logged with their execution time.
|
|
201
194
|
*
|
|
@@ -216,8 +209,8 @@ export class EventManager {
|
|
|
216
209
|
return;
|
|
217
210
|
}
|
|
218
211
|
|
|
219
|
-
// Fast path: single listener, no logging
|
|
220
|
-
if (events.length === 1 && !options.log
|
|
212
|
+
// Fast path: single listener, no logging
|
|
213
|
+
if (events.length === 1 && !options.log) {
|
|
221
214
|
const hook = events[0];
|
|
222
215
|
try {
|
|
223
216
|
const result = hook.callback(payload);
|
|
@@ -244,12 +237,7 @@ export class EventManager {
|
|
|
244
237
|
this.log?.trace(`${String(func)} ...`);
|
|
245
238
|
}
|
|
246
239
|
|
|
247
|
-
|
|
248
|
-
if (options.reverse) {
|
|
249
|
-
eventList = events.toReversed();
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
for (const hook of eventList) {
|
|
240
|
+
for (const hook of events) {
|
|
253
241
|
const name = hook.caller?.name ?? "unknown";
|
|
254
242
|
if (options.log) {
|
|
255
243
|
ctx.now2 = performance.now();
|
|
@@ -4,18 +4,6 @@
|
|
|
4
4
|
* Used across the codebase via dependency injection.
|
|
5
5
|
*/
|
|
6
6
|
export class Json {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
replacer?: (this: any, key: string, value: any) => any,
|
|
10
|
-
space?: string | number,
|
|
11
|
-
): string {
|
|
12
|
-
return JSON.stringify(value, replacer, space);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
public parse(
|
|
16
|
-
text: string,
|
|
17
|
-
reviver?: (this: any, key: string, value: any) => any,
|
|
18
|
-
) {
|
|
19
|
-
return JSON.parse(text, reviver);
|
|
20
|
-
}
|
|
7
|
+
stringify = JSON.stringify;
|
|
8
|
+
parse = JSON.parse;
|
|
21
9
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Alepha, t } from "alepha";
|
|
2
2
|
import { describe, test } from "vitest";
|
|
3
|
+
import { KeylessJsonSchemaCodec } from "./KeylessJsonSchemaCodec.ts";
|
|
3
4
|
|
|
4
5
|
describe("KeylessJsonSchemaCodec", () => {
|
|
5
6
|
describe("Basic types", () => {
|
|
@@ -618,4 +619,260 @@ describe("KeylessJsonSchemaCodec", () => {
|
|
|
618
619
|
expect(keylessSize).toBeLessThan(jsonSize);
|
|
619
620
|
});
|
|
620
621
|
});
|
|
622
|
+
|
|
623
|
+
describe("Safe Mode (Interpreted)", () => {
|
|
624
|
+
test("should work correctly in safe mode", async ({ expect }) => {
|
|
625
|
+
const alepha = Alepha.create();
|
|
626
|
+
const codec = alepha.inject(KeylessJsonSchemaCodec);
|
|
627
|
+
|
|
628
|
+
// Force safe mode (no Function compilation)
|
|
629
|
+
codec.configure({ useFunctionCompilation: false });
|
|
630
|
+
|
|
631
|
+
const schema = t.object({
|
|
632
|
+
name: t.text(),
|
|
633
|
+
age: t.integer(),
|
|
634
|
+
active: t.boolean(),
|
|
635
|
+
});
|
|
636
|
+
|
|
637
|
+
const data = {
|
|
638
|
+
name: "Alice",
|
|
639
|
+
age: 30,
|
|
640
|
+
active: true,
|
|
641
|
+
};
|
|
642
|
+
|
|
643
|
+
const encoded = codec.encodeToString(schema, data);
|
|
644
|
+
expect(encoded).toBe('["Alice",30,true]');
|
|
645
|
+
|
|
646
|
+
const decoded = codec.decode(schema, encoded);
|
|
647
|
+
expect(decoded).toEqual(data);
|
|
648
|
+
});
|
|
649
|
+
|
|
650
|
+
test("should handle nested objects in safe mode", async ({ expect }) => {
|
|
651
|
+
const alepha = Alepha.create();
|
|
652
|
+
const codec = alepha.inject(KeylessJsonSchemaCodec);
|
|
653
|
+
|
|
654
|
+
codec.configure({ useFunctionCompilation: false });
|
|
655
|
+
|
|
656
|
+
const schema = t.object({
|
|
657
|
+
user: t.object({
|
|
658
|
+
name: t.text(),
|
|
659
|
+
profile: t.object({
|
|
660
|
+
bio: t.text(),
|
|
661
|
+
age: t.integer(),
|
|
662
|
+
}),
|
|
663
|
+
}),
|
|
664
|
+
});
|
|
665
|
+
|
|
666
|
+
const data = {
|
|
667
|
+
user: {
|
|
668
|
+
name: "Alice",
|
|
669
|
+
profile: {
|
|
670
|
+
bio: "Developer",
|
|
671
|
+
age: 30,
|
|
672
|
+
},
|
|
673
|
+
},
|
|
674
|
+
};
|
|
675
|
+
|
|
676
|
+
const encoded = codec.encodeToString(schema, data);
|
|
677
|
+
expect(encoded).toBe('[["Alice",["Developer",30]]]');
|
|
678
|
+
|
|
679
|
+
const decoded = codec.decode(schema, encoded);
|
|
680
|
+
expect(decoded).toEqual(data);
|
|
681
|
+
});
|
|
682
|
+
|
|
683
|
+
test("should handle arrays of objects in safe mode", async ({ expect }) => {
|
|
684
|
+
const alepha = Alepha.create();
|
|
685
|
+
const codec = alepha.inject(KeylessJsonSchemaCodec);
|
|
686
|
+
|
|
687
|
+
codec.configure({ useFunctionCompilation: false });
|
|
688
|
+
|
|
689
|
+
const schema = t.object({
|
|
690
|
+
users: t.array(
|
|
691
|
+
t.object({
|
|
692
|
+
name: t.text(),
|
|
693
|
+
age: t.integer(),
|
|
694
|
+
}),
|
|
695
|
+
),
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
const data = {
|
|
699
|
+
users: [
|
|
700
|
+
{ name: "Alice", age: 30 },
|
|
701
|
+
{ name: "Bob", age: 25 },
|
|
702
|
+
],
|
|
703
|
+
};
|
|
704
|
+
|
|
705
|
+
const encoded = codec.encodeToString(schema, data);
|
|
706
|
+
const decoded = codec.decode(schema, encoded);
|
|
707
|
+
expect(decoded).toEqual(data);
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
test("should handle optional fields in safe mode", async ({ expect }) => {
|
|
711
|
+
const alepha = Alepha.create();
|
|
712
|
+
const codec = alepha.inject(KeylessJsonSchemaCodec);
|
|
713
|
+
|
|
714
|
+
codec.configure({ useFunctionCompilation: false });
|
|
715
|
+
|
|
716
|
+
const schema = t.object({
|
|
717
|
+
name: t.text(),
|
|
718
|
+
bio: t.optional(t.text()),
|
|
719
|
+
});
|
|
720
|
+
|
|
721
|
+
// With optional field
|
|
722
|
+
const dataWithBio = { name: "Alice", bio: "Developer" };
|
|
723
|
+
const encodedWith = codec.encodeToString(schema, dataWithBio);
|
|
724
|
+
const decodedWith = codec.decode(schema, encodedWith);
|
|
725
|
+
expect(decodedWith).toEqual(dataWithBio);
|
|
726
|
+
|
|
727
|
+
// Without optional field
|
|
728
|
+
const dataWithoutBio = { name: "Bob" };
|
|
729
|
+
const encodedWithout = codec.encodeToString(schema, dataWithoutBio);
|
|
730
|
+
const decodedWithout = codec.decode<{ name: string; bio?: string }>(
|
|
731
|
+
schema,
|
|
732
|
+
encodedWithout,
|
|
733
|
+
);
|
|
734
|
+
expect(decodedWithout.name).toBe("Bob");
|
|
735
|
+
expect(decodedWithout.bio).toBeUndefined();
|
|
736
|
+
});
|
|
737
|
+
|
|
738
|
+
test("should handle nullable fields in safe mode", async ({ expect }) => {
|
|
739
|
+
const alepha = Alepha.create();
|
|
740
|
+
const codec = alepha.inject(KeylessJsonSchemaCodec);
|
|
741
|
+
|
|
742
|
+
codec.configure({ useFunctionCompilation: false });
|
|
743
|
+
|
|
744
|
+
const schema = t.object({
|
|
745
|
+
name: t.text(),
|
|
746
|
+
deletedAt: t.nullable(t.datetime()),
|
|
747
|
+
});
|
|
748
|
+
|
|
749
|
+
// With null value
|
|
750
|
+
const dataNull = { name: "Alice", deletedAt: null };
|
|
751
|
+
const encodedNull = codec.encodeToString(schema, dataNull);
|
|
752
|
+
const decodedNull = codec.decode<{
|
|
753
|
+
name: string;
|
|
754
|
+
deletedAt: string | null;
|
|
755
|
+
}>(schema, encodedNull);
|
|
756
|
+
expect(decodedNull.deletedAt).toBeNull();
|
|
757
|
+
|
|
758
|
+
// With non-null value
|
|
759
|
+
const dataValue = { name: "Bob", deletedAt: "2024-01-15T10:00:00Z" };
|
|
760
|
+
const encodedValue = codec.encodeToString(schema, dataValue);
|
|
761
|
+
const decodedValue = codec.decode(schema, encodedValue);
|
|
762
|
+
expect(decodedValue).toEqual(dataValue);
|
|
763
|
+
});
|
|
764
|
+
});
|
|
765
|
+
|
|
766
|
+
describe("Compiled Mode (Function)", () => {
|
|
767
|
+
test("should work correctly in compiled mode", async ({ expect }) => {
|
|
768
|
+
const alepha = Alepha.create();
|
|
769
|
+
const codec = alepha.inject(KeylessJsonSchemaCodec);
|
|
770
|
+
|
|
771
|
+
// Force compiled mode
|
|
772
|
+
codec.configure({ useFunctionCompilation: true });
|
|
773
|
+
|
|
774
|
+
const schema = t.object({
|
|
775
|
+
name: t.text(),
|
|
776
|
+
age: t.integer(),
|
|
777
|
+
active: t.boolean(),
|
|
778
|
+
});
|
|
779
|
+
|
|
780
|
+
const data = {
|
|
781
|
+
name: "Alice",
|
|
782
|
+
age: 30,
|
|
783
|
+
active: true,
|
|
784
|
+
};
|
|
785
|
+
|
|
786
|
+
const encoded = codec.encodeToString(schema, data);
|
|
787
|
+
expect(encoded).toBe('["Alice",30,true]');
|
|
788
|
+
|
|
789
|
+
const decoded = codec.decode(schema, encoded);
|
|
790
|
+
expect(decoded).toEqual(data);
|
|
791
|
+
});
|
|
792
|
+
|
|
793
|
+
test("should produce same results as safe mode", async ({ expect }) => {
|
|
794
|
+
const alepha = Alepha.create();
|
|
795
|
+
|
|
796
|
+
const codecSafe = alepha.inject(KeylessJsonSchemaCodec);
|
|
797
|
+
codecSafe.configure({ useFunctionCompilation: false });
|
|
798
|
+
|
|
799
|
+
// Create a second Alepha instance for the compiled codec
|
|
800
|
+
const alepha2 = Alepha.create();
|
|
801
|
+
const codecCompiled = alepha2.inject(KeylessJsonSchemaCodec);
|
|
802
|
+
codecCompiled.configure({ useFunctionCompilation: true });
|
|
803
|
+
|
|
804
|
+
const schema = t.object({
|
|
805
|
+
user: t.object({
|
|
806
|
+
name: t.text(),
|
|
807
|
+
age: t.integer(),
|
|
808
|
+
}),
|
|
809
|
+
tags: t.array(t.text()),
|
|
810
|
+
active: t.boolean(),
|
|
811
|
+
});
|
|
812
|
+
|
|
813
|
+
const data = {
|
|
814
|
+
user: { name: "Alice", age: 30 },
|
|
815
|
+
tags: ["dev", "typescript"],
|
|
816
|
+
active: true,
|
|
817
|
+
};
|
|
818
|
+
|
|
819
|
+
const encodedSafe = codecSafe.encodeToString(schema, data);
|
|
820
|
+
const encodedCompiled = codecCompiled.encodeToString(schema, data);
|
|
821
|
+
|
|
822
|
+
// Both modes should produce the same output
|
|
823
|
+
expect(encodedSafe).toBe(encodedCompiled);
|
|
824
|
+
|
|
825
|
+
const decodedSafe = codecSafe.decode(schema, encodedSafe);
|
|
826
|
+
const decodedCompiled = codecCompiled.decode(schema, encodedCompiled);
|
|
827
|
+
|
|
828
|
+
// Both modes should decode to the same result
|
|
829
|
+
expect(decodedSafe).toEqual(data);
|
|
830
|
+
expect(decodedCompiled).toEqual(data);
|
|
831
|
+
});
|
|
832
|
+
});
|
|
833
|
+
|
|
834
|
+
describe("Configuration", () => {
|
|
835
|
+
test("should allow configuring options", async ({ expect }) => {
|
|
836
|
+
const alepha = Alepha.create();
|
|
837
|
+
const codec = alepha.inject(KeylessJsonSchemaCodec);
|
|
838
|
+
|
|
839
|
+
// Configure all options
|
|
840
|
+
codec.configure({
|
|
841
|
+
useFunctionCompilation: false,
|
|
842
|
+
maxArrayLength: 100,
|
|
843
|
+
maxStringLength: 1000,
|
|
844
|
+
maxDepth: 10,
|
|
845
|
+
});
|
|
846
|
+
|
|
847
|
+
// Test that configuration works by encoding/decoding
|
|
848
|
+
const schema = t.object({ name: t.text() });
|
|
849
|
+
const data = { name: "test" };
|
|
850
|
+
|
|
851
|
+
const encoded = codec.encodeToString(schema, data);
|
|
852
|
+
const decoded = codec.decode(schema, encoded);
|
|
853
|
+
|
|
854
|
+
expect(decoded).toEqual(data);
|
|
855
|
+
});
|
|
856
|
+
|
|
857
|
+
test("should clear cache when compilation mode changes", async ({
|
|
858
|
+
expect,
|
|
859
|
+
}) => {
|
|
860
|
+
const alepha = Alepha.create();
|
|
861
|
+
const codec = alepha.inject(KeylessJsonSchemaCodec);
|
|
862
|
+
|
|
863
|
+
const schema = t.object({ name: t.text() });
|
|
864
|
+
const data = { name: "test" };
|
|
865
|
+
|
|
866
|
+
// Use compiled mode first
|
|
867
|
+
codec.configure({ useFunctionCompilation: true });
|
|
868
|
+
const encoded1 = codec.encodeToString(schema, data);
|
|
869
|
+
|
|
870
|
+
// Switch to safe mode (cache should be cleared)
|
|
871
|
+
codec.configure({ useFunctionCompilation: false });
|
|
872
|
+
const encoded2 = codec.encodeToString(schema, data);
|
|
873
|
+
|
|
874
|
+
// Both should produce the same result
|
|
875
|
+
expect(encoded1).toBe(encoded2);
|
|
876
|
+
});
|
|
877
|
+
});
|
|
621
878
|
});
|