alepha 0.15.1 → 0.15.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -80
- package/dist/api/audits/index.d.ts +10 -33
- package/dist/api/audits/index.d.ts.map +1 -1
- package/dist/api/audits/index.js +10 -33
- package/dist/api/audits/index.js.map +1 -1
- package/dist/api/files/index.d.ts +10 -3
- package/dist/api/files/index.d.ts.map +1 -1
- package/dist/api/files/index.js +10 -3
- package/dist/api/files/index.js.map +1 -1
- package/dist/api/jobs/index.d.ts +162 -155
- package/dist/api/jobs/index.d.ts.map +1 -1
- package/dist/api/jobs/index.js +10 -3
- package/dist/api/jobs/index.js.map +1 -1
- package/dist/api/keys/index.d.ts +413 -0
- package/dist/api/keys/index.d.ts.map +1 -0
- package/dist/api/keys/index.js +476 -0
- package/dist/api/keys/index.js.map +1 -0
- package/dist/api/notifications/index.d.ts +10 -4
- package/dist/api/notifications/index.d.ts.map +1 -1
- package/dist/api/notifications/index.js +10 -4
- package/dist/api/notifications/index.js.map +1 -1
- package/dist/api/parameters/index.d.ts +43 -50
- package/dist/api/parameters/index.d.ts.map +1 -1
- package/dist/api/parameters/index.js +30 -37
- package/dist/api/parameters/index.js.map +1 -1
- package/dist/api/users/index.d.ts +1081 -760
- package/dist/api/users/index.d.ts.map +1 -1
- package/dist/api/users/index.js +2539 -218
- package/dist/api/users/index.js.map +1 -1
- package/dist/api/verifications/index.d.ts +138 -132
- package/dist/api/verifications/index.d.ts.map +1 -1
- package/dist/api/verifications/index.js +12 -4
- package/dist/api/verifications/index.js.map +1 -1
- package/dist/batch/index.d.ts +20 -40
- package/dist/batch/index.d.ts.map +1 -1
- package/dist/batch/index.js +31 -44
- package/dist/batch/index.js.map +1 -1
- package/dist/bucket/index.d.ts +440 -8
- package/dist/bucket/index.d.ts.map +1 -1
- package/dist/bucket/index.js +1861 -12
- package/dist/bucket/index.js.map +1 -1
- package/dist/cache/core/index.d.ts +179 -7
- package/dist/cache/core/index.d.ts.map +1 -1
- package/dist/cache/core/index.js +213 -7
- package/dist/cache/core/index.js.map +1 -1
- package/dist/cache/redis/index.d.ts +1 -0
- package/dist/cache/redis/index.d.ts.map +1 -1
- package/dist/cache/redis/index.js +4 -0
- package/dist/cache/redis/index.js.map +1 -1
- package/dist/cli/index.d.ts +638 -5645
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +2550 -368
- package/dist/cli/index.js.map +1 -1
- package/dist/command/index.d.ts +203 -45
- package/dist/command/index.d.ts.map +1 -1
- package/dist/command/index.js +2060 -71
- package/dist/command/index.js.map +1 -1
- package/dist/core/index.browser.js +70 -40
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +34 -13
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +90 -40
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js +70 -40
- package/dist/core/index.native.js.map +1 -1
- package/dist/datetime/index.d.ts +15 -0
- package/dist/datetime/index.d.ts.map +1 -1
- package/dist/datetime/index.js +15 -0
- package/dist/datetime/index.js.map +1 -1
- package/dist/email/index.d.ts +323 -20
- package/dist/email/index.d.ts.map +1 -1
- package/dist/email/index.js +1857 -7
- package/dist/email/index.js.map +1 -1
- package/dist/fake/index.d.ts +90 -8
- package/dist/fake/index.d.ts.map +1 -1
- package/dist/fake/index.js +91 -20
- package/dist/fake/index.js.map +1 -1
- package/dist/lock/core/index.d.ts +11 -4
- package/dist/lock/core/index.d.ts.map +1 -1
- package/dist/lock/core/index.js +11 -4
- package/dist/lock/core/index.js.map +1 -1
- package/dist/logger/index.d.ts +17 -66
- package/dist/logger/index.d.ts.map +1 -1
- package/dist/logger/index.js +14 -63
- package/dist/logger/index.js.map +1 -1
- package/dist/mcp/index.d.ts +10 -30
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +12 -35
- package/dist/mcp/index.js.map +1 -1
- package/dist/orm/index.browser.js +3 -3
- package/dist/orm/index.browser.js.map +1 -1
- package/dist/orm/index.bun.js +39 -20
- package/dist/orm/index.bun.js.map +1 -1
- package/dist/orm/index.d.ts +517 -540
- package/dist/orm/index.d.ts.map +1 -1
- package/dist/orm/index.js +58 -71
- package/dist/orm/index.js.map +1 -1
- package/dist/queue/core/index.d.ts +18 -10
- package/dist/queue/core/index.d.ts.map +1 -1
- package/dist/queue/core/index.js +14 -6
- package/dist/queue/core/index.js.map +1 -1
- package/dist/react/auth/index.browser.js +108 -0
- package/dist/react/auth/index.browser.js.map +1 -0
- package/dist/react/auth/index.d.ts +100 -0
- package/dist/react/auth/index.d.ts.map +1 -0
- package/dist/react/auth/index.js +145 -0
- package/dist/react/auth/index.js.map +1 -0
- package/dist/react/core/index.d.ts +469 -0
- package/dist/react/core/index.d.ts.map +1 -0
- package/dist/react/core/index.js +464 -0
- package/dist/react/core/index.js.map +1 -0
- package/dist/react/form/index.d.ts +232 -0
- package/dist/react/form/index.d.ts.map +1 -0
- package/dist/react/form/index.js +432 -0
- package/dist/react/form/index.js.map +1 -0
- package/dist/react/head/index.browser.js +423 -0
- package/dist/react/head/index.browser.js.map +1 -0
- package/dist/react/head/index.d.ts +288 -0
- package/dist/react/head/index.d.ts.map +1 -0
- package/dist/react/head/index.js +465 -0
- package/dist/react/head/index.js.map +1 -0
- package/dist/react/i18n/index.d.ts +175 -0
- package/dist/react/i18n/index.d.ts.map +1 -0
- package/dist/react/i18n/index.js +224 -0
- package/dist/react/i18n/index.js.map +1 -0
- package/dist/react/router/index.browser.js +1974 -0
- package/dist/react/router/index.browser.js.map +1 -0
- package/dist/react/router/index.d.ts +1956 -0
- package/dist/react/router/index.d.ts.map +1 -0
- package/dist/react/router/index.js +4722 -0
- package/dist/react/router/index.js.map +1 -0
- package/dist/react/websocket/index.d.ts +117 -0
- package/dist/react/websocket/index.d.ts.map +1 -0
- package/dist/react/websocket/index.js +107 -0
- package/dist/react/websocket/index.js.map +1 -0
- package/dist/redis/index.bun.js +4 -0
- package/dist/redis/index.bun.js.map +1 -1
- package/dist/redis/index.d.ts +41 -44
- package/dist/redis/index.d.ts.map +1 -1
- package/dist/redis/index.js +16 -25
- package/dist/redis/index.js.map +1 -1
- package/dist/retry/index.d.ts +11 -2
- package/dist/retry/index.d.ts.map +1 -1
- package/dist/retry/index.js +11 -2
- package/dist/retry/index.js.map +1 -1
- package/dist/scheduler/index.d.ts +11 -2
- package/dist/scheduler/index.d.ts.map +1 -1
- package/dist/scheduler/index.js +11 -2
- package/dist/scheduler/index.js.map +1 -1
- package/dist/security/index.d.ts +140 -49
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +164 -32
- package/dist/security/index.js.map +1 -1
- package/dist/server/auth/index.d.ts +12 -7
- package/dist/server/auth/index.d.ts.map +1 -1
- package/dist/server/auth/index.js +12 -7
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/cache/index.d.ts +7 -22
- package/dist/server/cache/index.d.ts.map +1 -1
- package/dist/server/cache/index.js +7 -22
- package/dist/server/cache/index.js.map +1 -1
- package/dist/server/compress/index.d.ts +10 -2
- package/dist/server/compress/index.d.ts.map +1 -1
- package/dist/server/compress/index.js +10 -2
- package/dist/server/compress/index.js.map +1 -1
- package/dist/server/cookies/index.d.ts +40 -16
- package/dist/server/cookies/index.d.ts.map +1 -1
- package/dist/server/cookies/index.js +7 -5
- package/dist/server/cookies/index.js.map +1 -1
- package/dist/server/core/index.d.ts +124 -23
- package/dist/server/core/index.d.ts.map +1 -1
- package/dist/server/core/index.js +231 -14
- package/dist/server/core/index.js.map +1 -1
- package/dist/server/cors/index.d.ts +13 -23
- package/dist/server/cors/index.d.ts.map +1 -1
- package/dist/server/cors/index.js +7 -21
- package/dist/server/cors/index.js.map +1 -1
- package/dist/server/health/index.d.ts +8 -2
- package/dist/server/health/index.d.ts.map +1 -1
- package/dist/server/health/index.js +8 -2
- package/dist/server/health/index.js.map +1 -1
- package/dist/server/helmet/index.d.ts +11 -3
- package/dist/server/helmet/index.d.ts.map +1 -1
- package/dist/server/helmet/index.js +11 -3
- package/dist/server/helmet/index.js.map +1 -1
- package/dist/server/links/index.d.ts +11 -6
- package/dist/server/links/index.d.ts.map +1 -1
- package/dist/server/links/index.js +11 -6
- package/dist/server/links/index.js.map +1 -1
- package/dist/server/metrics/index.d.ts +10 -3
- package/dist/server/metrics/index.d.ts.map +1 -1
- package/dist/server/metrics/index.js +10 -3
- package/dist/server/metrics/index.js.map +1 -1
- package/dist/server/multipart/index.d.ts +9 -3
- package/dist/server/multipart/index.d.ts.map +1 -1
- package/dist/server/multipart/index.js +9 -3
- package/dist/server/multipart/index.js.map +1 -1
- package/dist/server/proxy/index.d.ts +8 -2
- package/dist/server/proxy/index.d.ts.map +1 -1
- package/dist/server/proxy/index.js +8 -2
- package/dist/server/proxy/index.js.map +1 -1
- package/dist/server/rate-limit/index.d.ts +30 -35
- package/dist/server/rate-limit/index.d.ts.map +1 -1
- package/dist/server/rate-limit/index.js +18 -55
- package/dist/server/rate-limit/index.js.map +1 -1
- package/dist/server/static/index.d.ts +137 -4
- package/dist/server/static/index.d.ts.map +1 -1
- package/dist/server/static/index.js +1853 -5
- package/dist/server/static/index.js.map +1 -1
- package/dist/server/swagger/index.d.ts +309 -6
- package/dist/server/swagger/index.d.ts.map +1 -1
- package/dist/server/swagger/index.js +1854 -6
- package/dist/server/swagger/index.js.map +1 -1
- package/dist/sms/index.d.ts +309 -7
- package/dist/sms/index.d.ts.map +1 -1
- package/dist/sms/index.js +1856 -7
- package/dist/sms/index.js.map +1 -1
- package/dist/system/index.browser.js +1218 -0
- package/dist/system/index.browser.js.map +1 -0
- package/dist/{file → system}/index.d.ts +343 -16
- package/dist/system/index.d.ts.map +1 -0
- package/dist/{file → system}/index.js +419 -22
- package/dist/system/index.js.map +1 -0
- package/dist/thread/index.d.ts +11 -2
- package/dist/thread/index.d.ts.map +1 -1
- package/dist/thread/index.js +11 -2
- package/dist/thread/index.js.map +1 -1
- package/dist/topic/core/index.d.ts +12 -5
- package/dist/topic/core/index.d.ts.map +1 -1
- package/dist/topic/core/index.js +12 -5
- package/dist/topic/core/index.js.map +1 -1
- package/dist/vite/index.d.ts +5 -6272
- package/dist/vite/index.d.ts.map +1 -1
- package/dist/vite/index.js +23 -10
- package/dist/vite/index.js.map +1 -1
- package/dist/websocket/index.d.ts +12 -8
- package/dist/websocket/index.d.ts.map +1 -1
- package/dist/websocket/index.js +12 -8
- package/dist/websocket/index.js.map +1 -1
- package/package.json +82 -11
- package/src/api/audits/index.ts +10 -33
- package/src/api/files/__tests__/$bucket.spec.ts +1 -1
- package/src/api/files/controllers/AdminFileStatsController.spec.ts +1 -1
- package/src/api/files/controllers/FileController.spec.ts +1 -1
- package/src/api/files/index.ts +10 -3
- package/src/api/files/jobs/FileJobs.spec.ts +1 -1
- package/src/api/files/services/FileService.spec.ts +1 -1
- package/src/api/jobs/index.ts +10 -3
- package/src/api/keys/controllers/AdminApiKeyController.ts +75 -0
- package/src/api/keys/controllers/ApiKeyController.ts +103 -0
- package/src/api/keys/entities/apiKeyEntity.ts +41 -0
- package/src/api/keys/index.ts +49 -0
- package/src/api/keys/schemas/adminApiKeyQuerySchema.ts +7 -0
- package/src/api/keys/schemas/adminApiKeyResourceSchema.ts +17 -0
- package/src/api/keys/schemas/createApiKeyBodySchema.ts +7 -0
- package/src/api/keys/schemas/createApiKeyResponseSchema.ts +11 -0
- package/src/api/keys/schemas/listApiKeyResponseSchema.ts +15 -0
- package/src/api/keys/schemas/revokeApiKeyParamsSchema.ts +5 -0
- package/src/api/keys/schemas/revokeApiKeyResponseSchema.ts +5 -0
- package/src/api/keys/services/ApiKeyService.spec.ts +553 -0
- package/src/api/keys/services/ApiKeyService.ts +306 -0
- package/src/api/logs/TODO.md +55 -0
- package/src/api/notifications/index.ts +10 -4
- package/src/api/parameters/index.ts +9 -30
- package/src/api/parameters/primitives/$config.ts +12 -4
- package/src/api/parameters/services/ConfigStore.ts +9 -3
- package/src/api/users/__tests__/ApiKeys-integration.spec.ts +1035 -0
- package/src/api/users/__tests__/ApiKeys.spec.ts +401 -0
- package/src/api/users/index.ts +14 -3
- package/src/api/users/primitives/$realm.ts +33 -5
- package/src/api/users/providers/RealmProvider.ts +1 -12
- package/src/api/users/services/SessionService.ts +1 -1
- package/src/api/verifications/controllers/VerificationController.ts +2 -0
- package/src/api/verifications/index.ts +10 -4
- package/src/batch/index.ts +9 -36
- package/src/batch/primitives/$batch.ts +0 -8
- package/src/batch/providers/BatchProvider.ts +29 -2
- package/src/bucket/__tests__/shared.ts +1 -1
- package/src/bucket/index.ts +13 -6
- package/src/bucket/primitives/$bucket.ts +1 -1
- package/src/bucket/providers/LocalFileStorageProvider.ts +1 -1
- package/src/bucket/providers/MemoryFileStorageProvider.ts +1 -1
- package/src/cache/core/__tests__/shared.ts +30 -0
- package/src/cache/core/index.ts +11 -6
- package/src/cache/core/primitives/$cache.spec.ts +5 -0
- package/src/cache/core/providers/CacheProvider.ts +17 -0
- package/src/cache/core/providers/MemoryCacheProvider.ts +300 -1
- package/src/cache/redis/__tests__/cache-redis.spec.ts +5 -0
- package/src/cache/redis/providers/RedisCacheProvider.ts +9 -0
- package/src/cli/apps/AlephaCli.ts +1 -14
- package/src/cli/apps/AlephaPackageBuilderCli.ts +10 -1
- package/src/cli/atoms/buildOptions.ts +99 -9
- package/src/cli/commands/build.ts +150 -37
- package/src/cli/commands/db.ts +22 -18
- package/src/cli/commands/deploy.ts +1 -1
- package/src/cli/commands/dev.ts +1 -20
- package/src/cli/commands/gen/env.ts +5 -2
- package/src/cli/commands/gen/openapi.ts +5 -2
- package/src/cli/commands/init.spec.ts +588 -0
- package/src/cli/commands/init.ts +115 -58
- package/src/cli/commands/lint.ts +7 -1
- package/src/cli/commands/typecheck.ts +11 -0
- package/src/cli/providers/AppEntryProvider.ts +1 -1
- package/src/cli/providers/ViteBuildProvider.ts +8 -50
- package/src/cli/providers/ViteDevServerProvider.ts +35 -16
- package/src/cli/services/AlephaCliUtils.ts +52 -121
- package/src/cli/services/PackageManagerUtils.ts +129 -11
- package/src/cli/services/ProjectScaffolder.spec.ts +97 -0
- package/src/cli/services/ProjectScaffolder.ts +148 -81
- package/src/cli/services/ViteUtils.ts +82 -0
- package/src/cli/{assets/claudeMd.ts → templates/agentMd.ts} +37 -24
- package/src/cli/templates/apiAppSecurityTs.ts +11 -0
- package/src/cli/templates/apiIndexTs.ts +30 -0
- package/src/cli/templates/gitignore.ts +39 -0
- package/src/cli/{assets → templates}/mainCss.ts +11 -2
- package/src/cli/templates/mainServerTs.ts +33 -0
- package/src/cli/templates/webAppRouterTs.ts +74 -0
- package/src/cli/templates/webHelloComponentTsx.ts +30 -0
- package/src/command/helpers/Runner.spec.ts +139 -0
- package/src/command/helpers/Runner.ts +7 -22
- package/src/command/index.ts +12 -4
- package/src/command/providers/CliProvider.spec.ts +1392 -0
- package/src/command/providers/CliProvider.ts +320 -47
- package/src/core/Alepha.ts +34 -27
- package/src/core/__tests__/Alepha-start.spec.ts +4 -4
- package/src/core/helpers/jsonSchemaToTypeBox.spec.ts +771 -0
- package/src/core/helpers/jsonSchemaToTypeBox.ts +62 -10
- package/src/core/index.shared.ts +1 -0
- package/src/core/index.ts +20 -0
- package/src/core/providers/EventManager.spec.ts +0 -71
- package/src/core/providers/EventManager.ts +3 -15
- package/src/core/providers/Json.ts +2 -14
- package/src/datetime/index.ts +15 -0
- package/src/email/index.ts +10 -5
- package/src/email/providers/LocalEmailProvider.spec.ts +1 -1
- package/src/email/providers/LocalEmailProvider.ts +1 -1
- package/src/fake/__tests__/keyName.example.ts +1 -1
- package/src/fake/__tests__/keyName.spec.ts +5 -5
- package/src/fake/index.ts +9 -6
- package/src/fake/providers/FakeProvider.spec.ts +258 -40
- package/src/fake/providers/FakeProvider.ts +133 -19
- package/src/lock/core/index.ts +11 -4
- package/src/logger/index.ts +17 -66
- package/src/mcp/index.ts +10 -27
- package/src/mcp/transports/SseMcpTransport.ts +0 -11
- package/src/orm/__tests__/PostgresProvider.spec.ts +2 -2
- package/src/orm/index.browser.ts +2 -2
- package/src/orm/index.bun.ts +5 -3
- package/src/orm/index.ts +23 -53
- package/src/orm/providers/drivers/BunSqliteProvider.ts +5 -1
- package/src/orm/providers/drivers/CloudflareD1Provider.ts +57 -30
- package/src/orm/providers/drivers/DatabaseProvider.ts +9 -1
- package/src/orm/providers/drivers/NodeSqliteProvider.ts +4 -1
- package/src/orm/services/Repository.ts +7 -3
- package/src/queue/core/index.ts +14 -6
- package/src/react/auth/__tests__/$auth.spec.ts +202 -0
- package/src/react/auth/hooks/useAuth.ts +32 -0
- package/src/react/auth/index.browser.ts +13 -0
- package/src/react/auth/index.shared.ts +2 -0
- package/src/react/auth/index.ts +48 -0
- package/src/react/auth/providers/ReactAuthProvider.ts +16 -0
- package/src/react/auth/services/ReactAuth.ts +135 -0
- package/src/react/core/__tests__/Router.spec.tsx +169 -0
- package/src/react/core/components/ClientOnly.tsx +49 -0
- package/src/react/core/components/ErrorBoundary.tsx +73 -0
- package/src/react/core/contexts/AlephaContext.ts +7 -0
- package/src/react/core/contexts/AlephaProvider.tsx +42 -0
- package/src/react/core/hooks/useAction.browser.spec.tsx +569 -0
- package/src/react/core/hooks/useAction.ts +480 -0
- package/src/react/core/hooks/useAlepha.ts +26 -0
- package/src/react/core/hooks/useClient.ts +17 -0
- package/src/react/core/hooks/useEvents.ts +51 -0
- package/src/react/core/hooks/useInject.ts +12 -0
- package/src/react/core/hooks/useStore.ts +52 -0
- package/src/react/core/index.ts +90 -0
- package/src/react/form/components/FormState.tsx +17 -0
- package/src/react/form/errors/FormValidationError.ts +18 -0
- package/src/react/form/hooks/useForm.browser.spec.tsx +366 -0
- package/src/react/form/hooks/useForm.ts +47 -0
- package/src/react/form/hooks/useFormState.ts +130 -0
- package/src/react/form/index.ts +44 -0
- package/src/react/form/services/FormModel.ts +614 -0
- package/src/react/head/helpers/SeoExpander.spec.ts +203 -0
- package/src/react/head/helpers/SeoExpander.ts +142 -0
- package/src/react/head/hooks/useHead.spec.tsx +288 -0
- package/src/react/head/hooks/useHead.ts +62 -0
- package/src/react/head/index.browser.ts +26 -0
- package/src/react/head/index.ts +44 -0
- package/src/react/head/interfaces/Head.ts +105 -0
- package/src/react/head/primitives/$head.ts +25 -0
- package/src/react/head/providers/BrowserHeadProvider.browser.spec.ts +196 -0
- package/src/react/head/providers/BrowserHeadProvider.ts +212 -0
- package/src/react/head/providers/HeadProvider.ts +168 -0
- package/src/react/head/providers/ServerHeadProvider.ts +31 -0
- package/src/react/i18n/__tests__/integration.spec.tsx +239 -0
- package/src/react/i18n/components/Localize.spec.tsx +357 -0
- package/src/react/i18n/components/Localize.tsx +35 -0
- package/src/react/i18n/hooks/useI18n.browser.spec.tsx +438 -0
- package/src/react/i18n/hooks/useI18n.ts +18 -0
- package/src/react/i18n/index.ts +41 -0
- package/src/react/i18n/primitives/$dictionary.ts +69 -0
- package/src/react/i18n/providers/I18nProvider.spec.ts +389 -0
- package/src/react/i18n/providers/I18nProvider.ts +278 -0
- package/src/react/router/__tests__/page-head-browser.browser.spec.ts +95 -0
- package/src/react/router/__tests__/page-head.spec.ts +48 -0
- package/src/react/router/__tests__/seo-head.spec.ts +125 -0
- package/src/react/router/atoms/ssrManifestAtom.ts +58 -0
- package/src/react/router/components/ErrorViewer.tsx +872 -0
- package/src/react/router/components/Link.tsx +23 -0
- package/src/react/router/components/NestedView.tsx +223 -0
- package/src/react/router/components/NotFound.tsx +30 -0
- package/src/react/router/constants/PAGE_PRELOAD_KEY.ts +6 -0
- package/src/react/router/contexts/RouterLayerContext.ts +12 -0
- package/src/react/router/errors/Redirection.ts +28 -0
- package/src/react/router/hooks/useActive.ts +52 -0
- package/src/react/router/hooks/useQueryParams.ts +63 -0
- package/src/react/router/hooks/useRouter.ts +20 -0
- package/src/react/router/hooks/useRouterState.ts +11 -0
- package/src/react/router/index.browser.ts +45 -0
- package/src/react/router/index.shared.ts +19 -0
- package/src/react/router/index.ts +146 -0
- package/src/react/router/primitives/$page.browser.spec.tsx +851 -0
- package/src/react/router/primitives/$page.spec.tsx +676 -0
- package/src/react/router/primitives/$page.ts +489 -0
- package/src/react/router/providers/ReactBrowserProvider.ts +312 -0
- package/src/react/router/providers/ReactBrowserRendererProvider.ts +25 -0
- package/src/react/router/providers/ReactBrowserRouterProvider.ts +168 -0
- package/src/react/router/providers/ReactPageProvider.ts +726 -0
- package/src/react/router/providers/ReactPreloadProvider.spec.ts +142 -0
- package/src/react/router/providers/ReactPreloadProvider.ts +85 -0
- package/src/react/router/providers/ReactServerProvider.spec.tsx +316 -0
- package/src/react/router/providers/ReactServerProvider.ts +487 -0
- package/src/react/router/providers/ReactServerTemplateProvider.spec.ts +210 -0
- package/src/react/router/providers/ReactServerTemplateProvider.ts +542 -0
- package/src/react/router/providers/SSRManifestProvider.ts +334 -0
- package/src/react/router/services/ReactPageServerService.ts +48 -0
- package/src/react/router/services/ReactPageService.ts +27 -0
- package/src/react/router/services/ReactRouter.ts +262 -0
- package/src/react/websocket/hooks/useRoom.tsx +242 -0
- package/src/react/websocket/index.ts +7 -0
- package/src/redis/__tests__/redis.spec.ts +13 -0
- package/src/redis/index.ts +9 -25
- package/src/redis/providers/BunRedisProvider.ts +9 -0
- package/src/redis/providers/NodeRedisProvider.ts +8 -0
- package/src/redis/providers/RedisProvider.ts +16 -0
- package/src/retry/index.ts +11 -2
- package/src/router/index.ts +15 -0
- package/src/scheduler/index.ts +11 -2
- package/src/security/__tests__/BasicAuth.spec.ts +2 -0
- package/src/security/__tests__/ServerSecurityProvider.spec.ts +90 -5
- package/src/security/index.ts +15 -10
- package/src/security/interfaces/IssuerResolver.ts +27 -0
- package/src/security/primitives/$issuer.ts +55 -0
- package/src/security/providers/SecurityProvider.ts +179 -0
- package/src/security/providers/ServerBasicAuthProvider.ts +6 -2
- package/src/security/providers/ServerSecurityProvider.ts +63 -41
- package/src/server/auth/index.ts +12 -7
- package/src/server/cache/index.ts +7 -22
- package/src/server/compress/index.ts +10 -2
- package/src/server/cookies/index.ts +7 -5
- package/src/server/cookies/primitives/$cookie.ts +33 -11
- package/src/server/core/index.ts +16 -6
- package/src/server/core/interfaces/ServerRequest.ts +83 -1
- package/src/server/core/primitives/$action.spec.ts +1 -1
- package/src/server/core/primitives/$action.ts +8 -3
- package/src/server/core/providers/NodeHttpServerProvider.spec.ts +9 -3
- package/src/server/core/providers/NodeHttpServerProvider.ts +9 -3
- package/src/server/core/services/ServerRequestParser.spec.ts +520 -0
- package/src/server/core/services/ServerRequestParser.ts +306 -13
- package/src/server/cors/index.ts +7 -21
- package/src/server/cors/primitives/$cors.ts +6 -2
- package/src/server/health/index.ts +8 -2
- package/src/server/helmet/index.ts +11 -3
- package/src/server/links/index.ts +11 -6
- package/src/server/metrics/index.ts +10 -3
- package/src/server/multipart/index.ts +9 -3
- package/src/server/proxy/index.ts +8 -2
- package/src/server/rate-limit/index.ts +21 -25
- package/src/server/rate-limit/primitives/$rateLimit.ts +6 -2
- package/src/server/rate-limit/providers/ServerRateLimitProvider.spec.ts +38 -14
- package/src/server/rate-limit/providers/ServerRateLimitProvider.ts +22 -56
- package/src/server/static/index.ts +8 -2
- package/src/server/static/providers/ServerStaticProvider.ts +1 -1
- package/src/server/swagger/index.ts +9 -4
- package/src/server/swagger/providers/ServerSwaggerProvider.ts +1 -1
- package/src/sms/index.ts +9 -5
- package/src/sms/providers/LocalSmsProvider.spec.ts +1 -1
- package/src/sms/providers/LocalSmsProvider.ts +1 -1
- package/src/system/index.browser.ts +36 -0
- package/src/system/index.ts +62 -0
- package/src/system/index.workerd.ts +1 -0
- package/src/{file → system}/providers/FileSystemProvider.ts +24 -0
- package/src/{file → system}/providers/MemoryFileSystemProvider.ts +116 -3
- package/src/system/providers/MemoryShellProvider.ts +164 -0
- package/src/{file → system}/providers/NodeFileSystemProvider.spec.ts +2 -2
- package/src/{file → system}/providers/NodeFileSystemProvider.ts +47 -2
- package/src/system/providers/NodeShellProvider.ts +184 -0
- package/src/system/providers/ShellProvider.ts +74 -0
- package/src/{file → system}/services/FileDetector.spec.ts +2 -2
- package/src/thread/index.ts +11 -2
- package/src/topic/core/index.ts +12 -5
- package/src/vite/tasks/buildClient.ts +2 -7
- package/src/vite/tasks/buildServer.ts +19 -13
- package/src/vite/tasks/generateCloudflare.ts +10 -7
- package/src/vite/tasks/generateDocker.ts +4 -0
- package/src/websocket/index.ts +12 -8
- package/dist/file/index.d.ts.map +0 -1
- package/dist/file/index.js.map +0 -1
- package/src/cli/assets/apiIndexTs.ts +0 -16
- package/src/cli/assets/mainServerTs.ts +0 -24
- package/src/cli/assets/webAppRouterTs.ts +0 -16
- package/src/cli/assets/webHelloComponentTsx.ts +0 -20
- package/src/cli/providers/ViteTemplateProvider.ts +0 -27
- package/src/file/index.ts +0 -43
- /package/src/cli/{assets → templates}/apiHelloControllerTs.ts +0 -0
- /package/src/cli/{assets → templates}/biomeJson.ts +0 -0
- /package/src/cli/{assets → templates}/dummySpecTs.ts +0 -0
- /package/src/cli/{assets → templates}/editorconfig.ts +0 -0
- /package/src/cli/{assets → templates}/mainBrowserTs.ts +0 -0
- /package/src/cli/{assets → templates}/tsconfigJson.ts +0 -0
- /package/src/cli/{assets → templates}/webIndexTs.ts +0 -0
- /package/src/{file → system}/errors/FileError.ts +0 -0
- /package/src/{file → system}/services/FileDetector.ts +0 -0
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
type Static,
|
|
11
11
|
type TObject,
|
|
12
12
|
type TSchema,
|
|
13
|
+
type TUnion,
|
|
13
14
|
TypeBoxError,
|
|
14
15
|
t,
|
|
15
16
|
} from "alepha";
|
|
@@ -77,7 +78,37 @@ declare module "alepha" {
|
|
|
77
78
|
|
|
78
79
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
79
80
|
|
|
81
|
+
/**
|
|
82
|
+
* CLI provider for parsing and executing commands.
|
|
83
|
+
*
|
|
84
|
+
* Handles:
|
|
85
|
+
* - Command resolution (simple, nested, colon-notation)
|
|
86
|
+
* - Flag and argument parsing
|
|
87
|
+
* - Environment variable validation
|
|
88
|
+
* - Help generation
|
|
89
|
+
* - Pre/post command hooks
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```typescript
|
|
93
|
+
* // Define a command
|
|
94
|
+
* class MyCommands {
|
|
95
|
+
* build = $command({
|
|
96
|
+
* name: "build",
|
|
97
|
+
* description: "Build the project",
|
|
98
|
+
* flags: t.object({ watch: t.optional(t.boolean()) }),
|
|
99
|
+
* handler: async ({ flags }) => { ... }
|
|
100
|
+
* });
|
|
101
|
+
* }
|
|
102
|
+
*
|
|
103
|
+
* // CLI automatically discovers and executes commands
|
|
104
|
+
* const alepha = Alepha.create().with(MyCommands);
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
80
107
|
export class CliProvider {
|
|
108
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
109
|
+
// Dependencies
|
|
110
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
111
|
+
|
|
81
112
|
protected readonly env = $env(envSchema);
|
|
82
113
|
protected readonly alepha = $inject(Alepha);
|
|
83
114
|
protected readonly log = $logger();
|
|
@@ -85,9 +116,12 @@ export class CliProvider {
|
|
|
85
116
|
protected readonly runner = $inject(Runner);
|
|
86
117
|
protected readonly asker = $inject(Asker);
|
|
87
118
|
protected readonly envUtils = $inject(EnvUtils);
|
|
88
|
-
|
|
89
119
|
protected readonly options = $use(cliOptions);
|
|
90
120
|
|
|
121
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
122
|
+
// Configuration
|
|
123
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
124
|
+
|
|
91
125
|
protected get name(): string {
|
|
92
126
|
return this.options.name || this.env.CLI_NAME;
|
|
93
127
|
}
|
|
@@ -103,6 +137,9 @@ export class CliProvider {
|
|
|
103
137
|
);
|
|
104
138
|
}
|
|
105
139
|
|
|
140
|
+
/**
|
|
141
|
+
* Global flags available to all commands.
|
|
142
|
+
*/
|
|
106
143
|
protected readonly globalFlags = {
|
|
107
144
|
help: {
|
|
108
145
|
aliases: ["h", "help"],
|
|
@@ -111,6 +148,14 @@ export class CliProvider {
|
|
|
111
148
|
},
|
|
112
149
|
};
|
|
113
150
|
|
|
151
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
152
|
+
// Lifecycle
|
|
153
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Main entry point - resolves and executes the command from process.argv.
|
|
157
|
+
* This is the production execution path with full lifecycle support.
|
|
158
|
+
*/
|
|
114
159
|
protected readonly onReady = $hook({
|
|
115
160
|
on: "ready",
|
|
116
161
|
handler: async () => {
|
|
@@ -119,7 +164,7 @@ export class CliProvider {
|
|
|
119
164
|
// Extract positional arguments (potential command path)
|
|
120
165
|
const positionalArgs = argv.filter((arg) => !arg.startsWith("-"));
|
|
121
166
|
|
|
122
|
-
// Resolve command using
|
|
167
|
+
// Resolve command using space-separated or colon-notation
|
|
123
168
|
const { command, consumedArgs } = this.resolveCommand(positionalArgs);
|
|
124
169
|
|
|
125
170
|
const globalFlags = this.parseFlags(
|
|
@@ -128,6 +173,7 @@ export class CliProvider {
|
|
|
128
173
|
key,
|
|
129
174
|
...value,
|
|
130
175
|
})),
|
|
176
|
+
{ strict: false }, // Don't throw for command-specific flags
|
|
131
177
|
);
|
|
132
178
|
|
|
133
179
|
if (globalFlags.help) {
|
|
@@ -166,7 +212,15 @@ export class CliProvider {
|
|
|
166
212
|
});
|
|
167
213
|
|
|
168
214
|
/**
|
|
169
|
-
* Execute a command with
|
|
215
|
+
* Execute a command with full lifecycle support.
|
|
216
|
+
*
|
|
217
|
+
* This is the production execution path that includes:
|
|
218
|
+
* - Mode-based .env file loading
|
|
219
|
+
* - Pre/post command hooks
|
|
220
|
+
* - Runner session for pretty CLI output
|
|
221
|
+
* - Alepha context wrapper for proper scoping
|
|
222
|
+
*
|
|
223
|
+
* @see run() for a lightweight test-only alternative
|
|
170
224
|
*/
|
|
171
225
|
protected async executeCommand(
|
|
172
226
|
command: CommandPrimitive<TObject>,
|
|
@@ -186,7 +240,9 @@ export class CliProvider {
|
|
|
186
240
|
await this.loadModeEnv(root, modeValue);
|
|
187
241
|
}
|
|
188
242
|
|
|
189
|
-
const commandFlags = this.parseCommandFlags(argv, command.flags
|
|
243
|
+
const commandFlags = this.parseCommandFlags(argv, command.flags, {
|
|
244
|
+
modeEnabled: !!command.options.mode,
|
|
245
|
+
});
|
|
190
246
|
const commandArgs = this.parseCommandArgs(
|
|
191
247
|
argv,
|
|
192
248
|
command.options.args,
|
|
@@ -244,7 +300,7 @@ export class CliProvider {
|
|
|
244
300
|
}
|
|
245
301
|
|
|
246
302
|
/**
|
|
247
|
-
* Remove consumed command path arguments from argv.
|
|
303
|
+
* Remove consumed command path arguments from argv (keeps flags and remaining args).
|
|
248
304
|
*/
|
|
249
305
|
protected removeConsumedArgs(
|
|
250
306
|
argv: string[],
|
|
@@ -327,33 +383,113 @@ export class CliProvider {
|
|
|
327
383
|
return { command: currentCommand, consumedArgs };
|
|
328
384
|
}
|
|
329
385
|
|
|
386
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
387
|
+
// Public API
|
|
388
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Get all registered commands in the application.
|
|
392
|
+
*/
|
|
330
393
|
public get commands(): CommandPrimitive<any>[] {
|
|
331
394
|
return this.alepha.primitives($command);
|
|
332
395
|
}
|
|
333
396
|
|
|
397
|
+
/**
|
|
398
|
+
* Execute a command handler with given arguments.
|
|
399
|
+
*
|
|
400
|
+
* This is a **lightweight test helper** that directly invokes the command handler
|
|
401
|
+
* without the full production lifecycle. It intentionally skips:
|
|
402
|
+
* - Pre/post command hooks
|
|
403
|
+
* - Runner session (pretty CLI output)
|
|
404
|
+
* - Alepha context wrapper
|
|
405
|
+
* - .env.{mode} file loading
|
|
406
|
+
*
|
|
407
|
+
* For production execution, the `onReady` hook uses `executeCommand()` which
|
|
408
|
+
* provides the full lifecycle. Merging them would either make this method too
|
|
409
|
+
* heavy for simple testing or require many optional parameters to toggle behaviors.
|
|
410
|
+
*
|
|
411
|
+
* @example
|
|
412
|
+
* ```typescript
|
|
413
|
+
* // In tests
|
|
414
|
+
* const cli = alepha.inject(CliProvider);
|
|
415
|
+
* const cmd = alepha.inject(InitCommand);
|
|
416
|
+
*
|
|
417
|
+
* await cli.run(cmd.init, "--agent --pm=yarn");
|
|
418
|
+
* await cli.run(cmd.init, { argv: "--agent", root: "/project" });
|
|
419
|
+
* ```
|
|
420
|
+
*/
|
|
421
|
+
public async run<T extends TObject, A extends TSchema>(
|
|
422
|
+
command: CommandPrimitive<T, A>,
|
|
423
|
+
options:
|
|
424
|
+
| string
|
|
425
|
+
| string[]
|
|
426
|
+
| { argv?: string | string[]; root?: string } = {},
|
|
427
|
+
): Promise<void> {
|
|
428
|
+
const opts =
|
|
429
|
+
typeof options === "string" || Array.isArray(options)
|
|
430
|
+
? { argv: options }
|
|
431
|
+
: options;
|
|
432
|
+
const args =
|
|
433
|
+
typeof opts.argv === "string"
|
|
434
|
+
? opts.argv.split(" ").filter(Boolean)
|
|
435
|
+
: (opts.argv ?? []);
|
|
436
|
+
const root = opts.root ?? process.cwd();
|
|
437
|
+
|
|
438
|
+
const commandFlags = this.parseCommandFlags(args, command.flags, {
|
|
439
|
+
modeEnabled: !!command.options.mode,
|
|
440
|
+
});
|
|
441
|
+
const commandArgs = this.parseCommandArgs(
|
|
442
|
+
args,
|
|
443
|
+
command.options.args,
|
|
444
|
+
true,
|
|
445
|
+
command.flags,
|
|
446
|
+
);
|
|
447
|
+
const commandEnv = this.parseCommandEnv(command.env, command.name);
|
|
448
|
+
|
|
449
|
+
let modeValue: string | undefined;
|
|
450
|
+
if (command.options.mode) {
|
|
451
|
+
modeValue = this.parseModeFlag(args);
|
|
452
|
+
if (modeValue === undefined && typeof command.options.mode === "string") {
|
|
453
|
+
modeValue = command.options.mode;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
await command.options.handler({
|
|
458
|
+
flags: commandFlags,
|
|
459
|
+
args: commandArgs,
|
|
460
|
+
env: commandEnv,
|
|
461
|
+
run: this.runner.run,
|
|
462
|
+
ask: this.asker.ask,
|
|
463
|
+
fs,
|
|
464
|
+
glob,
|
|
465
|
+
root,
|
|
466
|
+
help: () => this.printHelp(command),
|
|
467
|
+
mode: modeValue,
|
|
468
|
+
} as CommandHandlerArgs<T, A>);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
472
|
+
// Command Resolution
|
|
473
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
474
|
+
|
|
475
|
+
/** Find a command by name or alias */
|
|
334
476
|
protected findCommand(name: string): CommandPrimitive<TObject> | undefined {
|
|
335
477
|
return this.commands.findLast(
|
|
336
478
|
(command) => command.name === name || command.aliases.includes(name),
|
|
337
479
|
);
|
|
338
480
|
}
|
|
339
481
|
|
|
340
|
-
/**
|
|
341
|
-
* Find all pre-hooks for a command.
|
|
342
|
-
*/
|
|
482
|
+
/** Find all pre-hooks for a command (commands named `pre{commandName}`) */
|
|
343
483
|
protected findPreHooks(commandName: string): CommandPrimitive<TObject>[] {
|
|
344
484
|
return this.commands.filter((cmd) => cmd.name === `pre${commandName}`);
|
|
345
485
|
}
|
|
346
486
|
|
|
347
|
-
/**
|
|
348
|
-
* Find all post-hooks for a command.
|
|
349
|
-
*/
|
|
487
|
+
/** Find all post-hooks for a command (commands named `post{commandName}`) */
|
|
350
488
|
protected findPostHooks(commandName: string): CommandPrimitive<TObject>[] {
|
|
351
489
|
return this.commands.filter((cmd) => cmd.name === `post${commandName}`);
|
|
352
490
|
}
|
|
353
491
|
|
|
354
|
-
/**
|
|
355
|
-
* Get global flags (help only, root command flags are NOT global).
|
|
356
|
-
*/
|
|
492
|
+
/** Get global flags (help only, root command flags are NOT global) */
|
|
357
493
|
protected getAllGlobalFlags(): Record<
|
|
358
494
|
string,
|
|
359
495
|
{ aliases: string[]; description?: string; schema: TSchema }
|
|
@@ -361,10 +497,17 @@ export class CliProvider {
|
|
|
361
497
|
return { ...this.globalFlags };
|
|
362
498
|
}
|
|
363
499
|
|
|
500
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
501
|
+
// Parsing (Flags, Args, Env)
|
|
502
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
503
|
+
|
|
504
|
+
/** Parse command flags from argv using the command's flag schema */
|
|
364
505
|
protected parseCommandFlags(
|
|
365
506
|
argv: string[],
|
|
366
507
|
schema: TObject,
|
|
508
|
+
options: { modeEnabled?: boolean } = {},
|
|
367
509
|
): Record<string, any> {
|
|
510
|
+
const { modeEnabled = false } = options;
|
|
368
511
|
const flagDefs = Object.entries(schema.properties).map(([key, value]) => ({
|
|
369
512
|
key,
|
|
370
513
|
aliases: [
|
|
@@ -377,8 +520,21 @@ export class CliProvider {
|
|
|
377
520
|
schema: value,
|
|
378
521
|
}));
|
|
379
522
|
|
|
523
|
+
// Add mode flags if mode is enabled (they're parsed elsewhere by parseModeFlag)
|
|
524
|
+
if (modeEnabled) {
|
|
525
|
+
flagDefs.push({
|
|
526
|
+
key: "__mode__",
|
|
527
|
+
aliases: ["mode", "m"],
|
|
528
|
+
description: undefined,
|
|
529
|
+
schema: t.string(),
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
|
|
380
533
|
const parsed = this.parseFlags(argv, flagDefs);
|
|
381
534
|
|
|
535
|
+
// Remove the mode flag from parsed result (it's handled separately)
|
|
536
|
+
delete parsed.__mode__;
|
|
537
|
+
|
|
382
538
|
// apply manually defaults for optional properties that have defaults
|
|
383
539
|
for (const [key, value] of Object.entries(schema.properties)) {
|
|
384
540
|
if (!(key in parsed) && t.schema.isOptional(value)) {
|
|
@@ -401,6 +557,7 @@ export class CliProvider {
|
|
|
401
557
|
}
|
|
402
558
|
}
|
|
403
559
|
|
|
560
|
+
/** Parse and validate environment variables using the command's env schema */
|
|
404
561
|
protected parseCommandEnv(
|
|
405
562
|
schema: TObject,
|
|
406
563
|
commandName: string,
|
|
@@ -442,9 +599,7 @@ export class CliProvider {
|
|
|
442
599
|
}
|
|
443
600
|
}
|
|
444
601
|
|
|
445
|
-
/**
|
|
446
|
-
* Parse --mode or -m flag from argv.
|
|
447
|
-
*/
|
|
602
|
+
/** Parse --mode or -m flag from argv for environment file loading */
|
|
448
603
|
protected parseModeFlag(argv: string[]): string | undefined {
|
|
449
604
|
for (let i = 0; i < argv.length; i++) {
|
|
450
605
|
const arg = argv[i];
|
|
@@ -467,9 +622,7 @@ export class CliProvider {
|
|
|
467
622
|
return undefined;
|
|
468
623
|
}
|
|
469
624
|
|
|
470
|
-
/**
|
|
471
|
-
* Load environment files based on mode.
|
|
472
|
-
*/
|
|
625
|
+
/** Load .env and .env.{mode} files into process.env */
|
|
473
626
|
protected async loadModeEnv(
|
|
474
627
|
root: string,
|
|
475
628
|
mode: string | undefined,
|
|
@@ -482,10 +635,13 @@ export class CliProvider {
|
|
|
482
635
|
await this.envUtils.loadEnv(root, envFiles);
|
|
483
636
|
}
|
|
484
637
|
|
|
638
|
+
/** Low-level flag parser - extracts flag values from argv based on definitions */
|
|
485
639
|
protected parseFlags(
|
|
486
640
|
argv: string[],
|
|
487
641
|
flagDefs: { key: string; aliases: string[]; schema: TSchema }[],
|
|
642
|
+
options: { strict?: boolean } = {},
|
|
488
643
|
): Record<string, any> {
|
|
644
|
+
const { strict = true } = options;
|
|
489
645
|
const result: Record<string, any> = {};
|
|
490
646
|
|
|
491
647
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -496,10 +652,31 @@ export class CliProvider {
|
|
|
496
652
|
let value = valueParts.join("=");
|
|
497
653
|
|
|
498
654
|
const def = flagDefs.find((d) => d.aliases.includes(rawKey));
|
|
499
|
-
if (!def)
|
|
655
|
+
if (!def) {
|
|
656
|
+
if (strict) {
|
|
657
|
+
throw new CommandError(`Unknown flag: --${rawKey}`);
|
|
658
|
+
}
|
|
659
|
+
continue;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
// Check if schema is a union containing boolean (allows flag without value)
|
|
663
|
+
const isUnionWithBoolean =
|
|
664
|
+
t.schema.isUnion(def.schema) &&
|
|
665
|
+
(def.schema as TUnion).anyOf.some((s) => t.schema.isBoolean(s));
|
|
500
666
|
|
|
501
667
|
if (t.schema.isBoolean(def.schema)) {
|
|
502
668
|
result[def.key] = true;
|
|
669
|
+
} else if (isUnionWithBoolean && !value) {
|
|
670
|
+
// Union with boolean: --flag without value → true
|
|
671
|
+
const nextArg = argv[i + 1];
|
|
672
|
+
if (nextArg && !nextArg.startsWith("-")) {
|
|
673
|
+
// Has a value after space: --flag value
|
|
674
|
+
result[def.key] = nextArg;
|
|
675
|
+
i++; // consume next arg
|
|
676
|
+
} else {
|
|
677
|
+
// No value: --flag → true
|
|
678
|
+
result[def.key] = true;
|
|
679
|
+
}
|
|
503
680
|
} else if (value) {
|
|
504
681
|
// Value provided via --flag=value syntax
|
|
505
682
|
try {
|
|
@@ -534,9 +711,7 @@ export class CliProvider {
|
|
|
534
711
|
return result;
|
|
535
712
|
}
|
|
536
713
|
|
|
537
|
-
/**
|
|
538
|
-
* Get indices of argv elements that are consumed by flags (including space-separated values).
|
|
539
|
-
*/
|
|
714
|
+
/** Get indices of argv elements consumed by flags (for separating args from flags) */
|
|
540
715
|
protected getFlagConsumedIndices(
|
|
541
716
|
argv: string[],
|
|
542
717
|
flagDefs: { key: string; aliases: string[]; schema: TSchema }[],
|
|
@@ -555,8 +730,24 @@ export class CliProvider {
|
|
|
555
730
|
const def = flagDefs.find((d) => d.aliases.includes(rawKey));
|
|
556
731
|
if (!def) continue;
|
|
557
732
|
|
|
733
|
+
// Check if schema is a union containing boolean
|
|
734
|
+
const isUnionWithBoolean =
|
|
735
|
+
t.schema.isUnion(def.schema) &&
|
|
736
|
+
(def.schema as TUnion).anyOf.some((s) => t.schema.isBoolean(s));
|
|
737
|
+
|
|
558
738
|
// If not a boolean flag and no = value, the next arg is consumed as the value
|
|
559
|
-
|
|
739
|
+
// Exception: union with boolean can work without a value
|
|
740
|
+
if (
|
|
741
|
+
!t.schema.isBoolean(def.schema) &&
|
|
742
|
+
!isUnionWithBoolean &&
|
|
743
|
+
!hasEqualValue
|
|
744
|
+
) {
|
|
745
|
+
const nextArg = argv[i + 1];
|
|
746
|
+
if (nextArg && !nextArg.startsWith("-")) {
|
|
747
|
+
consumed.add(i + 1);
|
|
748
|
+
}
|
|
749
|
+
} else if (isUnionWithBoolean && !hasEqualValue) {
|
|
750
|
+
// Union with boolean: check if next arg looks like a value (not a flag)
|
|
560
751
|
const nextArg = argv[i + 1];
|
|
561
752
|
if (nextArg && !nextArg.startsWith("-")) {
|
|
562
753
|
consumed.add(i + 1);
|
|
@@ -638,6 +829,7 @@ export class CliProvider {
|
|
|
638
829
|
}
|
|
639
830
|
}
|
|
640
831
|
|
|
832
|
+
/** Convert a string argument value to the appropriate type based on schema */
|
|
641
833
|
protected parseArgumentValue(value: string, schema: TSchema): any {
|
|
642
834
|
if (t.schema.isString(schema)) {
|
|
643
835
|
return value;
|
|
@@ -665,6 +857,11 @@ export class CliProvider {
|
|
|
665
857
|
return value;
|
|
666
858
|
}
|
|
667
859
|
|
|
860
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
861
|
+
// Help Generation
|
|
862
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
863
|
+
|
|
864
|
+
/** Generate usage string for command arguments (e.g., "<path>" or "[path]") */
|
|
668
865
|
protected generateArgsUsage(schema?: TSchema): string {
|
|
669
866
|
if (!schema) {
|
|
670
867
|
return "";
|
|
@@ -694,6 +891,7 @@ export class CliProvider {
|
|
|
694
891
|
return ` <${key}${typeName}>`;
|
|
695
892
|
}
|
|
696
893
|
|
|
894
|
+
/** Get display type name for a schema (e.g., ": number", ": boolean") */
|
|
697
895
|
protected getTypeName(schema: TSchema): string {
|
|
698
896
|
if (!schema) return "";
|
|
699
897
|
|
|
@@ -706,6 +904,12 @@ export class CliProvider {
|
|
|
706
904
|
return "";
|
|
707
905
|
}
|
|
708
906
|
|
|
907
|
+
/**
|
|
908
|
+
* Print help for a specific command or general CLI help.
|
|
909
|
+
*
|
|
910
|
+
* @param command - If provided, shows help for this specific command.
|
|
911
|
+
* If omitted, shows general CLI help with all commands.
|
|
912
|
+
*/
|
|
709
913
|
public printHelp(command?: CommandPrimitive<any>): void {
|
|
710
914
|
const cliName = this.name || "cli";
|
|
711
915
|
const c = this.color;
|
|
@@ -757,7 +961,11 @@ export class CliProvider {
|
|
|
757
961
|
...Object.entries(command.flags.properties).map(([key, value]) => ({
|
|
758
962
|
key,
|
|
759
963
|
schema: value,
|
|
760
|
-
aliases:
|
|
964
|
+
aliases: [
|
|
965
|
+
key,
|
|
966
|
+
...((value as any).aliases ??
|
|
967
|
+
((value as any).alias ? [(value as any).alias] : [])),
|
|
968
|
+
],
|
|
761
969
|
description: (value as any).description,
|
|
762
970
|
})),
|
|
763
971
|
// Add --mode flag if command has mode option enabled
|
|
@@ -770,6 +978,7 @@ export class CliProvider {
|
|
|
770
978
|
typeof command.options.mode === "string"
|
|
771
979
|
? `Environment mode - loads .env.{mode} (default: ${command.options.mode})`
|
|
772
980
|
: "Environment mode (e.g., production, staging) - loads .env.{mode}",
|
|
981
|
+
schema: t.string() as TSchema,
|
|
773
982
|
},
|
|
774
983
|
]
|
|
775
984
|
: []),
|
|
@@ -780,13 +989,20 @@ export class CliProvider {
|
|
|
780
989
|
];
|
|
781
990
|
|
|
782
991
|
const maxFlagLength = this.getMaxFlagLength(flags);
|
|
783
|
-
for (const
|
|
784
|
-
const
|
|
992
|
+
for (const flag of flags) {
|
|
993
|
+
const { aliases, description } = flag;
|
|
994
|
+
const schema = "schema" in flag ? (flag.schema as TSchema) : undefined;
|
|
995
|
+
// Sort aliases by length (shorter first: -t before --target)
|
|
996
|
+
const sortedAliases = (Array.isArray(aliases) ? aliases : [aliases])
|
|
997
|
+
.slice()
|
|
998
|
+
.sort((a, b) => a.length - b.length);
|
|
999
|
+
const flagStr = sortedAliases
|
|
785
1000
|
.map((a: string) => (a.length === 1 ? `-${a}` : `--${a}`))
|
|
786
1001
|
.join(", ");
|
|
787
1002
|
const coloredFlag = c.set("GREY_LIGHT", flagStr);
|
|
788
1003
|
const padding = " ".repeat(Math.max(0, maxFlagLength - flagStr.length));
|
|
789
|
-
this.
|
|
1004
|
+
const formattedDesc = this.formatFlagDescription(description, schema);
|
|
1005
|
+
this.log.info(` ${coloredFlag}${padding} ${formattedDesc}`);
|
|
790
1006
|
}
|
|
791
1007
|
|
|
792
1008
|
// Show environment variables if defined
|
|
@@ -853,6 +1069,7 @@ export class CliProvider {
|
|
|
853
1069
|
[]),
|
|
854
1070
|
],
|
|
855
1071
|
description: (value as any).description,
|
|
1072
|
+
schema: value as TSchema,
|
|
856
1073
|
}))
|
|
857
1074
|
: [];
|
|
858
1075
|
|
|
@@ -861,21 +1078,20 @@ export class CliProvider {
|
|
|
861
1078
|
...Object.values(this.getAllGlobalFlags()),
|
|
862
1079
|
];
|
|
863
1080
|
const maxFlagLength = this.getMaxFlagLength(globalFlags);
|
|
864
|
-
for (const { aliases, description } of globalFlags) {
|
|
1081
|
+
for (const { aliases, description, schema } of globalFlags) {
|
|
865
1082
|
const flagStr = aliases
|
|
866
1083
|
.map((a) => (a.length === 1 ? `-${a}` : `--${a}`))
|
|
867
1084
|
.join(", ");
|
|
868
1085
|
const coloredFlag = c.set("GREY_LIGHT", flagStr);
|
|
869
1086
|
const padding = " ".repeat(Math.max(0, maxFlagLength - flagStr.length));
|
|
870
|
-
this.
|
|
1087
|
+
const formattedDesc = this.formatFlagDescription(description, schema);
|
|
1088
|
+
this.log.info(` ${coloredFlag}${padding} ${formattedDesc}`);
|
|
871
1089
|
}
|
|
872
1090
|
}
|
|
873
1091
|
this.log.info(""); // Newline
|
|
874
1092
|
}
|
|
875
1093
|
|
|
876
|
-
/**
|
|
877
|
-
* Generate colored args usage string for help display.
|
|
878
|
-
*/
|
|
1094
|
+
/** Generate colored usage string for command arguments (for help display) */
|
|
879
1095
|
protected generateColoredArgsUsage(schema?: TSchema): string {
|
|
880
1096
|
if (!schema) {
|
|
881
1097
|
return "";
|
|
@@ -907,9 +1123,7 @@ export class CliProvider {
|
|
|
907
1123
|
return ` ${c.set("CYAN", `<${key}${typeName}>`)}`;
|
|
908
1124
|
}
|
|
909
1125
|
|
|
910
|
-
/**
|
|
911
|
-
* Get the full command path (e.g., "deploy vercel" for a child command).
|
|
912
|
-
*/
|
|
1126
|
+
/** Get the full command path (e.g., "deploy vercel" for a nested command) */
|
|
913
1127
|
protected getCommandPath(command: CommandPrimitive<any>): string {
|
|
914
1128
|
const path: string[] = [command.name];
|
|
915
1129
|
let current = command;
|
|
@@ -925,9 +1139,7 @@ export class CliProvider {
|
|
|
925
1139
|
return path.join(" ");
|
|
926
1140
|
}
|
|
927
1141
|
|
|
928
|
-
/**
|
|
929
|
-
* Find the parent command of a given command.
|
|
930
|
-
*/
|
|
1142
|
+
/** Find the parent command of a nested command */
|
|
931
1143
|
protected findParentCommand(
|
|
932
1144
|
command: CommandPrimitive<any>,
|
|
933
1145
|
): CommandPrimitive<any> | undefined {
|
|
@@ -939,9 +1151,7 @@ export class CliProvider {
|
|
|
939
1151
|
return undefined;
|
|
940
1152
|
}
|
|
941
1153
|
|
|
942
|
-
/**
|
|
943
|
-
* Get top-level commands (commands that are not children of other commands).
|
|
944
|
-
*/
|
|
1154
|
+
/** Get top-level commands (commands that are not children of other commands) */
|
|
945
1155
|
protected getTopLevelCommands(): CommandPrimitive<any>[] {
|
|
946
1156
|
const allChildren = new Set<CommandPrimitive<any>>();
|
|
947
1157
|
|
|
@@ -956,9 +1166,7 @@ export class CliProvider {
|
|
|
956
1166
|
return this.commands.filter((cmd) => !allChildren.has(cmd));
|
|
957
1167
|
}
|
|
958
1168
|
|
|
959
|
-
/**
|
|
960
|
-
* Get max length for child command display.
|
|
961
|
-
*/
|
|
1169
|
+
/** Calculate max display length for child commands (for help alignment) */
|
|
962
1170
|
protected getMaxChildCmdLength(children: CommandPrimitive<any>[]): number {
|
|
963
1171
|
return Math.max(
|
|
964
1172
|
...children
|
|
@@ -972,6 +1180,7 @@ export class CliProvider {
|
|
|
972
1180
|
);
|
|
973
1181
|
}
|
|
974
1182
|
|
|
1183
|
+
/** Calculate max display length for commands (for help alignment) */
|
|
975
1184
|
protected getMaxCmdLength(commands: CommandPrimitive[]): number {
|
|
976
1185
|
return Math.max(
|
|
977
1186
|
...commands
|
|
@@ -986,7 +1195,8 @@ export class CliProvider {
|
|
|
986
1195
|
);
|
|
987
1196
|
}
|
|
988
1197
|
|
|
989
|
-
|
|
1198
|
+
/** Calculate max display length for flags (for help alignment) */
|
|
1199
|
+
protected getMaxFlagLength(flags: { aliases: string[] }[]): number {
|
|
990
1200
|
return Math.max(
|
|
991
1201
|
...flags.map((f) => {
|
|
992
1202
|
const aliases = Array.isArray(f.aliases) ? f.aliases : [f.aliases];
|
|
@@ -996,4 +1206,67 @@ export class CliProvider {
|
|
|
996
1206
|
}),
|
|
997
1207
|
);
|
|
998
1208
|
}
|
|
1209
|
+
|
|
1210
|
+
/**
|
|
1211
|
+
* Extract enum values from a schema if it represents an enum.
|
|
1212
|
+
* Returns undefined if the schema is not an enum.
|
|
1213
|
+
*/
|
|
1214
|
+
protected getEnumValues(schema: TSchema): string[] | undefined {
|
|
1215
|
+
if (!schema) return undefined;
|
|
1216
|
+
|
|
1217
|
+
// Check if schema has an enum property (t.enum creates schemas with this)
|
|
1218
|
+
if (
|
|
1219
|
+
"enum" in schema &&
|
|
1220
|
+
Array.isArray(schema.enum) &&
|
|
1221
|
+
schema.enum.every((v) => typeof v === "string")
|
|
1222
|
+
) {
|
|
1223
|
+
return schema.enum as string[];
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
// Also check for union of string literals (alternative enum representation)
|
|
1227
|
+
if (t.schema.isUnion(schema)) {
|
|
1228
|
+
const union = schema as TUnion;
|
|
1229
|
+
const values: string[] = [];
|
|
1230
|
+
|
|
1231
|
+
for (const variant of union.anyOf) {
|
|
1232
|
+
// Check if the variant is a string literal (has const property)
|
|
1233
|
+
if (
|
|
1234
|
+
t.schema.isString(variant) &&
|
|
1235
|
+
"const" in variant &&
|
|
1236
|
+
typeof variant.const === "string"
|
|
1237
|
+
) {
|
|
1238
|
+
values.push(variant.const);
|
|
1239
|
+
} else {
|
|
1240
|
+
// Not all variants are string literals, not a simple enum
|
|
1241
|
+
return undefined;
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
return values.length > 0 ? values : undefined;
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
return undefined;
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
/**
|
|
1252
|
+
* Format flag description with enum values if applicable.
|
|
1253
|
+
*/
|
|
1254
|
+
protected formatFlagDescription(
|
|
1255
|
+
description: string | undefined,
|
|
1256
|
+
schema: TSchema | undefined,
|
|
1257
|
+
): string {
|
|
1258
|
+
const baseDesc = description ?? "";
|
|
1259
|
+
|
|
1260
|
+
if (!schema) return baseDesc;
|
|
1261
|
+
|
|
1262
|
+
const enumValues = this.getEnumValues(schema);
|
|
1263
|
+
if (enumValues && enumValues.length > 0) {
|
|
1264
|
+
const valuesStr = enumValues.join(", ");
|
|
1265
|
+
const c = this.color;
|
|
1266
|
+
const enumHint = c.set("GREY_DARK", `[${valuesStr}]`);
|
|
1267
|
+
return baseDesc ? `${baseDesc} ${enumHint}` : enumHint;
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
return baseDesc;
|
|
1271
|
+
}
|
|
999
1272
|
}
|