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
|
@@ -13,10 +13,12 @@ export * from "./primitives/$repository.ts";
|
|
|
13
13
|
export * from "./primitives/$seed.ts";
|
|
14
14
|
export * from "./primitives/$sequence.ts";
|
|
15
15
|
export * from "./primitives/$transactional.ts";
|
|
16
|
+
export * from "./providers/DbCacheProvider.ts";
|
|
16
17
|
export * from "./providers/DrizzleKitProvider.ts";
|
|
17
18
|
export * from "./providers/drivers/CloudflareD1Provider.ts";
|
|
18
19
|
export * from "./providers/drivers/DatabaseProvider.ts";
|
|
19
20
|
export * from "./providers/RepositoryProvider.ts";
|
|
21
|
+
export * from "./schemas/databaseEnvSchema.ts";
|
|
20
22
|
export * from "./schemas/insertSchema.ts";
|
|
21
23
|
export * from "./schemas/updateSchema.ts";
|
|
22
24
|
export * from "./services/ModelBuilder.ts";
|
|
@@ -13,9 +13,11 @@ export * from "./errors/DbNotNullError.ts";
|
|
|
13
13
|
export * from "./errors/DbTableNotFoundError.ts";
|
|
14
14
|
export * from "./helpers/parseQueryString.ts";
|
|
15
15
|
export * from "./helpers/pgAttr.ts";
|
|
16
|
+
export * from "./interfaces/AggregateQuery.ts";
|
|
16
17
|
export * from "./interfaces/FilterOperators.ts";
|
|
17
18
|
export * from "./interfaces/PgQuery.ts";
|
|
18
19
|
export * from "./interfaces/PgQueryWhere.ts";
|
|
19
20
|
export * from "./primitives/$entity.ts";
|
|
21
|
+
export * from "./primitives/$view.ts";
|
|
20
22
|
export * from "./providers/DatabaseTypeProvider.ts";
|
|
21
23
|
export * from "./schemas/legacyIdSchema.ts";
|
package/src/orm/core/index.ts
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import { $module, type Alepha
|
|
1
|
+
import { $module, type Alepha } from "alepha";
|
|
2
2
|
import { AlephaDateTime } from "alepha/datetime";
|
|
3
3
|
import type { PgTransaction } from "drizzle-orm/pg-core";
|
|
4
4
|
import { DbMigrationMode } from "./modes/DbMigrationMode.ts";
|
|
5
5
|
import { $entity } from "./primitives/$entity.ts";
|
|
6
6
|
import { $sequence } from "./primitives/$sequence.ts";
|
|
7
|
+
import { $view } from "./primitives/$view.ts";
|
|
7
8
|
import { DrizzleKitProvider } from "./providers/DrizzleKitProvider.ts";
|
|
8
9
|
import { BunSqliteProvider } from "./providers/drivers/BunSqliteProvider.ts";
|
|
9
10
|
import { CloudflareD1Provider } from "./providers/drivers/CloudflareD1Provider.ts";
|
|
10
11
|
import { DatabaseProvider } from "./providers/drivers/DatabaseProvider.ts";
|
|
11
12
|
import { NodeSqliteProvider } from "./providers/drivers/NodeSqliteProvider.ts";
|
|
12
13
|
import { RepositoryProvider } from "./providers/RepositoryProvider.ts";
|
|
14
|
+
import { databaseEnvSchema } from "./schemas/databaseEnvSchema.ts";
|
|
13
15
|
import { PgRelationManager } from "./services/PgRelationManager.ts";
|
|
14
16
|
import { QueryManager } from "./services/QueryManager.ts";
|
|
15
17
|
import { Repository } from "./services/Repository.ts";
|
|
@@ -100,7 +102,7 @@ export const SqliteProvider = NodeSqliteProvider;
|
|
|
100
102
|
|
|
101
103
|
export const AlephaOrm = $module({
|
|
102
104
|
name: "alepha.orm",
|
|
103
|
-
primitives: [$sequence, $entity],
|
|
105
|
+
primitives: [$sequence, $entity, $view],
|
|
104
106
|
services: [
|
|
105
107
|
AlephaDateTime,
|
|
106
108
|
DatabaseProvider,
|
|
@@ -116,11 +118,7 @@ export const AlephaOrm = $module({
|
|
|
116
118
|
DbMigrationMode,
|
|
117
119
|
],
|
|
118
120
|
register: (alepha: Alepha) => {
|
|
119
|
-
const env = alepha.parseEnv(
|
|
120
|
-
t.object({
|
|
121
|
-
DATABASE_URL: t.optional(t.text()),
|
|
122
|
-
}),
|
|
123
|
-
);
|
|
121
|
+
const env = alepha.parseEnv(databaseEnvSchema);
|
|
124
122
|
|
|
125
123
|
const url = env.DATABASE_URL;
|
|
126
124
|
const isBun = alepha.isBun();
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { Static, TObject } from "alepha";
|
|
2
|
+
import type { PgQueryWhereOrSQL } from "./PgQueryWhere.ts";
|
|
3
|
+
|
|
4
|
+
export type AggregateOp = "count" | "sum" | "avg" | "min" | "max";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Select definition for aggregate queries.
|
|
8
|
+
* - `true` means select the column value as-is (used for groupBy columns).
|
|
9
|
+
* - `{ sum: true, avg: true, ... }` means compute those aggregations.
|
|
10
|
+
*/
|
|
11
|
+
export type AggregateColumnSelect = true | Partial<Record<AggregateOp, true>>;
|
|
12
|
+
|
|
13
|
+
export type AggregateSelect<T extends TObject> = {
|
|
14
|
+
[K in keyof Static<T>]?: AggregateColumnSelect;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Maps a single column's select definition to its result type.
|
|
19
|
+
* - `true` → original column type
|
|
20
|
+
* - `{ sum: true, avg: true }` → `{ sum: number; avg: number }`
|
|
21
|
+
*/
|
|
22
|
+
export type AggregateColumnResult<TValue, TSelect> = TSelect extends true
|
|
23
|
+
? TValue
|
|
24
|
+
: {
|
|
25
|
+
[Op in AggregateOp as TSelect extends Record<Op, true>
|
|
26
|
+
? Op
|
|
27
|
+
: never]: number;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Result type for an aggregate query.
|
|
32
|
+
*/
|
|
33
|
+
export type AggregateResult<T extends TObject, S extends AggregateSelect<T>> = {
|
|
34
|
+
[K in keyof S & keyof Static<T>]: AggregateColumnResult<
|
|
35
|
+
Static<T>[K],
|
|
36
|
+
NonNullable<S[K]>
|
|
37
|
+
>;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* HAVING clause for aggregate queries.
|
|
42
|
+
* Only applies to columns with aggregate operations (not `true`).
|
|
43
|
+
*/
|
|
44
|
+
export type AggregateHaving<T extends TObject, S extends AggregateSelect<T>> = {
|
|
45
|
+
[K in keyof S & keyof Static<T>]?: S[K] extends true
|
|
46
|
+
? never
|
|
47
|
+
: {
|
|
48
|
+
[Op in AggregateOp as S[K] extends Record<Op, true> ? Op : never]?: {
|
|
49
|
+
gt?: number;
|
|
50
|
+
gte?: number;
|
|
51
|
+
lt?: number;
|
|
52
|
+
lte?: number;
|
|
53
|
+
eq?: number;
|
|
54
|
+
ne?: number;
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Full aggregate query definition.
|
|
61
|
+
*/
|
|
62
|
+
export interface AggregateQuery<
|
|
63
|
+
T extends TObject,
|
|
64
|
+
S extends AggregateSelect<T>,
|
|
65
|
+
> {
|
|
66
|
+
/**
|
|
67
|
+
* Columns and aggregate operations to select.
|
|
68
|
+
*/
|
|
69
|
+
select: S;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* WHERE clause to filter rows before aggregation.
|
|
73
|
+
*/
|
|
74
|
+
where?: PgQueryWhereOrSQL<T>;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Columns to group by.
|
|
78
|
+
*/
|
|
79
|
+
groupBy?: (keyof Static<T>)[];
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* HAVING clause to filter groups after aggregation.
|
|
83
|
+
*/
|
|
84
|
+
having?: AggregateHaving<T, S>;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Order results. Supports dot notation for aggregate columns (e.g. "amount.sum").
|
|
88
|
+
*/
|
|
89
|
+
orderBy?:
|
|
90
|
+
| string
|
|
91
|
+
| { column: string; direction: "asc" | "desc" }
|
|
92
|
+
| Array<{ column: string; direction: "asc" | "desc" }>;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Limit the number of results.
|
|
96
|
+
*/
|
|
97
|
+
limit?: number;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Offset for pagination.
|
|
101
|
+
*/
|
|
102
|
+
offset?: number;
|
|
103
|
+
}
|
|
@@ -97,6 +97,13 @@ type PgQueryWhereConditions<
|
|
|
97
97
|
* @see notExists for the inverse of this test
|
|
98
98
|
*/
|
|
99
99
|
exists?: SQLWrapper;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Test whether a subquery evaluates to have no rows.
|
|
103
|
+
*
|
|
104
|
+
* @see exists for the inverse of this test
|
|
105
|
+
*/
|
|
106
|
+
notExists?: SQLWrapper;
|
|
100
107
|
};
|
|
101
108
|
|
|
102
109
|
type PgQueryWhereRelations<
|
|
@@ -67,6 +67,10 @@ export interface EntityPrimitiveOptions<
|
|
|
67
67
|
* Custom name for the index. If not provided, generates name automatically.
|
|
68
68
|
*/
|
|
69
69
|
name?: string;
|
|
70
|
+
/**
|
|
71
|
+
* Partial index condition. Only rows matching this SQL expression are indexed.
|
|
72
|
+
*/
|
|
73
|
+
where?: SQL;
|
|
70
74
|
}
|
|
71
75
|
| {
|
|
72
76
|
/**
|
|
@@ -81,6 +85,10 @@ export interface EntityPrimitiveOptions<
|
|
|
81
85
|
* Custom name for the index. If not provided, generates name automatically.
|
|
82
86
|
*/
|
|
83
87
|
name?: string;
|
|
88
|
+
/**
|
|
89
|
+
* Partial index condition. Only rows matching this SQL expression are indexed.
|
|
90
|
+
*/
|
|
91
|
+
where?: SQL;
|
|
84
92
|
}
|
|
85
93
|
)[];
|
|
86
94
|
|
|
@@ -2,14 +2,17 @@ import { $context, $inject, type TObject } from "alepha";
|
|
|
2
2
|
import { RepositoryProvider } from "../providers/RepositoryProvider.ts";
|
|
3
3
|
import type { Repository } from "../services/Repository.ts";
|
|
4
4
|
import type { EntityPrimitive } from "./$entity.ts";
|
|
5
|
+
import type { ViewPrimitive } from "./$view.ts";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
|
-
* Get the repository for the given entity.
|
|
8
|
+
* Get the repository for the given entity or view.
|
|
8
9
|
*/
|
|
9
10
|
export const $repository = <T extends TObject>(
|
|
10
|
-
entity: EntityPrimitive<T>,
|
|
11
|
+
entity: EntityPrimitive<T> | ViewPrimitive<T>,
|
|
11
12
|
): Repository<T> => {
|
|
12
13
|
const { alepha } = $context();
|
|
13
14
|
const repositoryProvider = alepha.inject(RepositoryProvider);
|
|
14
|
-
return $inject(
|
|
15
|
+
return $inject(
|
|
16
|
+
repositoryProvider.createClassRepository(entity as EntityPrimitive<T>),
|
|
17
|
+
);
|
|
15
18
|
};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { KIND, type TObject } from "alepha";
|
|
2
|
+
import type { SQL } from "drizzle-orm";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Creates a database view primitive from a TypeBox schema and SQL query.
|
|
6
|
+
*
|
|
7
|
+
* Views are read-only: Repository blocks all write operations.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { t } from "alepha";
|
|
12
|
+
* import { $view } from "alepha/orm";
|
|
13
|
+
* import { sql } from "drizzle-orm";
|
|
14
|
+
*
|
|
15
|
+
* const userSummary = $view({
|
|
16
|
+
* name: "user_summary",
|
|
17
|
+
* schema: t.object({
|
|
18
|
+
* id: t.uuid(),
|
|
19
|
+
* fullName: t.text(),
|
|
20
|
+
* orderCount: t.integer(),
|
|
21
|
+
* }),
|
|
22
|
+
* query: sql`SELECT u.id, u.first_name || ' ' || u.last_name AS full_name, COUNT(o.id) AS order_count FROM users u LEFT JOIN orders o ON o.user_id = u.id GROUP BY u.id`,
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* // Materialized view (PostgreSQL only)
|
|
26
|
+
* const monthlyStats = $view({
|
|
27
|
+
* name: "monthly_stats",
|
|
28
|
+
* schema: t.object({ ... }),
|
|
29
|
+
* query: sql`...`,
|
|
30
|
+
* materialized: true,
|
|
31
|
+
* });
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export const $view = <TSchema extends TObject>(
|
|
35
|
+
options: ViewPrimitiveOptions<TSchema>,
|
|
36
|
+
): ViewPrimitive<TSchema> => {
|
|
37
|
+
return new ViewPrimitive<TSchema>(options);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
41
|
+
|
|
42
|
+
export interface ViewPrimitiveOptions<T extends TObject> {
|
|
43
|
+
/**
|
|
44
|
+
* The database view name.
|
|
45
|
+
*/
|
|
46
|
+
name: string;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* TypeBox schema defining the view's columns.
|
|
50
|
+
*/
|
|
51
|
+
schema: T;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* SQL query that defines the view.
|
|
55
|
+
*/
|
|
56
|
+
query: SQL;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Whether this is a materialized view (PostgreSQL only).
|
|
60
|
+
* Materialized views store results on disk and can be refreshed.
|
|
61
|
+
*/
|
|
62
|
+
materialized?: boolean;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
66
|
+
|
|
67
|
+
export class ViewPrimitive<T extends TObject = TObject> {
|
|
68
|
+
public readonly options: ViewPrimitiveOptions<T>;
|
|
69
|
+
public readonly isView = true;
|
|
70
|
+
|
|
71
|
+
constructor(options: ViewPrimitiveOptions<T>) {
|
|
72
|
+
this.options = options;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
get name(): string {
|
|
76
|
+
return this.options.name;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
get schema(): T {
|
|
80
|
+
return this.options.schema;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
get materialized(): boolean {
|
|
84
|
+
return this.options.materialized ?? false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
$view[KIND] = ViewPrimitive;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database query cache using a simple in-memory Map.
|
|
3
|
+
*
|
|
4
|
+
* Uses `{tableName}:{cacheKey}` as the storage key.
|
|
5
|
+
* Provides per-table invalidation for write-through cache busting.
|
|
6
|
+
*
|
|
7
|
+
* This is intentionally self-contained (no external cache dependencies)
|
|
8
|
+
* so the ORM module does not force `AlephaCache` on all consumers.
|
|
9
|
+
*/
|
|
10
|
+
export class DbCacheProvider {
|
|
11
|
+
protected readonly store = new Map<
|
|
12
|
+
string,
|
|
13
|
+
{ value: unknown; expiresAt?: number }
|
|
14
|
+
>();
|
|
15
|
+
|
|
16
|
+
protected storeKey(tableName: string, cacheKey: string): string {
|
|
17
|
+
return `${tableName}:${cacheKey}`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Get a cached query result.
|
|
22
|
+
*/
|
|
23
|
+
public async get<T>(
|
|
24
|
+
tableName: string,
|
|
25
|
+
cacheKey: string,
|
|
26
|
+
): Promise<T | undefined> {
|
|
27
|
+
const key = this.storeKey(tableName, cacheKey);
|
|
28
|
+
const entry = this.store.get(key);
|
|
29
|
+
|
|
30
|
+
if (!entry) return undefined;
|
|
31
|
+
if (entry.expiresAt && Date.now() > entry.expiresAt) {
|
|
32
|
+
this.store.delete(key);
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return entry.value as T;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Store a query result in the cache.
|
|
41
|
+
*/
|
|
42
|
+
public async set<T>(
|
|
43
|
+
tableName: string,
|
|
44
|
+
cacheKey: string,
|
|
45
|
+
value: T,
|
|
46
|
+
ttl?: number,
|
|
47
|
+
): Promise<void> {
|
|
48
|
+
const key = this.storeKey(tableName, cacheKey);
|
|
49
|
+
this.store.set(key, {
|
|
50
|
+
value,
|
|
51
|
+
expiresAt: ttl ? Date.now() + ttl : undefined,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Invalidate all cached queries for a table.
|
|
57
|
+
*/
|
|
58
|
+
public async invalidateTable(tableName: string): Promise<void> {
|
|
59
|
+
const prefix = `${tableName}:`;
|
|
60
|
+
for (const key of this.store.keys()) {
|
|
61
|
+
if (key.startsWith(prefix)) {
|
|
62
|
+
this.store.delete(key);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -203,6 +203,48 @@ export class DrizzleKitProvider {
|
|
|
203
203
|
return models;
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
+
/**
|
|
207
|
+
* Preview schema push without executing any statements.
|
|
208
|
+
*
|
|
209
|
+
* Returns the SQL statements that would be executed, warnings, and
|
|
210
|
+
* whether data loss would occur. Does NOT execute any SQL.
|
|
211
|
+
*/
|
|
212
|
+
public async dryRunPush(provider: DatabaseProvider): Promise<{
|
|
213
|
+
statements: string[];
|
|
214
|
+
warnings: string[];
|
|
215
|
+
hasDataLoss: boolean;
|
|
216
|
+
}> {
|
|
217
|
+
const kit = this.importDrizzleKit();
|
|
218
|
+
const models = this.getModels(provider);
|
|
219
|
+
|
|
220
|
+
if (Object.keys(models).length === 0) {
|
|
221
|
+
return { statements: [], warnings: [], hasDataLoss: false };
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
let result: {
|
|
225
|
+
statementsToExecute: string[];
|
|
226
|
+
warnings: string[];
|
|
227
|
+
hasDataLoss: boolean;
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
if (provider.dialect === "sqlite") {
|
|
231
|
+
result = await this.muteSpinner(() =>
|
|
232
|
+
kit.pushSQLiteSchema(models, provider.db as any),
|
|
233
|
+
);
|
|
234
|
+
} else {
|
|
235
|
+
const wrappedDb = this.wrapDbForDrizzleKit(provider.db);
|
|
236
|
+
result = await this.muteSpinner(() =>
|
|
237
|
+
kit.pushSchema(models, wrappedDb, [provider.schema]),
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return {
|
|
242
|
+
statements: result.statementsToExecute,
|
|
243
|
+
warnings: result.warnings,
|
|
244
|
+
hasDataLoss: result.hasDataLoss,
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
206
248
|
// -------------------------------------------------------------------------------------------------------------------
|
|
207
249
|
|
|
208
250
|
protected async pushSqlite(
|
|
@@ -13,14 +13,13 @@ import {
|
|
|
13
13
|
} from "alepha";
|
|
14
14
|
import type { BunSQLiteDatabase } from "drizzle-orm/bun-sqlite";
|
|
15
15
|
import type { PgDatabase } from "drizzle-orm/pg-core";
|
|
16
|
+
import { databaseEnvSchema } from "../../schemas/databaseEnvSchema.ts";
|
|
16
17
|
import { SqliteModelBuilder } from "../../services/SqliteModelBuilder.ts";
|
|
17
18
|
import { DatabaseProvider, type SQLLike } from "./DatabaseProvider.ts";
|
|
18
19
|
|
|
19
20
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
20
21
|
|
|
21
|
-
const envSchema =
|
|
22
|
-
DATABASE_URL: t.optional(t.text()),
|
|
23
|
-
});
|
|
22
|
+
const envSchema = databaseEnvSchema;
|
|
24
23
|
|
|
25
24
|
/**
|
|
26
25
|
* Configuration options for the Bun SQLite database provider.
|
|
@@ -88,6 +88,18 @@ export class CloudflareD1Provider extends DatabaseProvider {
|
|
|
88
88
|
return rows;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
/**
|
|
92
|
+
* D1 does not support SQL-level transactions (BEGIN/COMMIT/ROLLBACK).
|
|
93
|
+
* It rejects these statements and requires the JS `batch()` API for atomic
|
|
94
|
+
* multi-statement operations instead.
|
|
95
|
+
*
|
|
96
|
+
* @see https://developers.cloudflare.com/d1/worker-api/d1-database/#batch-statements
|
|
97
|
+
* @see https://github.com/drizzle-team/drizzle-orm/issues/2463
|
|
98
|
+
*/
|
|
99
|
+
public override get supportsTransactions(): boolean {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
|
|
91
103
|
protected readonly onStart = $hook({
|
|
92
104
|
on: "start",
|
|
93
105
|
handler: async () => {
|
|
@@ -21,6 +21,8 @@ import type {
|
|
|
21
21
|
SchemaToTableConfig,
|
|
22
22
|
} from "../../primitives/$entity.ts";
|
|
23
23
|
import type { SequencePrimitive } from "../../primitives/$sequence.ts";
|
|
24
|
+
import type { ViewPrimitive } from "../../primitives/$view.ts";
|
|
25
|
+
import { databaseEnvSchema } from "../../schemas/databaseEnvSchema.ts";
|
|
24
26
|
import type { ModelBuilder } from "../../services/ModelBuilder.ts";
|
|
25
27
|
import { DrizzleKitProvider } from "../DrizzleKitProvider.ts";
|
|
26
28
|
|
|
@@ -51,6 +53,15 @@ export abstract class DatabaseProvider {
|
|
|
51
53
|
return this.dialect;
|
|
52
54
|
}
|
|
53
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Whether this driver supports SQL-level transactions (BEGIN/COMMIT/ROLLBACK).
|
|
58
|
+
*
|
|
59
|
+
* Drivers that do not (e.g. PGlite, Cloudflare D1) should override to `false`.
|
|
60
|
+
*/
|
|
61
|
+
public get supportsTransactions(): boolean {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
|
|
54
65
|
/**
|
|
55
66
|
* Raw database connection handle (e.g. DatabaseSync, bun:sqlite Database).
|
|
56
67
|
* Override in providers that expose native connections for introspection.
|
|
@@ -143,6 +154,10 @@ export abstract class DatabaseProvider {
|
|
|
143
154
|
this.builder.buildTable(entity, this);
|
|
144
155
|
}
|
|
145
156
|
|
|
157
|
+
public registerView(view: ViewPrimitive) {
|
|
158
|
+
this.builder.buildView(view, this);
|
|
159
|
+
}
|
|
160
|
+
|
|
146
161
|
public registerSequence(sequence: SequencePrimitive) {
|
|
147
162
|
this.sequencePrimitives.push(sequence);
|
|
148
163
|
this.builder.buildSequence(sequence, this);
|
|
@@ -197,6 +212,10 @@ export abstract class DatabaseProvider {
|
|
|
197
212
|
return fn();
|
|
198
213
|
}
|
|
199
214
|
|
|
215
|
+
if (!this.supportsTransactions) {
|
|
216
|
+
return fn();
|
|
217
|
+
}
|
|
218
|
+
|
|
200
219
|
return this.db.transaction(async (tx) => {
|
|
201
220
|
this.alepha.store.set("alepha.orm.tx", tx as PgTransaction<any>, {
|
|
202
221
|
skipEvents: true,
|
|
@@ -218,6 +237,18 @@ export abstract class DatabaseProvider {
|
|
|
218
237
|
schema: T,
|
|
219
238
|
): Promise<Array<Static<T>>> {
|
|
220
239
|
const result = await this.execute(statement);
|
|
240
|
+
|
|
241
|
+
if (result == null) {
|
|
242
|
+
return [];
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (!Array.isArray(result)) {
|
|
246
|
+
this.log.error("Unexpected query result format", { result });
|
|
247
|
+
throw new DbError(
|
|
248
|
+
"Unexpected query result format, expected array of rows",
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
|
|
221
252
|
return result.map((row) => this.alepha.codec.decode(schema, row));
|
|
222
253
|
}
|
|
223
254
|
|
|
@@ -263,6 +294,14 @@ export abstract class DatabaseProvider {
|
|
|
263
294
|
await this.executeMigrations(migrationsFolder);
|
|
264
295
|
this.log.info("Migration OK");
|
|
265
296
|
} else {
|
|
297
|
+
const { DATABASE_SYNC } = this.alepha.parseEnv(databaseEnvSchema);
|
|
298
|
+
if (DATABASE_SYNC === false) {
|
|
299
|
+
this.log.info(
|
|
300
|
+
"Database synchronization disabled (DATABASE_SYNC=false)",
|
|
301
|
+
);
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
|
|
266
305
|
try {
|
|
267
306
|
await this.kit.synchronize(this);
|
|
268
307
|
} catch (error) {
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
t,
|
|
14
14
|
} from "alepha";
|
|
15
15
|
import type { PgDatabase } from "drizzle-orm/pg-core";
|
|
16
|
+
import { databaseEnvSchema } from "../../schemas/databaseEnvSchema.ts";
|
|
16
17
|
import { SqliteModelBuilder } from "../../services/SqliteModelBuilder.ts";
|
|
17
18
|
import { DatabaseProvider, type SQLLike } from "./DatabaseProvider.ts";
|
|
18
19
|
|
|
@@ -39,9 +40,7 @@ import { DatabaseProvider, type SQLLike } from "./DatabaseProvider.ts";
|
|
|
39
40
|
|
|
40
41
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
41
42
|
|
|
42
|
-
const envSchema =
|
|
43
|
-
DATABASE_URL: t.optional(t.text()),
|
|
44
|
-
});
|
|
43
|
+
const envSchema = databaseEnvSchema;
|
|
45
44
|
|
|
46
45
|
/**
|
|
47
46
|
* Configuration options for the Node.js SQLite database provider.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type Static, t } from "alepha";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Base database environment schema.
|
|
5
|
+
*
|
|
6
|
+
* Defines the `DATABASE_URL` connection string used by all ORM providers
|
|
7
|
+
* to determine the database driver and connection target.
|
|
8
|
+
*
|
|
9
|
+
* Supported URL formats:
|
|
10
|
+
* - `sqlite://:memory:` or `sqlite://./path/to/db` — SQLite (Node.js or Bun)
|
|
11
|
+
* - `postgres://user:password@host:port/database` — PostgreSQL (Node.js or Bun)
|
|
12
|
+
* - `pglite://:memory:` or `pglite://./path` — PGlite (embedded Postgres)
|
|
13
|
+
* - `d1://BINDING_NAME` — Cloudflare D1
|
|
14
|
+
* - `hyperdrive://BINDING_NAME` — Cloudflare Hyperdrive
|
|
15
|
+
*/
|
|
16
|
+
export const databaseEnvSchema = t.object({
|
|
17
|
+
DATABASE_URL: t.optional(t.text()),
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Enable or disable push-based schema synchronization (drizzle-kit push).
|
|
21
|
+
*
|
|
22
|
+
* Defaults to `true` in development and test, `false` in production.
|
|
23
|
+
* Set to `false` in development to skip automatic schema sync
|
|
24
|
+
* (e.g. when managing migrations manually).
|
|
25
|
+
*/
|
|
26
|
+
DATABASE_SYNC: t.optional(t.boolean()),
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
declare module "alepha" {
|
|
30
|
+
interface Env extends Partial<Static<typeof databaseEnvSchema>> {}
|
|
31
|
+
}
|
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
import type { TObject, TOptional } from "alepha";
|
|
2
2
|
import { t } from "alepha";
|
|
3
|
-
import { PG_DEFAULT } from "../constants/PG_SYMBOLS.ts";
|
|
3
|
+
import { PG_DEFAULT, PG_GENERATED } from "../constants/PG_SYMBOLS.ts";
|
|
4
4
|
import { schema } from "../types/schema.ts";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Transforms a TObject schema for insert operations.
|
|
8
8
|
* All default properties at the root level are made optional.
|
|
9
|
+
* Generated columns are excluded entirely.
|
|
9
10
|
*
|
|
10
11
|
* @example
|
|
11
|
-
* Before: { name: string; age: number(default=0); }
|
|
12
|
+
* Before: { name: string; age: number(default=0); fullName: generated }
|
|
12
13
|
* After: { name: string; age?: number; }
|
|
13
14
|
*/
|
|
14
15
|
export type TObjectInsert<T extends TObject> = TObject<{
|
|
15
|
-
[K in keyof T["properties"]
|
|
16
|
+
[K in keyof T["properties"] as T["properties"][K] extends {
|
|
17
|
+
[PG_GENERATED]: any;
|
|
18
|
+
}
|
|
19
|
+
? never
|
|
20
|
+
: K]: T["properties"][K] extends
|
|
16
21
|
| { [PG_DEFAULT]: any }
|
|
17
22
|
| { "~optional": true }
|
|
18
23
|
? TOptional<T["properties"][K]>
|
|
@@ -25,6 +30,11 @@ export const insertSchema = <T extends TObject>(obj: T): TObjectInsert<T> => {
|
|
|
25
30
|
for (const key in obj.properties) {
|
|
26
31
|
const prop = obj.properties[key];
|
|
27
32
|
|
|
33
|
+
// Skip generated columns — they are computed by the database
|
|
34
|
+
if (PG_GENERATED in prop) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
|
|
28
38
|
if (PG_DEFAULT in prop) {
|
|
29
39
|
newProperties[key] = t.optional(prop);
|
|
30
40
|
} else {
|
|
@@ -5,18 +5,23 @@ import {
|
|
|
5
5
|
type TUnion,
|
|
6
6
|
t,
|
|
7
7
|
} from "alepha";
|
|
8
|
+
import { PG_GENERATED } from "../constants/PG_SYMBOLS.ts";
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Transforms a TObject schema for update operations.
|
|
11
12
|
* All optional properties at the root level are made nullable (i.e., `T | null`).
|
|
12
|
-
*
|
|
13
|
+
* Generated columns are excluded entirely.
|
|
13
14
|
*
|
|
14
15
|
* @example
|
|
15
|
-
* Before: { name?: string; age: number; }
|
|
16
|
+
* Before: { name?: string; age: number; fullName: generated }
|
|
16
17
|
* After: { name?: string | null; age: number; }
|
|
17
18
|
*/
|
|
18
19
|
export type TObjectUpdate<T extends TObject> = TObject<{
|
|
19
|
-
[K in keyof T["properties"]
|
|
20
|
+
[K in keyof T["properties"] as T["properties"][K] extends {
|
|
21
|
+
[PG_GENERATED]: any;
|
|
22
|
+
}
|
|
23
|
+
? never
|
|
24
|
+
: K]: T["properties"][K] extends TOptional<infer U>
|
|
20
25
|
? TOptional<TUnion<[U, TNull]>>
|
|
21
26
|
: T["properties"][K];
|
|
22
27
|
}>;
|
|
@@ -28,6 +33,12 @@ export const updateSchema = <T extends TObject>(
|
|
|
28
33
|
|
|
29
34
|
for (const key in schema.properties) {
|
|
30
35
|
const prop = schema.properties[key];
|
|
36
|
+
|
|
37
|
+
// Skip generated columns — they are computed by the database
|
|
38
|
+
if (PG_GENERATED in prop) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
|
|
31
42
|
if (t.schema.isOptional(prop)) {
|
|
32
43
|
newProperties[key] = t.optional(t.union([prop, t.raw.Null()]));
|
|
33
44
|
} else {
|