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
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
import { $module } from "alepha";
|
|
2
|
-
import {
|
|
3
|
-
AlephaCli,
|
|
4
|
-
type AlephaCliConfig,
|
|
5
|
-
registerConfigProcessor,
|
|
6
|
-
} from "alepha/cli";
|
|
2
|
+
import { AlephaCli } from "alepha/cli";
|
|
7
3
|
import { CloudflareAdapter } from "./adapters/CloudflareAdapter.ts";
|
|
8
4
|
import { DockerAdapter } from "./adapters/DockerAdapter.ts";
|
|
9
5
|
import { VercelAdapter } from "./adapters/VercelAdapter.ts";
|
|
10
|
-
import {
|
|
11
|
-
type PlatformOptions,
|
|
12
|
-
platformOptions,
|
|
13
|
-
} from "./atoms/platformOptions.ts";
|
|
14
6
|
import { PlatformCommand } from "./commands/platform.ts";
|
|
7
|
+
import { SecretsCommand } from "./commands/SecretsCommand.ts";
|
|
8
|
+
import { GitHubSecretStore } from "./providers/GitHubSecretStore.ts";
|
|
9
|
+
import { MemorySecretStore } from "./providers/MemorySecretStore.ts";
|
|
15
10
|
import { PlatformCacheProvider } from "./providers/PlatformCacheProvider.ts";
|
|
16
11
|
import { CloudflareApi } from "./services/CloudflareApi.ts";
|
|
17
12
|
import { DockerComposeGenerator } from "./services/DockerComposeGenerator.ts";
|
|
@@ -19,29 +14,11 @@ import { DockerSshService } from "./services/DockerSshService.ts";
|
|
|
19
14
|
import { NamingService } from "./services/NamingService.ts";
|
|
20
15
|
import { PlatformInspector } from "./services/PlatformInspector.ts";
|
|
21
16
|
import { PlatformOrchestrator } from "./services/PlatformOrchestrator.ts";
|
|
17
|
+
import { SecretFilterService } from "./services/SecretFilterService.ts";
|
|
22
18
|
import { VercelApi } from "./services/VercelApi.ts";
|
|
23
19
|
import { VercelCli } from "./services/VercelCli.ts";
|
|
24
20
|
import { WranglerApi } from "./services/WranglerApi.ts";
|
|
25
21
|
|
|
26
|
-
// ---------------------------------------------------------------------------
|
|
27
|
-
// Module augmentation — extends AlephaCliConfig with platform options
|
|
28
|
-
// ---------------------------------------------------------------------------
|
|
29
|
-
|
|
30
|
-
declare module "alepha/cli" {
|
|
31
|
-
interface AlephaCliConfig {
|
|
32
|
-
/**
|
|
33
|
-
* Platform deployment configuration.
|
|
34
|
-
*/
|
|
35
|
-
platform?: PlatformOptions;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
registerConfigProcessor((alepha: any, config: AlephaCliConfig) => {
|
|
40
|
-
if (config.platform) {
|
|
41
|
-
alepha.set(platformOptions, config.platform);
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
|
|
45
22
|
// ---------------------------------------------------------------------------
|
|
46
23
|
|
|
47
24
|
export const AlephaCliPlatform = $module({
|
|
@@ -49,6 +26,7 @@ export const AlephaCliPlatform = $module({
|
|
|
49
26
|
services: [
|
|
50
27
|
AlephaCli,
|
|
51
28
|
PlatformCommand,
|
|
29
|
+
SecretsCommand,
|
|
52
30
|
CloudflareAdapter,
|
|
53
31
|
CloudflareApi,
|
|
54
32
|
DockerAdapter,
|
|
@@ -59,7 +37,10 @@ export const AlephaCliPlatform = $module({
|
|
|
59
37
|
VercelCli,
|
|
60
38
|
WranglerApi,
|
|
61
39
|
PlatformCacheProvider,
|
|
40
|
+
GitHubSecretStore,
|
|
41
|
+
MemorySecretStore,
|
|
62
42
|
NamingService,
|
|
43
|
+
SecretFilterService,
|
|
63
44
|
PlatformInspector,
|
|
64
45
|
PlatformOrchestrator,
|
|
65
46
|
],
|
|
@@ -73,7 +54,11 @@ export * from "./adapters/PlatformAdapter.ts";
|
|
|
73
54
|
export * from "./adapters/VercelAdapter.ts";
|
|
74
55
|
export * from "./atoms/platformOptions.ts";
|
|
75
56
|
export * from "./commands/platform.ts";
|
|
57
|
+
export * from "./commands/SecretsCommand.ts";
|
|
58
|
+
export * from "./providers/GitHubSecretStore.ts";
|
|
59
|
+
export * from "./providers/MemorySecretStore.ts";
|
|
76
60
|
export * from "./providers/PlatformCacheProvider.ts";
|
|
61
|
+
export * from "./providers/SecretStoreProvider.ts";
|
|
77
62
|
export * from "./schemas/cloudflare.ts";
|
|
78
63
|
export * from "./schemas/platform.ts";
|
|
79
64
|
export * from "./schemas/vercel.ts";
|
|
@@ -83,6 +68,7 @@ export * from "./services/DockerSshService.ts";
|
|
|
83
68
|
export * from "./services/NamingService.ts";
|
|
84
69
|
export * from "./services/PlatformInspector.ts";
|
|
85
70
|
export * from "./services/PlatformOrchestrator.ts";
|
|
71
|
+
export * from "./services/SecretFilterService.ts";
|
|
86
72
|
export * from "./services/VercelApi.ts";
|
|
87
73
|
export * from "./services/VercelCli.ts";
|
|
88
74
|
export * from "./services/WranglerApi.ts";
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { Alepha } from "alepha";
|
|
2
|
+
import {
|
|
3
|
+
FileSystemProvider,
|
|
4
|
+
MemoryFileSystemProvider,
|
|
5
|
+
MemoryShellProvider,
|
|
6
|
+
ShellProvider,
|
|
7
|
+
} from "alepha/system";
|
|
8
|
+
import { describe, test } from "vitest";
|
|
9
|
+
import { GitHubSecretStore } from "./GitHubSecretStore.ts";
|
|
10
|
+
|
|
11
|
+
describe("GitHubSecretStore", () => {
|
|
12
|
+
const createTestEnv = () => {
|
|
13
|
+
const alepha = Alepha.create()
|
|
14
|
+
.with({
|
|
15
|
+
provide: ShellProvider,
|
|
16
|
+
use: MemoryShellProvider,
|
|
17
|
+
})
|
|
18
|
+
.with({
|
|
19
|
+
provide: FileSystemProvider,
|
|
20
|
+
use: MemoryFileSystemProvider,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const shell = alepha.inject(MemoryShellProvider);
|
|
24
|
+
const fs = alepha.inject(MemoryFileSystemProvider);
|
|
25
|
+
const store = alepha.inject(GitHubSecretStore);
|
|
26
|
+
|
|
27
|
+
return { alepha, shell, fs, store };
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
describe("ensureAvailable", () => {
|
|
31
|
+
test("succeeds when gh is installed and authenticated", async ({
|
|
32
|
+
expect,
|
|
33
|
+
}) => {
|
|
34
|
+
const { shell, store } = createTestEnv();
|
|
35
|
+
shell.installedCommands.add("gh");
|
|
36
|
+
shell.outputs.set("gh auth status", "Logged in");
|
|
37
|
+
|
|
38
|
+
await expect(store.ensureAvailable()).resolves.not.toThrow();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test("throws when gh is not installed", async ({ expect }) => {
|
|
42
|
+
const { store } = createTestEnv();
|
|
43
|
+
|
|
44
|
+
await expect(store.ensureAvailable()).rejects.toThrow(
|
|
45
|
+
"GitHub CLI (gh) is not installed",
|
|
46
|
+
);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test("throws when gh is not authenticated", async ({ expect }) => {
|
|
50
|
+
const { shell, store } = createTestEnv();
|
|
51
|
+
shell.installedCommands.add("gh");
|
|
52
|
+
shell.errors.set("gh auth status", "Not logged in");
|
|
53
|
+
|
|
54
|
+
await expect(store.ensureAvailable()).rejects.toThrow(
|
|
55
|
+
"GitHub CLI is not authenticated",
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
describe("list", () => {
|
|
61
|
+
test("parses JSON output from gh", async ({ expect }) => {
|
|
62
|
+
const { shell, store } = createTestEnv();
|
|
63
|
+
shell.outputs.set(
|
|
64
|
+
"gh secret list --env app-production --json name,updatedAt",
|
|
65
|
+
JSON.stringify([
|
|
66
|
+
{ name: "API_KEY", updatedAt: "2026-01-01T00:00:00Z" },
|
|
67
|
+
{ name: "DATABASE_URL", updatedAt: "2026-01-02T00:00:00Z" },
|
|
68
|
+
]),
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
const result = await store.list("app-production");
|
|
72
|
+
|
|
73
|
+
expect(result).toEqual([
|
|
74
|
+
{ name: "API_KEY", updatedAt: "2026-01-01T00:00:00Z" },
|
|
75
|
+
{ name: "DATABASE_URL", updatedAt: "2026-01-02T00:00:00Z" },
|
|
76
|
+
]);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test("returns empty array when no secrets", async ({ expect }) => {
|
|
80
|
+
const { shell, store } = createTestEnv();
|
|
81
|
+
shell.outputs.set(
|
|
82
|
+
"gh secret list --env app-staging --json name,updatedAt",
|
|
83
|
+
"[]",
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const result = await store.list("app-staging");
|
|
87
|
+
expect(result).toEqual([]);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test("returns empty array on error", async ({ expect }) => {
|
|
91
|
+
const { shell, store } = createTestEnv();
|
|
92
|
+
shell.errors.set(
|
|
93
|
+
"gh secret list --env bad-env --json name,updatedAt",
|
|
94
|
+
"Environment not found",
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
const result = await store.list("bad-env");
|
|
98
|
+
expect(result).toEqual([]);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
describe("set", () => {
|
|
103
|
+
test("writes dotenv file and calls gh secret set --env-file", async ({
|
|
104
|
+
expect,
|
|
105
|
+
}) => {
|
|
106
|
+
const { shell, fs, store } = createTestEnv();
|
|
107
|
+
|
|
108
|
+
await store.set("app-production", "API_KEY", "abc123");
|
|
109
|
+
|
|
110
|
+
// Should write dotenv format
|
|
111
|
+
const written = fs.writeFileCalls.find((c) =>
|
|
112
|
+
/\/tmp\/alepha-secret-API_KEY-/.test(c.path),
|
|
113
|
+
);
|
|
114
|
+
expect(written).toBeDefined();
|
|
115
|
+
expect(written!.data).toBe('API_KEY="abc123"\n');
|
|
116
|
+
|
|
117
|
+
// Should call gh with --env-file (no positional secret name)
|
|
118
|
+
expect(
|
|
119
|
+
shell.wasCalledMatching(
|
|
120
|
+
/gh secret set -f \/tmp\/alepha-secret-API_KEY-\d+ --env app-production/,
|
|
121
|
+
),
|
|
122
|
+
).toBe(true);
|
|
123
|
+
|
|
124
|
+
// Temp file should be cleaned up
|
|
125
|
+
expect(
|
|
126
|
+
fs.rmCalls.some((c) => /\/tmp\/alepha-secret-API_KEY-/.test(c.path)),
|
|
127
|
+
).toBe(true);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test("escapes special characters in value", async ({ expect }) => {
|
|
131
|
+
const { fs, store } = createTestEnv();
|
|
132
|
+
|
|
133
|
+
await store.set("app-production", "KEY", 'val"ue\nwith\\special');
|
|
134
|
+
|
|
135
|
+
const written = fs.writeFileCalls.find((c) =>
|
|
136
|
+
/\/tmp\/alepha-secret-KEY-/.test(c.path),
|
|
137
|
+
);
|
|
138
|
+
expect(written!.data).toBe('KEY="val\\"ue\\nwith\\\\special"\n');
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
describe("delete", () => {
|
|
143
|
+
test("calls gh secret delete with correct args", async ({ expect }) => {
|
|
144
|
+
const { shell, store } = createTestEnv();
|
|
145
|
+
|
|
146
|
+
await store.delete("app-production", "OLD_KEY");
|
|
147
|
+
|
|
148
|
+
expect(
|
|
149
|
+
shell.wasCalled("gh secret delete OLD_KEY --env app-production"),
|
|
150
|
+
).toBe(true);
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
});
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { $inject, AlephaError } from "alepha";
|
|
2
|
+
import { $logger } from "alepha/logger";
|
|
3
|
+
import { FileSystemProvider, ShellProvider } from "alepha/system";
|
|
4
|
+
import type {
|
|
5
|
+
RemoteSecret,
|
|
6
|
+
SecretStoreProvider,
|
|
7
|
+
} from "./SecretStoreProvider.ts";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* GitHub Actions secret store backed by the `gh` CLI.
|
|
11
|
+
*
|
|
12
|
+
* Requires the GitHub CLI (`gh`) to be installed and authenticated.
|
|
13
|
+
* Pushes secrets into GitHub Actions environments.
|
|
14
|
+
*/
|
|
15
|
+
export class GitHubSecretStore implements SecretStoreProvider {
|
|
16
|
+
protected readonly log = $logger();
|
|
17
|
+
protected readonly shell = $inject(ShellProvider);
|
|
18
|
+
protected readonly fs = $inject(FileSystemProvider);
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Verify that `gh` is installed and authenticated.
|
|
22
|
+
*/
|
|
23
|
+
public async ensureAvailable(): Promise<void> {
|
|
24
|
+
const installed = await this.shell.isInstalled("gh");
|
|
25
|
+
if (!installed) {
|
|
26
|
+
throw new AlephaError(
|
|
27
|
+
"GitHub CLI (gh) is not installed. Install it from https://cli.github.com",
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
await this.shell.run("gh auth status", { capture: true });
|
|
33
|
+
} catch {
|
|
34
|
+
throw new AlephaError(
|
|
35
|
+
"GitHub CLI is not authenticated. Run `gh auth login` first.",
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Create the GitHub Actions environment if it doesn't exist.
|
|
42
|
+
*/
|
|
43
|
+
public async ensureEnvironment(environment: string): Promise<void> {
|
|
44
|
+
await this.shell.run(
|
|
45
|
+
`gh api --method PUT /repos/{owner}/{repo}/environments/${environment} --silent`,
|
|
46
|
+
{ capture: true },
|
|
47
|
+
);
|
|
48
|
+
this.log.debug(`Ensured environment "${environment}" exists`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* List all secrets in a GitHub Actions environment.
|
|
53
|
+
*/
|
|
54
|
+
public async list(environment: string): Promise<RemoteSecret[]> {
|
|
55
|
+
try {
|
|
56
|
+
const output = await this.shell.run(
|
|
57
|
+
`gh secret list --env ${environment} --json name,updatedAt`,
|
|
58
|
+
{ capture: true },
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
const parsed = JSON.parse(output || "[]") as Array<{
|
|
62
|
+
name: string;
|
|
63
|
+
updatedAt?: string;
|
|
64
|
+
}>;
|
|
65
|
+
|
|
66
|
+
return parsed.map((s) => ({
|
|
67
|
+
name: s.name,
|
|
68
|
+
updatedAt: s.updatedAt,
|
|
69
|
+
}));
|
|
70
|
+
} catch (error) {
|
|
71
|
+
this.log.debug("Failed to list secrets", { environment, error });
|
|
72
|
+
return [];
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Set a secret in a GitHub Actions environment.
|
|
78
|
+
*
|
|
79
|
+
* Writes a dotenv-formatted file and uses `gh secret set --env-file` to
|
|
80
|
+
* avoid shell pipe issues with NodeShellProvider escaping the `|` character.
|
|
81
|
+
*/
|
|
82
|
+
public async set(
|
|
83
|
+
environment: string,
|
|
84
|
+
key: string,
|
|
85
|
+
value: string,
|
|
86
|
+
): Promise<void> {
|
|
87
|
+
const tmpFile = `/tmp/alepha-secret-${key}-${Date.now()}`;
|
|
88
|
+
const escaped = value
|
|
89
|
+
.replace(/\\/g, "\\\\")
|
|
90
|
+
.replace(/"/g, '\\"')
|
|
91
|
+
.replace(/\n/g, "\\n");
|
|
92
|
+
await this.fs.writeFile(tmpFile, `${key}="${escaped}"\n`);
|
|
93
|
+
try {
|
|
94
|
+
const output = await this.shell.run(
|
|
95
|
+
`gh secret set -f ${tmpFile} --env ${environment}`,
|
|
96
|
+
{ capture: true },
|
|
97
|
+
);
|
|
98
|
+
this.log.debug(`Secret set: ${key}`, { output });
|
|
99
|
+
} finally {
|
|
100
|
+
await this.fs.rm(tmpFile);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Delete a secret from a GitHub Actions environment.
|
|
106
|
+
*/
|
|
107
|
+
public async delete(environment: string, key: string): Promise<void> {
|
|
108
|
+
await this.shell.run(`gh secret delete ${key} --env ${environment}`, {
|
|
109
|
+
capture: true,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
RemoteSecret,
|
|
3
|
+
SecretStoreProvider,
|
|
4
|
+
} from "./SecretStoreProvider.ts";
|
|
5
|
+
|
|
6
|
+
export interface MemorySecretStoreCall {
|
|
7
|
+
method: "ensureAvailable" | "ensureEnvironment" | "list" | "set" | "delete";
|
|
8
|
+
environment?: string;
|
|
9
|
+
key?: string;
|
|
10
|
+
value?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* In-memory implementation of SecretStoreProvider for testing.
|
|
15
|
+
* Records all operations and stores secrets in a nested Map.
|
|
16
|
+
*/
|
|
17
|
+
export class MemorySecretStore implements SecretStoreProvider {
|
|
18
|
+
/**
|
|
19
|
+
* Secrets keyed by environment, then by key.
|
|
20
|
+
*/
|
|
21
|
+
public secrets = new Map<string, Map<string, string>>();
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* All recorded operations.
|
|
25
|
+
*/
|
|
26
|
+
public calls: MemorySecretStoreCall[] = [];
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* When set, ensureAvailable() will throw with this message.
|
|
30
|
+
*/
|
|
31
|
+
public availableError: string | null = null;
|
|
32
|
+
|
|
33
|
+
public async ensureAvailable(): Promise<void> {
|
|
34
|
+
this.calls.push({ method: "ensureAvailable" });
|
|
35
|
+
if (this.availableError) {
|
|
36
|
+
throw new Error(this.availableError);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public async ensureEnvironment(environment: string): Promise<void> {
|
|
41
|
+
this.calls.push({ method: "ensureEnvironment", environment });
|
|
42
|
+
if (!this.secrets.has(environment)) {
|
|
43
|
+
this.secrets.set(environment, new Map());
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public async list(environment: string): Promise<RemoteSecret[]> {
|
|
48
|
+
this.calls.push({ method: "list", environment });
|
|
49
|
+
const envSecrets = this.secrets.get(environment);
|
|
50
|
+
if (!envSecrets) return [];
|
|
51
|
+
|
|
52
|
+
return Array.from(envSecrets.keys()).map((name) => ({ name }));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public async set(
|
|
56
|
+
environment: string,
|
|
57
|
+
key: string,
|
|
58
|
+
value: string,
|
|
59
|
+
): Promise<void> {
|
|
60
|
+
this.calls.push({ method: "set", environment, key, value });
|
|
61
|
+
|
|
62
|
+
let envSecrets = this.secrets.get(environment);
|
|
63
|
+
if (!envSecrets) {
|
|
64
|
+
envSecrets = new Map();
|
|
65
|
+
this.secrets.set(environment, envSecrets);
|
|
66
|
+
}
|
|
67
|
+
envSecrets.set(key, value);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public async delete(environment: string, key: string): Promise<void> {
|
|
71
|
+
this.calls.push({ method: "delete", environment, key });
|
|
72
|
+
this.secrets.get(environment)?.delete(key);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Check if set() was called for a given environment and key.
|
|
77
|
+
*/
|
|
78
|
+
public wasSet(environment: string, key: string): boolean {
|
|
79
|
+
return this.calls.some(
|
|
80
|
+
(c) =>
|
|
81
|
+
c.method === "set" && c.environment === environment && c.key === key,
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Check if delete() was called for a given environment and key.
|
|
87
|
+
*/
|
|
88
|
+
public wasDeleted(environment: string, key: string): boolean {
|
|
89
|
+
return this.calls.some(
|
|
90
|
+
(c) =>
|
|
91
|
+
c.method === "delete" && c.environment === environment && c.key === key,
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Get all set() calls for a given environment.
|
|
97
|
+
*/
|
|
98
|
+
public getSetCalls(
|
|
99
|
+
environment: string,
|
|
100
|
+
): Array<{ key: string; value: string }> {
|
|
101
|
+
return this.calls
|
|
102
|
+
.filter((c) => c.method === "set" && c.environment === environment)
|
|
103
|
+
.map((c) => ({ key: c.key!, value: c.value! }));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Reset all state.
|
|
108
|
+
*/
|
|
109
|
+
public reset(): void {
|
|
110
|
+
this.secrets.clear();
|
|
111
|
+
this.calls = [];
|
|
112
|
+
this.availableError = null;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A secret stored in a remote secret store.
|
|
3
|
+
*/
|
|
4
|
+
export interface RemoteSecret {
|
|
5
|
+
name: string;
|
|
6
|
+
updatedAt?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Abstract provider for managing secrets in an external store.
|
|
11
|
+
*
|
|
12
|
+
* Implementations: GitHubSecretStore, MemorySecretStore
|
|
13
|
+
*/
|
|
14
|
+
export abstract class SecretStoreProvider {
|
|
15
|
+
/**
|
|
16
|
+
* Verify the backing store is reachable and authenticated.
|
|
17
|
+
*/
|
|
18
|
+
abstract ensureAvailable(): Promise<void>;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Ensure the target environment exists in the store, creating it if needed.
|
|
22
|
+
*/
|
|
23
|
+
abstract ensureEnvironment(environment: string): Promise<void>;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* List all secrets in a given environment.
|
|
27
|
+
*/
|
|
28
|
+
abstract list(environment: string): Promise<RemoteSecret[]>;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Set (create or update) a secret in a given environment.
|
|
32
|
+
*/
|
|
33
|
+
abstract set(environment: string, key: string, value: string): Promise<void>;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Delete a secret from a given environment.
|
|
37
|
+
*/
|
|
38
|
+
abstract delete(environment: string, key: string): Promise<void>;
|
|
39
|
+
}
|
|
@@ -153,6 +153,8 @@ export type CloudflareSecret = Static<typeof cloudflareSecretSchema>;
|
|
|
153
153
|
|
|
154
154
|
export const createD1BodySchema = t.object({
|
|
155
155
|
name: t.string(),
|
|
156
|
+
primary_location_hint: t.optional(t.string()),
|
|
157
|
+
jurisdiction: t.optional(t.string()),
|
|
156
158
|
});
|
|
157
159
|
|
|
158
160
|
export const createKVBodySchema = t.object({
|
|
@@ -118,13 +118,16 @@ export class CloudflareApi {
|
|
|
118
118
|
);
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
public async createD1(
|
|
121
|
+
public async createD1(
|
|
122
|
+
name: string,
|
|
123
|
+
location = "weur", // TODO: move to config (or auto-resolve based on account info, or ask ?)
|
|
124
|
+
): Promise<CloudflareD1> {
|
|
122
125
|
const accountId = await this.resolveAccountId();
|
|
123
126
|
return await this.fetch<CloudflareD1>(
|
|
124
127
|
`/accounts/${accountId}/d1/database`,
|
|
125
128
|
{
|
|
126
129
|
method: "POST",
|
|
127
|
-
body: { name },
|
|
130
|
+
body: { name, primary_location_hint: location },
|
|
128
131
|
bodySchema: createD1BodySchema,
|
|
129
132
|
schema: cloudflareD1Schema,
|
|
130
133
|
},
|
|
@@ -154,6 +154,62 @@ describe("DockerComposeGenerator", () => {
|
|
|
154
154
|
expect(result).toBeNull();
|
|
155
155
|
});
|
|
156
156
|
|
|
157
|
+
test("generates rustfs service when app has bucket and no S3_ENDPOINT", ({
|
|
158
|
+
expect,
|
|
159
|
+
}) => {
|
|
160
|
+
const { generator, naming } = createTestEnv();
|
|
161
|
+
const namingCtx = naming.forContext("myapp", "local");
|
|
162
|
+
|
|
163
|
+
const result = generator.generateLocal({
|
|
164
|
+
project: "myapp",
|
|
165
|
+
env: "local",
|
|
166
|
+
naming: namingCtx,
|
|
167
|
+
apps: [
|
|
168
|
+
makeApp({
|
|
169
|
+
resources: {
|
|
170
|
+
hasDatabase: false,
|
|
171
|
+
hasBucket: true,
|
|
172
|
+
hasKV: false,
|
|
173
|
+
hasQueue: false,
|
|
174
|
+
hasCron: false,
|
|
175
|
+
},
|
|
176
|
+
}),
|
|
177
|
+
],
|
|
178
|
+
envVars: {},
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
expect(result).toContain("rustfs:");
|
|
182
|
+
expect(result).toContain("image: rustfs/rustfs:latest");
|
|
183
|
+
expect(result).toContain("9000:9000");
|
|
184
|
+
expect(result).toContain("RUSTFS_ROOT_USER: alepha");
|
|
185
|
+
expect(result).toContain("rustfs_data:");
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
test("skips rustfs when S3_ENDPOINT is present", ({ expect }) => {
|
|
189
|
+
const { generator, naming } = createTestEnv();
|
|
190
|
+
const namingCtx = naming.forContext("myapp", "local");
|
|
191
|
+
|
|
192
|
+
const result = generator.generateLocal({
|
|
193
|
+
project: "myapp",
|
|
194
|
+
env: "local",
|
|
195
|
+
naming: namingCtx,
|
|
196
|
+
apps: [
|
|
197
|
+
makeApp({
|
|
198
|
+
resources: {
|
|
199
|
+
hasDatabase: false,
|
|
200
|
+
hasBucket: true,
|
|
201
|
+
hasKV: false,
|
|
202
|
+
hasQueue: false,
|
|
203
|
+
hasCron: false,
|
|
204
|
+
},
|
|
205
|
+
}),
|
|
206
|
+
],
|
|
207
|
+
envVars: { S3_ENDPOINT: "https://xxx.r2.cloudflarestorage.com" },
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
expect(result).toBeNull();
|
|
211
|
+
});
|
|
212
|
+
|
|
157
213
|
test("returns null when no services needed", ({ expect }) => {
|
|
158
214
|
const { generator, naming } = createTestEnv();
|
|
159
215
|
const namingCtx = naming.forContext("myapp", "local");
|
|
@@ -312,6 +368,65 @@ describe("DockerComposeGenerator", () => {
|
|
|
312
368
|
expect(result).toContain("Host(`myshop.com`)");
|
|
313
369
|
});
|
|
314
370
|
|
|
371
|
+
test("generates rustfs service when app has bucket", ({ expect }) => {
|
|
372
|
+
const { generator, naming } = createTestEnv();
|
|
373
|
+
const namingCtx = naming.forContext("myapp", "production");
|
|
374
|
+
|
|
375
|
+
const result = generator.generateRemote({
|
|
376
|
+
project: "myapp",
|
|
377
|
+
env: "production",
|
|
378
|
+
naming: namingCtx,
|
|
379
|
+
domain: "myapp.com",
|
|
380
|
+
apps: [
|
|
381
|
+
makeApp({
|
|
382
|
+
resources: {
|
|
383
|
+
hasDatabase: false,
|
|
384
|
+
hasBucket: true,
|
|
385
|
+
hasKV: false,
|
|
386
|
+
hasQueue: false,
|
|
387
|
+
hasCron: false,
|
|
388
|
+
},
|
|
389
|
+
}),
|
|
390
|
+
],
|
|
391
|
+
envVars: {},
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
expect(result).toContain("rustfs:");
|
|
395
|
+
expect(result).toContain("image: rustfs/rustfs:latest");
|
|
396
|
+
expect(result).toContain("RUSTFS_ROOT_PASSWORD: ${S3_SECRET_KEY}");
|
|
397
|
+
expect(result).toContain("rustfs_data:");
|
|
398
|
+
expect(result).toContain("depends_on:");
|
|
399
|
+
expect(result).toContain("- rustfs");
|
|
400
|
+
// RustFS on internal network when domain is set
|
|
401
|
+
expect(result).toContain("internal");
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
test("skips rustfs when S3_ENDPOINT present", ({ expect }) => {
|
|
405
|
+
const { generator, naming } = createTestEnv();
|
|
406
|
+
const namingCtx = naming.forContext("myapp", "production");
|
|
407
|
+
|
|
408
|
+
const result = generator.generateRemote({
|
|
409
|
+
project: "myapp",
|
|
410
|
+
env: "production",
|
|
411
|
+
naming: namingCtx,
|
|
412
|
+
domain: "myapp.com",
|
|
413
|
+
apps: [
|
|
414
|
+
makeApp({
|
|
415
|
+
resources: {
|
|
416
|
+
hasDatabase: false,
|
|
417
|
+
hasBucket: true,
|
|
418
|
+
hasKV: false,
|
|
419
|
+
hasQueue: false,
|
|
420
|
+
hasCron: false,
|
|
421
|
+
},
|
|
422
|
+
}),
|
|
423
|
+
],
|
|
424
|
+
envVars: { S3_ENDPOINT: "https://xxx.r2.cloudflarestorage.com" },
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
expect(result).not.toContain("rustfs:");
|
|
428
|
+
});
|
|
429
|
+
|
|
315
430
|
test("multi-app without domain exposes incremental ports", ({ expect }) => {
|
|
316
431
|
const { generator, naming } = createTestEnv();
|
|
317
432
|
const namingCtx = naming.forContext("myproject", "staging");
|