alepha 0.18.2 → 0.18.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/assets/devtools-ui/200.html +2 -2
- package/assets/devtools-ui/200.html.br +0 -0
- package/assets/devtools-ui/404.html +2 -2
- package/assets/devtools-ui/404.html.br +0 -0
- package/assets/devtools-ui/{asset.BfSBZ5Dd.css → asset.hG_f8HuK.css} +1 -1
- package/assets/devtools-ui/asset.hG_f8HuK.css.br +0 -0
- package/assets/devtools-ui/chunk.B3au4Lhg.js +1 -0
- package/assets/devtools-ui/chunk.B3au4Lhg.js.br +0 -0
- package/assets/devtools-ui/chunk.BLOrlnMB.js +1 -0
- package/assets/devtools-ui/chunk.BLOrlnMB.js.br +0 -0
- package/assets/devtools-ui/chunk.BLR01ljW.js +1 -0
- package/assets/devtools-ui/chunk.BLR01ljW.js.br +0 -0
- package/assets/devtools-ui/chunk.BTXaIUlA.js +1 -0
- package/assets/devtools-ui/chunk.BTXaIUlA.js.br +0 -0
- package/assets/devtools-ui/{chunk.lJL-lgnW.js → chunk.BhJaxmm8.js} +1 -1
- package/assets/devtools-ui/chunk.BhJaxmm8.js.br +0 -0
- package/assets/devtools-ui/chunk.BtoNxFuL.js +1 -0
- package/assets/devtools-ui/chunk.BtoNxFuL.js.br +0 -0
- package/assets/devtools-ui/chunk.C8YUV2Wd.js +1 -0
- package/assets/devtools-ui/chunk.C8YUV2Wd.js.br +0 -0
- package/assets/devtools-ui/{chunk.M6wyKO_3.js → chunk.CBbIgDzE.js} +2 -2
- package/assets/devtools-ui/chunk.CBbIgDzE.js.br +0 -0
- package/assets/devtools-ui/chunk.CFqIniwA.js +1 -0
- package/assets/devtools-ui/chunk.CFqIniwA.js.br +0 -0
- package/assets/devtools-ui/chunk.CLFF7f7-.js +1 -0
- package/assets/devtools-ui/chunk.CLFF7f7-.js.br +0 -0
- package/assets/devtools-ui/chunk.CRsBbA10.js +1 -0
- package/assets/devtools-ui/chunk.CRsBbA10.js.br +0 -0
- package/assets/devtools-ui/{chunk.DbEH1oOB.js → chunk.CZPo6v95.js} +1 -1
- package/assets/devtools-ui/chunk.CZPo6v95.js.br +0 -0
- package/assets/devtools-ui/chunk.D0fWgNos.js +1 -0
- package/assets/devtools-ui/chunk.D0fWgNos.js.br +1 -0
- package/assets/devtools-ui/chunk.D7-0ziQ6.js +1 -0
- package/assets/devtools-ui/chunk.D7-0ziQ6.js.br +0 -0
- package/assets/devtools-ui/chunk.DAewe0vm.js +1 -0
- package/assets/devtools-ui/chunk.DAewe0vm.js.br +0 -0
- package/assets/devtools-ui/chunk.DJRQEYqK.js +1 -0
- package/assets/devtools-ui/chunk.DJRQEYqK.js.br +0 -0
- package/assets/devtools-ui/{chunk.CZl6J9DF.js → chunk.DMAxv14p.js} +1 -1
- package/assets/devtools-ui/chunk.DMAxv14p.js.br +0 -0
- package/assets/devtools-ui/{chunk.BT2IiBkZ.js → chunk.DMImnNjU.js} +1 -1
- package/assets/devtools-ui/chunk.DMImnNjU.js.br +0 -0
- package/assets/devtools-ui/chunk.DeeQsidk.js +9 -0
- package/assets/devtools-ui/chunk.DeeQsidk.js.br +0 -0
- package/assets/devtools-ui/chunk.DqEwn9Vj.js +7 -0
- package/assets/devtools-ui/chunk.DqEwn9Vj.js.br +0 -0
- package/assets/devtools-ui/chunk.Dt8OsQey.js +1 -0
- package/assets/devtools-ui/chunk.Dt8OsQey.js.br +0 -0
- package/assets/devtools-ui/{chunk.B9pX3zit.js → chunk.Dtp8oa_f.js} +1 -1
- package/assets/devtools-ui/chunk.Dtp8oa_f.js.br +0 -0
- package/assets/devtools-ui/chunk.Dx3JzAYM.js +1 -0
- package/assets/devtools-ui/chunk.Dx3JzAYM.js.br +0 -0
- package/assets/devtools-ui/chunk.GCOj1-5E.js +1 -0
- package/assets/devtools-ui/chunk.GCOj1-5E.js.br +0 -0
- package/assets/devtools-ui/chunk.IC1LD8BH.js +1 -0
- package/assets/devtools-ui/chunk.IC1LD8BH.js.br +0 -0
- package/assets/devtools-ui/chunk.IwuB_TqW.js +1 -0
- package/assets/devtools-ui/chunk.IwuB_TqW.js.br +0 -0
- package/assets/devtools-ui/chunk.Qqapj2zq.js +1 -0
- package/assets/devtools-ui/chunk.Qqapj2zq.js.br +0 -0
- package/assets/devtools-ui/{chunk.C79YouPp.js → chunk.TKKKndOy.js} +1 -1
- package/assets/devtools-ui/chunk.TKKKndOy.js.br +0 -0
- package/assets/devtools-ui/chunk.YHTVhFQT.js +1 -0
- package/assets/devtools-ui/chunk.YHTVhFQT.js.br +0 -0
- package/assets/devtools-ui/chunk.fnod6uEi.js +1 -0
- package/assets/devtools-ui/chunk.fnod6uEi.js.br +0 -0
- package/assets/devtools-ui/chunk.mOCRmXjo.js +1 -0
- package/assets/devtools-ui/chunk.mOCRmXjo.js.br +0 -0
- package/assets/devtools-ui/chunk.qZTNEAK0.js +1 -0
- package/assets/devtools-ui/chunk.qZTNEAK0.js.br +0 -0
- package/assets/devtools-ui/chunk.rc9m0y4-.js +1 -0
- package/assets/devtools-ui/chunk.rc9m0y4-.js.br +0 -0
- package/assets/devtools-ui/entry.Cxc5QLCU.js +80 -0
- package/assets/devtools-ui/entry.Cxc5QLCU.js.br +0 -0
- package/assets/devtools-ui/index.html +2 -2
- package/assets/devtools-ui/index.html.br +0 -0
- package/assets/swagger-ui/swagger-ui-bundle.js +1 -1
- package/assets/swagger-ui/swagger-ui.css +1 -1
- package/dist/api/audits/index.d.ts +61 -5
- package/dist/api/audits/index.d.ts.map +1 -1
- package/dist/api/files/index.d.ts +61 -5
- package/dist/api/files/index.d.ts.map +1 -1
- package/dist/api/jobs/index.d.ts +61 -5
- package/dist/api/jobs/index.d.ts.map +1 -1
- package/dist/api/jobs/index.js +4 -2
- package/dist/api/jobs/index.js.map +1 -1
- package/dist/api/keys/index.d.ts +5 -5
- package/dist/api/notifications/index.browser.js +44 -1
- package/dist/api/notifications/index.browser.js.map +1 -1
- package/dist/api/notifications/index.d.ts +187 -2
- package/dist/api/notifications/index.d.ts.map +1 -1
- package/dist/api/notifications/index.js +143 -8
- package/dist/api/notifications/index.js.map +1 -1
- package/dist/api/parameters/index.d.ts +61 -5
- package/dist/api/parameters/index.d.ts.map +1 -1
- package/dist/api/users/index.d.ts +330 -93
- package/dist/api/users/index.d.ts.map +1 -1
- package/dist/api/users/index.js +27 -36
- package/dist/api/users/index.js.map +1 -1
- package/dist/cli/config/index.d.ts +46 -0
- package/dist/cli/config/index.d.ts.map +1 -0
- package/dist/cli/config/index.js +20 -0
- package/dist/cli/config/index.js.map +1 -0
- package/dist/cli/core/index.d.ts +69 -66
- package/dist/cli/core/index.d.ts.map +1 -1
- package/dist/cli/core/index.js +329 -196
- package/dist/cli/core/index.js.map +1 -1
- package/dist/cli/platform/index.d.ts +302 -63
- package/dist/cli/platform/index.d.ts.map +1 -1
- package/dist/cli/platform/index.js +455 -25
- package/dist/cli/platform/index.js.map +1 -1
- package/dist/core/index.browser.js +125 -87
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +62 -53
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +125 -87
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js +125 -87
- package/dist/core/index.native.js.map +1 -1
- package/dist/core/index.workerd.js +125 -87
- package/dist/core/index.workerd.js.map +1 -1
- package/dist/crypto/index.d.ts +18 -1
- package/dist/crypto/index.d.ts.map +1 -1
- package/dist/crypto/index.js +29 -3
- package/dist/crypto/index.js.map +1 -1
- package/dist/devtools/index.js +3 -12
- package/dist/devtools/index.js.map +1 -1
- package/dist/logger/index.d.ts +10 -1
- package/dist/logger/index.d.ts.map +1 -1
- package/dist/logger/index.js +19 -9
- package/dist/logger/index.js.map +1 -1
- package/dist/orm/core/index.browser.js +57 -1
- package/dist/orm/core/index.browser.js.map +1 -1
- package/dist/orm/core/index.bun.js +378 -19
- package/dist/orm/core/index.bun.js.map +1 -1
- package/dist/orm/core/index.d.ts +328 -9
- package/dist/orm/core/index.d.ts.map +1 -1
- package/dist/orm/core/index.js +384 -21
- package/dist/orm/core/index.js.map +1 -1
- package/dist/orm/postgres/index.bun.js +49 -17
- package/dist/orm/postgres/index.bun.js.map +1 -1
- package/dist/orm/postgres/index.d.ts +47 -21
- package/dist/orm/postgres/index.d.ts.map +1 -1
- package/dist/orm/postgres/index.js +52 -17
- package/dist/orm/postgres/index.js.map +1 -1
- package/dist/react/core/index.d.ts +1 -1
- package/dist/react/core/index.d.ts.map +1 -1
- package/dist/react/core/index.js +6 -1
- package/dist/react/core/index.js.map +1 -1
- package/dist/react/form/index.d.ts +28 -18
- package/dist/react/form/index.d.ts.map +1 -1
- package/dist/react/form/index.js +92 -56
- package/dist/react/form/index.js.map +1 -1
- package/dist/react/router/index.browser.js +448 -116
- package/dist/react/router/index.browser.js.map +1 -1
- package/dist/react/router/index.d.ts +102 -40
- package/dist/react/router/index.d.ts.map +1 -1
- package/dist/react/router/index.js +453 -92
- package/dist/react/router/index.js.map +1 -1
- package/dist/security/index.d.ts +3 -11
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +6 -11
- package/dist/security/index.js.map +1 -1
- package/dist/server/auth/index.d.ts +22 -24
- package/dist/server/auth/index.d.ts.map +1 -1
- package/dist/server/auth/index.js +102 -82
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/cookies/index.d.ts +7 -4
- package/dist/server/cookies/index.d.ts.map +1 -1
- package/dist/server/cookies/index.js +13 -12
- package/dist/server/cookies/index.js.map +1 -1
- package/dist/server/core/index.d.ts +288 -4
- package/dist/server/core/index.d.ts.map +1 -1
- package/dist/server/core/index.js +375 -2
- package/dist/server/core/index.js.map +1 -1
- package/dist/server/links/index.browser.js +10 -71
- package/dist/server/links/index.browser.js.map +1 -1
- package/dist/server/links/index.d.ts +32 -49
- package/dist/server/links/index.d.ts.map +1 -1
- package/dist/server/links/index.js +73 -100
- package/dist/server/links/index.js.map +1 -1
- package/dist/system/index.browser.js +221 -2
- package/dist/system/index.browser.js.map +1 -1
- package/dist/system/index.d.ts +63 -1
- package/dist/system/index.d.ts.map +1 -1
- package/dist/system/index.js +221 -1
- package/dist/system/index.js.map +1 -1
- package/dist/system/index.workerd.js +224 -4
- package/dist/system/index.workerd.js.map +1 -1
- package/package.json +10 -5
- package/src/api/jobs/providers/JobProvider.ts +6 -3
- package/src/api/notifications/controllers/AdminNotificationController.ts +83 -0
- package/src/api/notifications/index.browser.ts +3 -0
- package/src/api/notifications/index.ts +14 -2
- package/src/api/notifications/jobs/NotificationJobs.ts +11 -2
- package/src/api/notifications/schemas/notificationDetailResourceSchema.ts +20 -0
- package/src/api/notifications/schemas/notificationQuerySchema.ts +19 -0
- package/src/api/notifications/schemas/notificationResourceSchema.ts +18 -0
- package/src/api/notifications/services/NotificationSenderService.ts +15 -2
- package/src/api/users/atoms/realmAuthSettingsAtom.ts +28 -32
- package/src/api/users/buckets/UserBuckets.ts +1 -1
- package/src/api/users/jobs/UserJobs.ts +1 -1
- package/src/api/users/primitives/$realm.ts +8 -49
- package/src/api/users/providers/RealmProvider.ts +2 -3
- package/src/api/users/services/RegistrationService.spec.ts +7 -7
- package/src/api/users/services/RegistrationService.ts +3 -3
- package/src/api/users/services/SessionService.spec.ts +4 -4
- package/src/api/users/services/SessionService.ts +3 -3
- package/src/cli/{core → config}/defineConfig.ts +14 -20
- package/src/cli/config/index.ts +1 -0
- package/src/cli/core/commands/db.ts +65 -1
- package/src/cli/core/commands/dev.ts +1 -0
- package/src/cli/core/commands/init.ts +2 -192
- package/src/cli/core/index.ts +34 -11
- package/src/cli/core/providers/ViteDevServerProvider.ts +52 -13
- package/src/cli/core/services/PackageManagerUtils.ts +43 -21
- package/src/cli/core/services/ProjectScaffolder.ts +214 -2
- package/src/cli/core/services/ViteUtils.ts +57 -0
- package/src/cli/core/tasks/BuildClientTask.ts +7 -2
- package/src/cli/core/tasks/BuildCloudflareTask.ts +4 -12
- package/src/cli/core/tasks/BuildServerTask.ts +2 -0
- package/src/cli/core/tasks/BuildVercelTask.ts +165 -168
- package/src/cli/core/templates/alephaConfigTs.ts +1 -1
- package/src/cli/core/templates/apiAppSecurityTs.ts +5 -8
- package/src/cli/core/templates/tsconfigJson.ts +6 -1
- package/src/cli/platform/adapters/CloudflareAdapter.spec.ts +1 -1
- package/src/cli/platform/adapters/CloudflareAdapter.ts +30 -29
- package/src/cli/platform/atoms/platformOptions.ts +21 -0
- package/src/cli/platform/commands/SecretsCommand.spec.ts +298 -0
- package/src/cli/platform/commands/SecretsCommand.ts +283 -0
- package/src/cli/platform/commands/platform.ts +12 -0
- package/src/cli/platform/index.ts +14 -28
- package/src/cli/platform/providers/GitHubSecretStore.spec.ts +153 -0
- package/src/cli/platform/providers/GitHubSecretStore.ts +112 -0
- package/src/cli/platform/providers/MemorySecretStore.ts +114 -0
- package/src/cli/platform/providers/SecretStoreProvider.ts +39 -0
- package/src/cli/platform/schemas/cloudflare.ts +2 -0
- package/src/cli/platform/services/CloudflareApi.ts +5 -2
- package/src/cli/platform/services/DockerComposeGenerator.spec.ts +115 -0
- package/src/cli/platform/services/DockerComposeGenerator.ts +46 -1
- package/src/cli/platform/services/SecretFilterService.spec.ts +111 -0
- package/src/cli/platform/services/SecretFilterService.ts +54 -0
- package/src/core/Alepha.ts +94 -25
- package/src/core/__tests__/Alepha-parseEnv.spec.ts +20 -0
- package/src/core/primitives/$memoize.ts +38 -26
- package/src/core/providers/AlsProvider.ts +2 -0
- package/src/core/providers/EventManager.ts +4 -0
- package/src/core/providers/KeylessJsonSchemaCodec.spec.ts +1 -4
- package/src/core/providers/KeylessJsonSchemaCodec.ts +19 -125
- package/src/core/providers/SchemaValidator.spec.ts +36 -0
- package/src/core/providers/SchemaValidator.ts +9 -0
- package/src/crypto/index.ts +6 -1
- package/src/crypto/providers/SecretProvider.ts +36 -0
- package/src/devtools/providers/DevToolsProvider.ts +3 -12
- package/src/logger/index.ts +33 -6
- package/src/logger/providers/PrettyFormatterProvider.ts +5 -3
- package/src/orm/__tests__/orm-next-tests.ts +492 -0
- package/src/orm/__tests__/orm-next.spec.ts +140 -0
- package/src/orm/core/constants/PG_SYMBOLS.ts +17 -0
- package/src/orm/core/index.bun.ts +3 -6
- package/src/orm/core/index.shared-server.ts +2 -0
- package/src/orm/core/index.shared.ts +2 -0
- package/src/orm/core/index.ts +5 -7
- package/src/orm/core/interfaces/AggregateQuery.ts +103 -0
- package/src/orm/core/interfaces/PgQueryWhere.ts +7 -0
- package/src/orm/core/primitives/$entity.ts +8 -0
- package/src/orm/core/primitives/$repository.ts +6 -3
- package/src/orm/core/primitives/$view.ts +88 -0
- package/src/orm/core/providers/DbCacheProvider.ts +66 -0
- package/src/orm/core/providers/DrizzleKitProvider.ts +42 -0
- package/src/orm/core/providers/drivers/BunSqliteProvider.ts +2 -3
- package/src/orm/core/providers/drivers/CloudflareD1Provider.ts +12 -0
- package/src/orm/core/providers/drivers/DatabaseProvider.ts +39 -0
- package/src/orm/core/providers/drivers/NodeSqliteProvider.ts +2 -3
- package/src/orm/core/schemas/databaseEnvSchema.ts +31 -0
- package/src/orm/core/schemas/insertSchema.ts +13 -3
- package/src/orm/core/schemas/updateSchema.ts +14 -3
- package/src/orm/core/services/ModelBuilder.ts +26 -14
- package/src/orm/core/services/QueryManager.ts +13 -0
- package/src/orm/core/services/Repository.ts +307 -5
- package/src/orm/core/services/SqliteModelBuilder.ts +38 -0
- package/src/orm/postgres/index.bun.ts +4 -7
- package/src/orm/postgres/index.ts +4 -7
- package/src/orm/postgres/providers/BunPostgresProvider.ts +12 -2
- package/src/orm/postgres/providers/NodePostgresProvider.ts +7 -0
- package/src/orm/postgres/providers/PglitePostgresProvider.ts +10 -17
- package/src/orm/postgres/providers/PostgresProvider.ts +7 -36
- package/src/orm/postgres/schemas/postgresEnvSchema.ts +32 -0
- package/src/orm/postgres/services/PostgresModelBuilder.ts +40 -0
- package/src/react/core/components/ErrorBoundary.tsx +5 -2
- package/src/react/form/hooks/useFieldValue.ts +34 -0
- package/src/react/form/hooks/useForm.browser.spec.tsx +94 -9
- package/src/react/form/hooks/useForm.ts +14 -2
- package/src/react/form/hooks/useFormState.ts +10 -10
- package/src/react/form/hooks/useFormValues.ts +29 -0
- package/src/react/form/index.ts +3 -1
- package/src/react/form/services/FormModel.ts +53 -122
- package/src/react/router/components/ErrorViewer.tsx +333 -34
- package/src/react/router/components/NestedView.tsx +10 -3
- package/src/react/router/primitives/$page.browser.spec.tsx +34 -0
- package/src/react/router/primitives/$page.spec.tsx +20 -0
- package/src/react/router/primitives/$page.ts +24 -0
- package/src/react/router/providers/ReactBrowserRouterProvider.ts +14 -2
- package/src/react/router/providers/ReactPageProvider.ts +156 -73
- package/src/react/router/providers/ReactServerProvider.ts +40 -2
- package/src/react/router/providers/ReactServerTemplateProvider.ts +13 -1
- package/src/security/providers/SecurityProvider.ts +5 -27
- package/src/server/auth/primitives/$auth.ts +52 -19
- package/src/server/auth/providers/ServerAuthProvider.ts +145 -139
- package/src/server/cookies/providers/ServerCookiesProvider.ts +12 -24
- package/src/server/core/index.ts +3 -1
- package/src/server/core/primitives/$sse.spec.ts +315 -0
- package/src/server/core/primitives/$sse.ts +715 -0
- package/src/server/links/index.browser.ts +1 -3
- package/src/server/links/index.ts +0 -3
- package/src/server/links/providers/LinkProvider.spec.ts +12 -21
- package/src/server/links/providers/LinkProvider.ts +20 -52
- package/src/server/links/providers/ServerLinksProvider.spec.ts +106 -0
- package/src/server/links/providers/ServerLinksProvider.ts +113 -73
- package/src/server/links/schemas/apiLinksResponseSchema.ts +4 -21
- package/src/server/links/services/BatchCollector.ts +5 -3
- package/src/system/index.browser.ts +1 -0
- package/src/system/index.ts +3 -0
- package/src/system/index.workerd.ts +39 -1
- package/src/system/providers/WorkerdFileSystemProvider.ts +365 -0
- package/assets/devtools-ui/asset.BfSBZ5Dd.css.br +0 -0
- package/assets/devtools-ui/chunk.2NYaoqWt.js +0 -1
- package/assets/devtools-ui/chunk.2NYaoqWt.js.br +0 -0
- package/assets/devtools-ui/chunk.B052Z_xQ.js +0 -1
- package/assets/devtools-ui/chunk.B052Z_xQ.js.br +0 -0
- package/assets/devtools-ui/chunk.B4kVY90C.js +0 -1
- package/assets/devtools-ui/chunk.B4kVY90C.js.br +0 -0
- package/assets/devtools-ui/chunk.B7QJXctB.js +0 -1
- package/assets/devtools-ui/chunk.B7QJXctB.js.br +0 -0
- package/assets/devtools-ui/chunk.B9pX3zit.js.br +0 -0
- package/assets/devtools-ui/chunk.BKF9JxIo.js +0 -1
- package/assets/devtools-ui/chunk.BKF9JxIo.js.br +0 -0
- package/assets/devtools-ui/chunk.BOHgdTP-.js +0 -1
- package/assets/devtools-ui/chunk.BOHgdTP-.js.br +0 -0
- package/assets/devtools-ui/chunk.BOVFxkYC.js +0 -1
- package/assets/devtools-ui/chunk.BOVFxkYC.js.br +0 -0
- package/assets/devtools-ui/chunk.BR842zj5.js +0 -1
- package/assets/devtools-ui/chunk.BR842zj5.js.br +0 -0
- package/assets/devtools-ui/chunk.BT2IiBkZ.js.br +0 -0
- package/assets/devtools-ui/chunk.C79YouPp.js.br +0 -0
- package/assets/devtools-ui/chunk.C8mlBrjW.js +0 -9
- package/assets/devtools-ui/chunk.C8mlBrjW.js.br +0 -0
- package/assets/devtools-ui/chunk.CK0ow3AZ.js +0 -1
- package/assets/devtools-ui/chunk.CK0ow3AZ.js.br +0 -0
- package/assets/devtools-ui/chunk.CZl6J9DF.js.br +0 -0
- package/assets/devtools-ui/chunk.CdNr0YzS.js +0 -1
- package/assets/devtools-ui/chunk.CdNr0YzS.js.br +0 -0
- package/assets/devtools-ui/chunk.Ce6_6iIF.js +0 -1
- package/assets/devtools-ui/chunk.Ce6_6iIF.js.br +0 -0
- package/assets/devtools-ui/chunk.CpyDMr6O.js +0 -1
- package/assets/devtools-ui/chunk.CpyDMr6O.js.br +0 -0
- package/assets/devtools-ui/chunk.CyPmvPnY.js +0 -1
- package/assets/devtools-ui/chunk.CyPmvPnY.js.br +0 -0
- package/assets/devtools-ui/chunk.DTI_geWu.js +0 -1
- package/assets/devtools-ui/chunk.DTI_geWu.js.br +0 -0
- package/assets/devtools-ui/chunk.DbEH1oOB.js.br +0 -0
- package/assets/devtools-ui/chunk.Ddeqj5gv.js +0 -1
- package/assets/devtools-ui/chunk.Ddeqj5gv.js.br +0 -0
- package/assets/devtools-ui/chunk.DpRnB4vJ.js +0 -1
- package/assets/devtools-ui/chunk.DpRnB4vJ.js.br +0 -0
- package/assets/devtools-ui/chunk.DxPGTlsg.js +0 -1
- package/assets/devtools-ui/chunk.DxPGTlsg.js.br +0 -0
- package/assets/devtools-ui/chunk.G7_MMBJS.js +0 -1
- package/assets/devtools-ui/chunk.G7_MMBJS.js.br +0 -0
- package/assets/devtools-ui/chunk.M6wyKO_3.js.br +0 -0
- package/assets/devtools-ui/chunk.OUxNGmQ6.js +0 -1
- package/assets/devtools-ui/chunk.OUxNGmQ6.js.br +0 -0
- package/assets/devtools-ui/chunk.T1kle-fF.js +0 -1
- package/assets/devtools-ui/chunk.T1kle-fF.js.br +0 -0
- package/assets/devtools-ui/chunk.WjpsbQAv.js +0 -1
- package/assets/devtools-ui/chunk.WjpsbQAv.js.br +0 -0
- package/assets/devtools-ui/chunk.c6YgVx86.js +0 -1
- package/assets/devtools-ui/chunk.c6YgVx86.js.br +0 -0
- package/assets/devtools-ui/chunk.dwU3E_MU.js +0 -1
- package/assets/devtools-ui/chunk.dwU3E_MU.js.br +0 -0
- package/assets/devtools-ui/chunk.lJL-lgnW.js.br +0 -0
- package/assets/devtools-ui/chunk.lPWRmvA-.js +0 -7
- package/assets/devtools-ui/chunk.lPWRmvA-.js.br +0 -0
- package/assets/devtools-ui/chunk.p3HJvugM.js +0 -1
- package/assets/devtools-ui/chunk.p3HJvugM.js.br +0 -0
- package/assets/devtools-ui/chunk.r_Xoa_CI.js +0 -1
- package/assets/devtools-ui/chunk.r_Xoa_CI.js.br +0 -0
- package/assets/devtools-ui/chunk.sRNuTYXb.js +0 -1
- package/assets/devtools-ui/chunk.sRNuTYXb.js.br +0 -0
- package/assets/devtools-ui/chunk.tUjcyX5C.js +0 -1
- package/assets/devtools-ui/chunk.tUjcyX5C.js.br +0 -0
- package/assets/devtools-ui/chunk.thjBxvCA.js +0 -1
- package/assets/devtools-ui/chunk.thjBxvCA.js.br +0 -0
- package/assets/devtools-ui/entry.GYhBVRpC.js +0 -78
- package/assets/devtools-ui/entry.GYhBVRpC.js.br +0 -0
- package/src/server/links/services/DefinitionsPool.spec.ts +0 -86
- package/src/server/links/services/DefinitionsPool.ts +0 -43
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "alepha",
|
|
3
3
|
"description": "Easy-to-use modern TypeScript framework for building many kind of applications.",
|
|
4
4
|
"author": "Nicolas Foures",
|
|
5
|
-
"version": "0.18.
|
|
5
|
+
"version": "0.18.3",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"engines": {
|
|
8
8
|
"node": ">=22.0.0"
|
|
@@ -25,18 +25,18 @@
|
|
|
25
25
|
"drizzle-orm": "^0.45.1",
|
|
26
26
|
"postgres": "^3.4.8",
|
|
27
27
|
"tsx": "^4.21.0",
|
|
28
|
-
"typebox": "^1.1.
|
|
28
|
+
"typebox": "^1.1.5",
|
|
29
29
|
"typescript": "^5.9.3",
|
|
30
30
|
"vite-bundle-analyzer": "^1.3.6",
|
|
31
31
|
"ws": "^8.19.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"@biomejs/biome": "^2.4.
|
|
34
|
+
"@biomejs/biome": "^2.4.5",
|
|
35
35
|
"@electric-sql/pglite": "^0.3.15",
|
|
36
36
|
"@faker-js/faker": "^10.3.0",
|
|
37
37
|
"@testing-library/dom": "^10.4.1",
|
|
38
38
|
"@testing-library/react": "^16.3.2",
|
|
39
|
-
"@types/node": "^25.3.
|
|
39
|
+
"@types/node": "^25.3.3",
|
|
40
40
|
"@types/nodemailer": "^7.0.11",
|
|
41
41
|
"@types/react": "^19.2.14",
|
|
42
42
|
"@types/react-dom": "^19.2.3",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"prom-client": "^15.1.3",
|
|
52
52
|
"react": "^19.2.4",
|
|
53
53
|
"react-dom": "^19.2.4",
|
|
54
|
-
"swagger-ui-dist": "^5.
|
|
54
|
+
"swagger-ui-dist": "^5.32.0",
|
|
55
55
|
"tsdown": "^0.20.3",
|
|
56
56
|
"vite": "^7.3.1",
|
|
57
57
|
"vitest": "^4.0.18"
|
|
@@ -174,6 +174,11 @@
|
|
|
174
174
|
"import": "./dist/cache/redis/index.js",
|
|
175
175
|
"default": "./dist/cache/redis/index.js"
|
|
176
176
|
},
|
|
177
|
+
"./cli/config": {
|
|
178
|
+
"types": "./dist/cli/config/index.d.ts",
|
|
179
|
+
"import": "./dist/cli/config/index.js",
|
|
180
|
+
"default": "./dist/cli/config/index.js"
|
|
181
|
+
},
|
|
177
182
|
"./cli": {
|
|
178
183
|
"types": "./dist/cli/core/index.d.ts",
|
|
179
184
|
"import": "./dist/cli/core/index.js",
|
|
@@ -796,9 +796,12 @@ export class JobProvider {
|
|
|
796
796
|
entries.push(entry);
|
|
797
797
|
});
|
|
798
798
|
|
|
799
|
-
// Run initial sweeps to recover from previous crashes
|
|
800
|
-
|
|
801
|
-
|
|
799
|
+
// Run initial sweeps to recover from previous crashes.
|
|
800
|
+
// Skipped on serverless — cron triggers handle periodic sweeps instead.
|
|
801
|
+
if (!this.alepha.isServerless()) {
|
|
802
|
+
await this.delayedDispatchSweep();
|
|
803
|
+
await this.recoverySweep();
|
|
804
|
+
}
|
|
802
805
|
|
|
803
806
|
// Periodic sweeps via cron (works in serverless environments like Cloudflare Workers)
|
|
804
807
|
this.cronProvider.createCronJob(
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { $inject, t } from "alepha";
|
|
2
|
+
import { JobService } from "alepha/api/jobs";
|
|
3
|
+
import { $secure } from "alepha/security";
|
|
4
|
+
import { $action } from "alepha/server";
|
|
5
|
+
import { NotificationJobs } from "../jobs/NotificationJobs.ts";
|
|
6
|
+
import { notificationDetailResourceSchema } from "../schemas/notificationDetailResourceSchema.ts";
|
|
7
|
+
import { notificationQuerySchema } from "../schemas/notificationQuerySchema.ts";
|
|
8
|
+
import { notificationResourceSchema } from "../schemas/notificationResourceSchema.ts";
|
|
9
|
+
|
|
10
|
+
export class AdminNotificationController {
|
|
11
|
+
protected readonly url: string = "/notifications";
|
|
12
|
+
protected readonly group: string = "admin:notifications";
|
|
13
|
+
protected readonly jobService = $inject(JobService);
|
|
14
|
+
protected readonly notificationJobs = $inject(NotificationJobs);
|
|
15
|
+
|
|
16
|
+
protected get jobName(): string {
|
|
17
|
+
return this.notificationJobs.sendNotification.name;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public readonly findNotifications = $action({
|
|
21
|
+
path: this.url,
|
|
22
|
+
group: this.group,
|
|
23
|
+
use: [$secure({ permissions: ["admin:notification:read"] })],
|
|
24
|
+
schema: {
|
|
25
|
+
query: notificationQuerySchema,
|
|
26
|
+
response: t.page(notificationResourceSchema),
|
|
27
|
+
},
|
|
28
|
+
handler: async ({ query }) => {
|
|
29
|
+
const result = await this.jobService.findExecutions({
|
|
30
|
+
...query,
|
|
31
|
+
job: this.jobName,
|
|
32
|
+
});
|
|
33
|
+
return {
|
|
34
|
+
...result,
|
|
35
|
+
content: result.content.map((exec) => this.toResource(exec)),
|
|
36
|
+
} as any;
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
public readonly getNotification = $action({
|
|
41
|
+
path: `${this.url}/:id`,
|
|
42
|
+
group: this.group,
|
|
43
|
+
use: [$secure({ permissions: ["admin:notification:read"] })],
|
|
44
|
+
schema: {
|
|
45
|
+
params: t.object({
|
|
46
|
+
id: t.uuid(),
|
|
47
|
+
}),
|
|
48
|
+
response: notificationDetailResourceSchema,
|
|
49
|
+
},
|
|
50
|
+
handler: async ({ params }) => {
|
|
51
|
+
const detail = await this.jobService.getExecution(params.id);
|
|
52
|
+
return this.toDetailResource(detail) as any;
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
protected toResource(exec: Record<string, unknown>) {
|
|
57
|
+
const payload = (exec.payload ?? {}) as Record<string, unknown>;
|
|
58
|
+
return {
|
|
59
|
+
id: exec.id,
|
|
60
|
+
createdAt: exec.createdAt,
|
|
61
|
+
status: exec.status,
|
|
62
|
+
template: payload.template,
|
|
63
|
+
type: payload.type,
|
|
64
|
+
contact: payload.contact,
|
|
65
|
+
category: payload.category,
|
|
66
|
+
critical: payload.critical,
|
|
67
|
+
sensitive: payload.sensitive,
|
|
68
|
+
startedAt: exec.startedAt,
|
|
69
|
+
completedAt: exec.completedAt,
|
|
70
|
+
error: exec.error,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
protected toDetailResource(exec: Record<string, unknown>) {
|
|
75
|
+
const payload = (exec.payload ?? {}) as Record<string, unknown>;
|
|
76
|
+
return {
|
|
77
|
+
...this.toResource(exec),
|
|
78
|
+
variables: payload.variables,
|
|
79
|
+
rendered: exec.result,
|
|
80
|
+
logs: exec.logs,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -4,7 +4,10 @@ import { $module } from "alepha";
|
|
|
4
4
|
|
|
5
5
|
export * from "./schemas/notificationContactPreferencesSchema.ts";
|
|
6
6
|
export * from "./schemas/notificationContactSchema.ts";
|
|
7
|
+
export * from "./schemas/notificationDetailResourceSchema.ts";
|
|
7
8
|
export * from "./schemas/notificationPayloadSchema.ts";
|
|
9
|
+
export * from "./schemas/notificationQuerySchema.ts";
|
|
10
|
+
export * from "./schemas/notificationResourceSchema.ts";
|
|
8
11
|
|
|
9
12
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
10
13
|
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import { $module } from "alepha";
|
|
2
|
+
import { AdminNotificationController } from "./controllers/AdminNotificationController.ts";
|
|
2
3
|
import { NotificationJobs } from "./jobs/NotificationJobs.ts";
|
|
3
4
|
import { $notification } from "./primitives/$notification.ts";
|
|
4
5
|
import { NotificationSenderService } from "./services/NotificationSenderService.ts";
|
|
5
6
|
|
|
6
7
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
7
8
|
|
|
9
|
+
export * from "./controllers/AdminNotificationController.ts";
|
|
8
10
|
export * from "./jobs/NotificationJobs.ts";
|
|
9
11
|
export * from "./primitives/$notification.ts";
|
|
10
12
|
export * from "./schemas/notificationContactPreferencesSchema.ts";
|
|
11
13
|
export * from "./schemas/notificationContactSchema.ts";
|
|
14
|
+
export * from "./schemas/notificationDetailResourceSchema.ts";
|
|
12
15
|
export * from "./schemas/notificationPayloadSchema.ts";
|
|
16
|
+
export * from "./schemas/notificationQuerySchema.ts";
|
|
17
|
+
export * from "./schemas/notificationResourceSchema.ts";
|
|
13
18
|
export * from "./services/NotificationSenderService.ts";
|
|
14
19
|
|
|
15
20
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
@@ -28,8 +33,15 @@ export * from "./services/NotificationSenderService.ts";
|
|
|
28
33
|
export const AlephaApiNotifications = $module({
|
|
29
34
|
name: "alepha.api.notifications",
|
|
30
35
|
primitives: [$notification],
|
|
31
|
-
services: [
|
|
36
|
+
services: [
|
|
37
|
+
NotificationSenderService,
|
|
38
|
+
NotificationJobs,
|
|
39
|
+
AdminNotificationController,
|
|
40
|
+
],
|
|
32
41
|
register: (alepha) => {
|
|
33
|
-
alepha
|
|
42
|
+
alepha
|
|
43
|
+
.with(NotificationSenderService)
|
|
44
|
+
.with(NotificationJobs)
|
|
45
|
+
.with(AdminNotificationController);
|
|
34
46
|
},
|
|
35
47
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { $inject } from "alepha";
|
|
2
|
-
import { $job } from "alepha/api/jobs";
|
|
2
|
+
import { $job, jobExecutionEntity } from "alepha/api/jobs";
|
|
3
|
+
import { $repository } from "alepha/orm";
|
|
3
4
|
import { notificationPayloadSchema } from "../schemas/notificationPayloadSchema.ts";
|
|
4
5
|
import { NotificationSenderService } from "../services/NotificationSenderService.ts";
|
|
5
6
|
|
|
@@ -7,6 +8,7 @@ export class NotificationJobs {
|
|
|
7
8
|
protected readonly notificationSenderService = $inject(
|
|
8
9
|
NotificationSenderService,
|
|
9
10
|
);
|
|
11
|
+
protected readonly executions = $repository(jobExecutionEntity);
|
|
10
12
|
|
|
11
13
|
public readonly sendNotification = $job({
|
|
12
14
|
schema: notificationPayloadSchema,
|
|
@@ -23,7 +25,14 @@ export class NotificationJobs {
|
|
|
23
25
|
concurrency: 5,
|
|
24
26
|
handler: async ({ items }) => {
|
|
25
27
|
for (const item of items) {
|
|
26
|
-
await this.notificationSenderService.send(
|
|
28
|
+
const rendered = await this.notificationSenderService.send(
|
|
29
|
+
item.payload,
|
|
30
|
+
);
|
|
31
|
+
if (rendered) {
|
|
32
|
+
await this.executions.updateById(item.id, {
|
|
33
|
+
result: rendered as Record<string, unknown>,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
27
36
|
}
|
|
28
37
|
},
|
|
29
38
|
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type Static, t } from "alepha";
|
|
2
|
+
import { logEntrySchema } from "alepha/logger";
|
|
3
|
+
import { notificationResourceSchema } from "./notificationResourceSchema.ts";
|
|
4
|
+
|
|
5
|
+
export const notificationDetailResourceSchema = t.extend(
|
|
6
|
+
notificationResourceSchema,
|
|
7
|
+
{
|
|
8
|
+
variables: t.optional(t.record(t.text(), t.any())),
|
|
9
|
+
rendered: t.optional(t.record(t.text(), t.any())),
|
|
10
|
+
logs: t.optional(t.array(logEntrySchema)),
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
title: "NotificationDetailResource",
|
|
14
|
+
description: "A notification resource with rendered content and logs.",
|
|
15
|
+
},
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
export type NotificationDetailResource = Static<
|
|
19
|
+
typeof notificationDetailResourceSchema
|
|
20
|
+
>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type Static, t } from "alepha";
|
|
2
|
+
import { pageQuerySchema } from "alepha/orm";
|
|
3
|
+
|
|
4
|
+
export const notificationQuerySchema = t.extend(pageQuerySchema, {
|
|
5
|
+
status: t.optional(
|
|
6
|
+
t.enum([
|
|
7
|
+
"pending",
|
|
8
|
+
"scheduled",
|
|
9
|
+
"retrying",
|
|
10
|
+
"running",
|
|
11
|
+
"completed",
|
|
12
|
+
"failed",
|
|
13
|
+
"dead",
|
|
14
|
+
"cancelled",
|
|
15
|
+
]),
|
|
16
|
+
),
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
export type NotificationQuery = Static<typeof notificationQuerySchema>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type Static, t } from "alepha";
|
|
2
|
+
|
|
3
|
+
export const notificationResourceSchema = t.object({
|
|
4
|
+
id: t.uuid(),
|
|
5
|
+
createdAt: t.datetime(),
|
|
6
|
+
status: t.text(),
|
|
7
|
+
template: t.optional(t.text()),
|
|
8
|
+
type: t.optional(t.text()),
|
|
9
|
+
contact: t.optional(t.text()),
|
|
10
|
+
category: t.optional(t.text()),
|
|
11
|
+
critical: t.optional(t.boolean()),
|
|
12
|
+
sensitive: t.optional(t.boolean()),
|
|
13
|
+
startedAt: t.optional(t.datetime()),
|
|
14
|
+
completedAt: t.optional(t.datetime()),
|
|
15
|
+
error: t.optional(t.text()),
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export type NotificationResource = Static<typeof notificationResourceSchema>;
|
|
@@ -19,19 +19,32 @@ export class NotificationSenderService {
|
|
|
19
19
|
});
|
|
20
20
|
|
|
21
21
|
if (payload.type === "email") {
|
|
22
|
-
|
|
22
|
+
const rendered = this.renderEmail(payload);
|
|
23
|
+
await this.emailProvider.send(rendered);
|
|
23
24
|
this.log.info("Email notification sent", {
|
|
24
25
|
template: payload.template,
|
|
25
26
|
contact: payload.contact,
|
|
26
27
|
});
|
|
28
|
+
return {
|
|
29
|
+
type: "email" as const,
|
|
30
|
+
to: rendered.to,
|
|
31
|
+
subject: rendered.subject,
|
|
32
|
+
body: rendered.body,
|
|
33
|
+
};
|
|
27
34
|
}
|
|
28
35
|
|
|
29
36
|
if (payload.type === "sms") {
|
|
30
|
-
|
|
37
|
+
const rendered = this.renderSms(payload);
|
|
38
|
+
await this.smsProvider.send(rendered);
|
|
31
39
|
this.log.info("SMS notification sent", {
|
|
32
40
|
template: payload.template,
|
|
33
41
|
contact: payload.contact,
|
|
34
42
|
});
|
|
43
|
+
return {
|
|
44
|
+
type: "sms" as const,
|
|
45
|
+
to: rendered.to,
|
|
46
|
+
message: rendered.message,
|
|
47
|
+
};
|
|
35
48
|
}
|
|
36
49
|
}
|
|
37
50
|
|
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
import { $atom, type Static, t } from "alepha";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Tri-state field requirement for realm auth settings.
|
|
5
|
+
*
|
|
6
|
+
* - `"none"`: Field is disabled and not shown.
|
|
7
|
+
* - `"optional"`: Field is shown but not required.
|
|
8
|
+
* - `"required"`: Field is shown and required.
|
|
9
|
+
*/
|
|
10
|
+
export type FieldRequirement = "none" | "optional" | "required";
|
|
11
|
+
|
|
12
|
+
const fieldRequirement = (description: string) =>
|
|
13
|
+
t.union([t.const("none"), t.const("optional"), t.const("required")], {
|
|
14
|
+
description,
|
|
15
|
+
});
|
|
16
|
+
|
|
3
17
|
export const realmAuthSettingsAtom = $atom({
|
|
4
18
|
name: "alepha.api.users.realmAuthSettings",
|
|
5
19
|
schema: t.object({
|
|
@@ -25,40 +39,26 @@ export const realmAuthSettingsAtom = $atom({
|
|
|
25
39
|
registrationAllowed: t.boolean({
|
|
26
40
|
description: "Enable user self-registration",
|
|
27
41
|
}),
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
description: "Require email address for user accounts",
|
|
33
|
-
}),
|
|
34
|
-
usernameEnabled: t.boolean({
|
|
35
|
-
description: "Enable username as a login/registration credential",
|
|
36
|
-
}),
|
|
37
|
-
usernameRequired: t.boolean({
|
|
38
|
-
description: "Require username for user accounts",
|
|
39
|
-
}),
|
|
42
|
+
email: fieldRequirement(
|
|
43
|
+
"Email address field requirement for user accounts",
|
|
44
|
+
),
|
|
45
|
+
username: fieldRequirement("Username field requirement for user accounts"),
|
|
40
46
|
usernameRegExp: t.string({
|
|
41
47
|
description:
|
|
42
48
|
"Regular expression that usernames must match (if username is enabled)",
|
|
43
49
|
}),
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
phoneRequired: t.boolean({
|
|
48
|
-
description: "Require phone number for user accounts",
|
|
49
|
-
}),
|
|
50
|
+
phoneNumber: fieldRequirement(
|
|
51
|
+
"Phone number field requirement for user accounts",
|
|
52
|
+
),
|
|
50
53
|
verifyEmailRequired: t.boolean({
|
|
51
54
|
description: "Require email verification for user accounts",
|
|
52
55
|
}),
|
|
53
56
|
verifyPhoneRequired: t.boolean({
|
|
54
57
|
description: "Require phone verification for user accounts",
|
|
55
58
|
}),
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
firstNameLastNameRequired: t.boolean({
|
|
60
|
-
description: "Require first and last name for user accounts",
|
|
61
|
-
}),
|
|
59
|
+
firstNameLastName: fieldRequirement(
|
|
60
|
+
"First and last name field requirement for user accounts",
|
|
61
|
+
),
|
|
62
62
|
resetPasswordAllowed: t.boolean({
|
|
63
63
|
description: "Enable forgot password functionality",
|
|
64
64
|
}),
|
|
@@ -93,18 +93,14 @@ export const realmAuthSettingsAtom = $atom({
|
|
|
93
93
|
default: {
|
|
94
94
|
// for a fresh hello world setup, we accept registration and email login
|
|
95
95
|
registrationAllowed: true,
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
usernameEnabled: false,
|
|
99
|
-
usernameRequired: false,
|
|
96
|
+
email: "required" as FieldRequirement,
|
|
97
|
+
username: "none" as FieldRequirement,
|
|
100
98
|
usernameRegExp: "^[a-zA-Z0-9_]{3,30}$",
|
|
101
|
-
|
|
102
|
-
phoneRequired: false,
|
|
99
|
+
phoneNumber: "none" as FieldRequirement,
|
|
103
100
|
verifyEmailRequired: false,
|
|
104
101
|
verifyPhoneRequired: false,
|
|
105
102
|
resetPasswordAllowed: false,
|
|
106
|
-
|
|
107
|
-
firstNameLastNameRequired: false,
|
|
103
|
+
firstNameLastName: "none" as FieldRequirement,
|
|
108
104
|
adminEmails: [],
|
|
109
105
|
adminUsernames: [],
|
|
110
106
|
// TODO: not implemented yet
|
|
@@ -6,7 +6,7 @@ import { $bucket } from "alepha/bucket";
|
|
|
6
6
|
* This service provides file storage for user-related files such as:
|
|
7
7
|
* - User avatars/profile pictures
|
|
8
8
|
*
|
|
9
|
-
* It is lazy-loaded when the `
|
|
9
|
+
* It is lazy-loaded when the `avatars` feature is enabled in the realm.
|
|
10
10
|
*/
|
|
11
11
|
export class UserBuckets {
|
|
12
12
|
/**
|
|
@@ -13,7 +13,7 @@ import { sessions } from "../entities/sessions.ts";
|
|
|
13
13
|
* - Verification code cleanup
|
|
14
14
|
* - Inactive user notifications
|
|
15
15
|
*
|
|
16
|
-
* It is lazy-loaded when the `
|
|
16
|
+
* It is lazy-loaded when the `sessionPurge` feature is enabled in the realm.
|
|
17
17
|
*/
|
|
18
18
|
export class UserJobs {
|
|
19
19
|
protected readonly log = $logger();
|
|
@@ -57,28 +57,14 @@ export const $realm = (options: RealmOptions = {}): RealmPrimitive => {
|
|
|
57
57
|
|
|
58
58
|
options.settings ??= {};
|
|
59
59
|
|
|
60
|
-
if (options.settings.emailRequired) {
|
|
61
|
-
options.settings.emailEnabled = true;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (options.settings.usernameRequired) {
|
|
65
|
-
options.settings.usernameEnabled = true;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if (options.settings.phoneRequired) {
|
|
69
|
-
options.settings.phoneEnabled = true;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
60
|
// Merge features with defaults
|
|
73
61
|
const features: RealmFeatures = {
|
|
74
|
-
|
|
62
|
+
sessionPurge: false,
|
|
75
63
|
notifications: false,
|
|
76
64
|
apiKeys: false,
|
|
77
|
-
clients: false,
|
|
78
65
|
parameters: false,
|
|
79
|
-
|
|
66
|
+
avatars: false,
|
|
80
67
|
audits: false,
|
|
81
|
-
organizations: false,
|
|
82
68
|
...options.features,
|
|
83
69
|
};
|
|
84
70
|
|
|
@@ -97,7 +83,7 @@ export const $realm = (options: RealmOptions = {}): RealmPrimitive => {
|
|
|
97
83
|
// Enable features based on configuration
|
|
98
84
|
// Each feature registers its wrapper service which internally uses the module primitives
|
|
99
85
|
|
|
100
|
-
if (features.
|
|
86
|
+
if (features.avatars) {
|
|
101
87
|
alepha.with(UserBuckets);
|
|
102
88
|
}
|
|
103
89
|
|
|
@@ -105,7 +91,7 @@ export const $realm = (options: RealmOptions = {}): RealmPrimitive => {
|
|
|
105
91
|
alepha.with(UserAudits);
|
|
106
92
|
}
|
|
107
93
|
|
|
108
|
-
if (features.
|
|
94
|
+
if (features.sessionPurge) {
|
|
109
95
|
alepha.with(UserJobs);
|
|
110
96
|
}
|
|
111
97
|
|
|
@@ -226,11 +212,11 @@ export const $realm = (options: RealmOptions = {}): RealmPrimitive => {
|
|
|
226
212
|
|
|
227
213
|
export interface RealmFeatures {
|
|
228
214
|
/**
|
|
229
|
-
* Enable
|
|
215
|
+
* Enable session purge functionality for cleaning up expired sessions.
|
|
230
216
|
*
|
|
231
217
|
* @default false
|
|
232
218
|
*/
|
|
233
|
-
|
|
219
|
+
sessionPurge?: boolean;
|
|
234
220
|
|
|
235
221
|
/**
|
|
236
222
|
* Enable notification system for password reset, verification emails, etc.
|
|
@@ -256,26 +242,6 @@ export interface RealmFeatures {
|
|
|
256
242
|
*/
|
|
257
243
|
apiKeys?: boolean;
|
|
258
244
|
|
|
259
|
-
/**
|
|
260
|
-
* Enable OAuth2 Authorization Server for third-party client authentication.
|
|
261
|
-
*
|
|
262
|
-
* When enabled, Alepha acts as an OAuth2 Authorization Server, allowing
|
|
263
|
-
* third-party applications to authenticate users via standard OAuth2 flows:
|
|
264
|
-
* - Authorization Code + PKCE (OAuth 2.1)
|
|
265
|
-
* - Client Credentials (machine-to-machine)
|
|
266
|
-
* - Refresh Token
|
|
267
|
-
*
|
|
268
|
-
* Also provides:
|
|
269
|
-
* - Token introspection (RFC 7662)
|
|
270
|
-
* - Token revocation (RFC 7009)
|
|
271
|
-
* - AS metadata (RFC 8414)
|
|
272
|
-
* - Protected Resource metadata (RFC 9728)
|
|
273
|
-
* - MCP-compatible OAuth2 flow
|
|
274
|
-
*
|
|
275
|
-
* @default false
|
|
276
|
-
*/
|
|
277
|
-
clients?: boolean;
|
|
278
|
-
|
|
279
245
|
/**
|
|
280
246
|
* Enable runtime configuration management.
|
|
281
247
|
*
|
|
@@ -286,11 +252,11 @@ export interface RealmFeatures {
|
|
|
286
252
|
parameters?: boolean;
|
|
287
253
|
|
|
288
254
|
/**
|
|
289
|
-
* Enable
|
|
255
|
+
* Enable avatar uploads for user profiles.
|
|
290
256
|
*
|
|
291
257
|
* @default false
|
|
292
258
|
*/
|
|
293
|
-
|
|
259
|
+
avatars?: boolean;
|
|
294
260
|
|
|
295
261
|
/**
|
|
296
262
|
* Enable audit trail for compliance and event logging.
|
|
@@ -298,13 +264,6 @@ export interface RealmFeatures {
|
|
|
298
264
|
* @default false
|
|
299
265
|
*/
|
|
300
266
|
audits?: boolean;
|
|
301
|
-
|
|
302
|
-
/**
|
|
303
|
-
* Enable organization management to group users.
|
|
304
|
-
*
|
|
305
|
-
* @default false
|
|
306
|
-
*/
|
|
307
|
-
organizations?: boolean;
|
|
308
267
|
}
|
|
309
268
|
|
|
310
269
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
@@ -34,13 +34,12 @@ export class RealmProvider {
|
|
|
34
34
|
public register(realmName: string, realmOptions: RealmOptions = {}) {
|
|
35
35
|
// Merge features with defaults
|
|
36
36
|
const features: RealmFeatures = {
|
|
37
|
-
|
|
37
|
+
sessionPurge: false,
|
|
38
38
|
notifications: false,
|
|
39
39
|
apiKeys: false,
|
|
40
40
|
parameters: false,
|
|
41
|
-
|
|
41
|
+
avatars: false,
|
|
42
42
|
audits: false,
|
|
43
|
-
organizations: false,
|
|
44
43
|
...realmOptions.features,
|
|
45
44
|
};
|
|
46
45
|
|
|
@@ -146,7 +146,7 @@ describe("alepha/api/users - RegistrationService", () => {
|
|
|
146
146
|
|
|
147
147
|
realmProvider.register("username-required-realm", {
|
|
148
148
|
settings: {
|
|
149
|
-
|
|
149
|
+
username: "required",
|
|
150
150
|
} as never,
|
|
151
151
|
});
|
|
152
152
|
|
|
@@ -180,8 +180,8 @@ describe("alepha/api/users - RegistrationService", () => {
|
|
|
180
180
|
|
|
181
181
|
realmProvider.register("phone-required-realm", {
|
|
182
182
|
settings: {
|
|
183
|
-
|
|
184
|
-
|
|
183
|
+
phoneNumber: "required",
|
|
184
|
+
email: "optional",
|
|
185
185
|
} as never,
|
|
186
186
|
});
|
|
187
187
|
|
|
@@ -240,8 +240,8 @@ describe("alepha/api/users - RegistrationService", () => {
|
|
|
240
240
|
|
|
241
241
|
realmProvider.register("phone-realm", {
|
|
242
242
|
settings: {
|
|
243
|
-
|
|
244
|
-
|
|
243
|
+
phoneNumber: "optional",
|
|
244
|
+
email: "optional",
|
|
245
245
|
} as never,
|
|
246
246
|
});
|
|
247
247
|
|
|
@@ -530,7 +530,7 @@ describe("alepha/api/users - RegistrationService", () => {
|
|
|
530
530
|
expect,
|
|
531
531
|
}) => {
|
|
532
532
|
const { registrationService, sessionService } = await setup({
|
|
533
|
-
|
|
533
|
+
username: "optional",
|
|
534
534
|
});
|
|
535
535
|
|
|
536
536
|
const intent = await registrationService.createRegistrationIntent({
|
|
@@ -559,7 +559,7 @@ describe("alepha/api/users - RegistrationService", () => {
|
|
|
559
559
|
expect,
|
|
560
560
|
}) => {
|
|
561
561
|
const { registrationService, sessionService } = await setup({
|
|
562
|
-
|
|
562
|
+
username: "optional",
|
|
563
563
|
});
|
|
564
564
|
|
|
565
565
|
// Phase 1: Create intent
|
|
@@ -97,7 +97,7 @@ export class RegistrationService {
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
// Validate required fields based on settings
|
|
100
|
-
if (realmSettings?.
|
|
100
|
+
if (realmSettings?.username === "required" && !body.username) {
|
|
101
101
|
this.log.debug("Registration rejected: username required", {
|
|
102
102
|
userRealmName,
|
|
103
103
|
});
|
|
@@ -120,14 +120,14 @@ export class RegistrationService {
|
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
if (realmSettings?.
|
|
123
|
+
if (realmSettings?.email === "required" && !body.email) {
|
|
124
124
|
this.log.debug("Registration rejected: email required", {
|
|
125
125
|
userRealmName,
|
|
126
126
|
});
|
|
127
127
|
throw new BadRequestError("Email is required");
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
if (realmSettings?.
|
|
130
|
+
if (realmSettings?.phoneNumber === "required" && !body.phoneNumber) {
|
|
131
131
|
this.log.debug("Registration rejected: phone required", {
|
|
132
132
|
userRealmName,
|
|
133
133
|
});
|