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
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import { Alepha } from "alepha";
|
|
2
|
+
import { CliProvider } from "alepha/command";
|
|
3
|
+
import { FileSystemProvider, MemoryFileSystemProvider } from "alepha/system";
|
|
4
|
+
import { describe, test } from "vitest";
|
|
5
|
+
import { platformOptions } from "../atoms/platformOptions.ts";
|
|
6
|
+
import { MemorySecretStore } from "../providers/MemorySecretStore.ts";
|
|
7
|
+
import type { SecretStoreProvider } from "../providers/SecretStoreProvider.ts";
|
|
8
|
+
import { SecretsCommand } from "./SecretsCommand.ts";
|
|
9
|
+
|
|
10
|
+
class TestSecretsCommand extends SecretsCommand {
|
|
11
|
+
public readonly testList = this.list;
|
|
12
|
+
public readonly testDiff = this.diff;
|
|
13
|
+
public readonly testApply = this.apply;
|
|
14
|
+
public testStore: MemorySecretStore | null = null;
|
|
15
|
+
|
|
16
|
+
public override resolveStore(): SecretStoreProvider {
|
|
17
|
+
if (this.testStore) return this.testStore;
|
|
18
|
+
return super.resolveStore();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
describe("SecretsCommand", () => {
|
|
23
|
+
const createTestEnv = (
|
|
24
|
+
config: Record<string, any> = {},
|
|
25
|
+
storeSecrets: Record<string, Record<string, string>> = {},
|
|
26
|
+
) => {
|
|
27
|
+
const alepha = Alepha.create().with({
|
|
28
|
+
provide: FileSystemProvider,
|
|
29
|
+
use: MemoryFileSystemProvider,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const fs = alepha.inject(MemoryFileSystemProvider);
|
|
33
|
+
const store = new MemorySecretStore();
|
|
34
|
+
const cli = alepha.inject(CliProvider);
|
|
35
|
+
const cmd = alepha.inject(TestSecretsCommand);
|
|
36
|
+
cmd.testStore = store;
|
|
37
|
+
|
|
38
|
+
alepha.set(platformOptions, {
|
|
39
|
+
name: "my-app",
|
|
40
|
+
environments: { production: { adapter: "cloudflare" } },
|
|
41
|
+
...config,
|
|
42
|
+
} as any);
|
|
43
|
+
|
|
44
|
+
// Seed package.json
|
|
45
|
+
fs.writeFile("/project/package.json", JSON.stringify({ name: "my-app" }));
|
|
46
|
+
|
|
47
|
+
// Seed store with pre-existing secrets
|
|
48
|
+
for (const [env, secrets] of Object.entries(storeSecrets)) {
|
|
49
|
+
const envMap = new Map<string, string>();
|
|
50
|
+
for (const [k, v] of Object.entries(secrets)) {
|
|
51
|
+
envMap.set(k, v);
|
|
52
|
+
}
|
|
53
|
+
store.secrets.set(env, envMap);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return { alepha, fs, store, cli, cmd };
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// -----------------------------------------------------------------------
|
|
60
|
+
// apply
|
|
61
|
+
// -----------------------------------------------------------------------
|
|
62
|
+
|
|
63
|
+
describe("apply", () => {
|
|
64
|
+
test("filters and pushes secrets to store", async ({ expect }) => {
|
|
65
|
+
const { fs, store, cli, cmd } = createTestEnv();
|
|
66
|
+
|
|
67
|
+
await fs.writeFile(
|
|
68
|
+
"/project/.env.production",
|
|
69
|
+
"DATABASE_URL=postgres://localhost/db\nAPI_KEY=abc123\nNODE_ENV=production\nVITE_APP=hello\nEMPTY=",
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
await cli.run(cmd.testApply, {
|
|
73
|
+
root: "/project",
|
|
74
|
+
argv: "--env production",
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
expect(store.wasSet("my-app-production", "DATABASE_URL")).toBe(true);
|
|
78
|
+
expect(store.wasSet("my-app-production", "API_KEY")).toBe(true);
|
|
79
|
+
expect(store.wasSet("my-app-production", "NODE_ENV")).toBe(false);
|
|
80
|
+
expect(store.wasSet("my-app-production", "VITE_APP")).toBe(false);
|
|
81
|
+
expect(store.wasSet("my-app-production", "EMPTY")).toBe(false);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test("renames GITHUB_ keys with APP_ prefix", async ({ expect }) => {
|
|
85
|
+
const { fs, store, cli, cmd } = createTestEnv();
|
|
86
|
+
|
|
87
|
+
await fs.writeFile(
|
|
88
|
+
"/project/.env.production",
|
|
89
|
+
"GITHUB_CLIENT_ID=id123\nGITHUB_CLIENT_SECRET=secret456",
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
await cli.run(cmd.testApply, {
|
|
93
|
+
root: "/project",
|
|
94
|
+
argv: "--env production",
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
expect(store.wasSet("my-app-production", "APP_GITHUB_CLIENT_ID")).toBe(
|
|
98
|
+
true,
|
|
99
|
+
);
|
|
100
|
+
expect(
|
|
101
|
+
store.wasSet("my-app-production", "APP_GITHUB_CLIENT_SECRET"),
|
|
102
|
+
).toBe(true);
|
|
103
|
+
expect(store.wasSet("my-app-production", "GITHUB_CLIENT_ID")).toBe(false);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
test("dry run does not call store", async ({ expect }) => {
|
|
107
|
+
const { fs, store, cli, cmd } = createTestEnv();
|
|
108
|
+
|
|
109
|
+
await fs.writeFile(
|
|
110
|
+
"/project/.env.production",
|
|
111
|
+
"API_KEY=abc123\nSECRET=xyz",
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
await cli.run(cmd.testApply, {
|
|
115
|
+
root: "/project",
|
|
116
|
+
argv: "--env production --dry-run",
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
expect(store.calls.filter((c) => c.method === "set")).toHaveLength(0);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
test("uses custom environment pattern", async ({ expect }) => {
|
|
123
|
+
const { fs, store, cli, cmd } = createTestEnv({
|
|
124
|
+
secrets: {
|
|
125
|
+
store: "github",
|
|
126
|
+
environmentPattern: "{env}",
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
await fs.writeFile("/project/.env.production", "API_KEY=abc123");
|
|
131
|
+
|
|
132
|
+
await cli.run(cmd.testApply, {
|
|
133
|
+
root: "/project",
|
|
134
|
+
argv: "--env production",
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
expect(store.wasSet("production", "API_KEY")).toBe(true);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// -----------------------------------------------------------------------
|
|
142
|
+
// diff
|
|
143
|
+
// -----------------------------------------------------------------------
|
|
144
|
+
|
|
145
|
+
describe("diff", () => {
|
|
146
|
+
test("detects only-local, only-remote, and in-both keys", async ({
|
|
147
|
+
expect,
|
|
148
|
+
}) => {
|
|
149
|
+
const { fs, cli, cmd } = createTestEnv(
|
|
150
|
+
{},
|
|
151
|
+
{
|
|
152
|
+
"my-app-production": {
|
|
153
|
+
API_KEY: "remote-value",
|
|
154
|
+
OLD_SECRET: "stale",
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
await fs.writeFile(
|
|
160
|
+
"/project/.env.production",
|
|
161
|
+
"API_KEY=local-value\nNEW_SECRET=fresh",
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
// Capture stdout
|
|
165
|
+
const writes: string[] = [];
|
|
166
|
+
const originalWrite = process.stdout.write;
|
|
167
|
+
process.stdout.write = ((chunk: string) => {
|
|
168
|
+
writes.push(chunk);
|
|
169
|
+
return true;
|
|
170
|
+
}) as any;
|
|
171
|
+
|
|
172
|
+
try {
|
|
173
|
+
await cli.run(cmd.testDiff, {
|
|
174
|
+
root: "/project",
|
|
175
|
+
argv: "--env production",
|
|
176
|
+
});
|
|
177
|
+
} finally {
|
|
178
|
+
process.stdout.write = originalWrite;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// biome-ignore lint/suspicious/noControlCharactersInRegex: stripping ANSI codes
|
|
182
|
+
const output = writes.join("").replace(/\x1B\[[0-9;]*m/g, "");
|
|
183
|
+
expect(output).toContain("+ NEW_SECRET");
|
|
184
|
+
expect(output).toContain("- OLD_SECRET");
|
|
185
|
+
expect(output).toContain("= API_KEY");
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
// -----------------------------------------------------------------------
|
|
190
|
+
// list
|
|
191
|
+
// -----------------------------------------------------------------------
|
|
192
|
+
|
|
193
|
+
describe("list", () => {
|
|
194
|
+
test("shows table format by default", async ({ expect }) => {
|
|
195
|
+
const { cli, cmd } = createTestEnv(
|
|
196
|
+
{},
|
|
197
|
+
{
|
|
198
|
+
"my-app-production": {
|
|
199
|
+
API_KEY: "value1",
|
|
200
|
+
DATABASE_URL: "value2",
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
const writes: string[] = [];
|
|
206
|
+
const originalWrite = process.stdout.write;
|
|
207
|
+
process.stdout.write = ((chunk: string) => {
|
|
208
|
+
writes.push(chunk);
|
|
209
|
+
return true;
|
|
210
|
+
}) as any;
|
|
211
|
+
|
|
212
|
+
try {
|
|
213
|
+
await cli.run(cmd.testList, {
|
|
214
|
+
root: "/project",
|
|
215
|
+
argv: "--env production",
|
|
216
|
+
});
|
|
217
|
+
} finally {
|
|
218
|
+
process.stdout.write = originalWrite;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const output = writes.join("");
|
|
222
|
+
expect(output).toContain("API_KEY");
|
|
223
|
+
expect(output).toContain("DATABASE_URL");
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
test("shows GHA format", async ({ expect }) => {
|
|
227
|
+
const { cli, cmd } = createTestEnv(
|
|
228
|
+
{},
|
|
229
|
+
{
|
|
230
|
+
"my-app-production": {
|
|
231
|
+
API_KEY: "value1",
|
|
232
|
+
APP_GITHUB_CLIENT_ID: "value2",
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
const writes: string[] = [];
|
|
238
|
+
const originalWrite = process.stdout.write;
|
|
239
|
+
process.stdout.write = ((chunk: string) => {
|
|
240
|
+
writes.push(chunk);
|
|
241
|
+
return true;
|
|
242
|
+
}) as any;
|
|
243
|
+
|
|
244
|
+
try {
|
|
245
|
+
await cli.run(cmd.testList, {
|
|
246
|
+
root: "/project",
|
|
247
|
+
argv: "--env production --format gha",
|
|
248
|
+
});
|
|
249
|
+
} finally {
|
|
250
|
+
process.stdout.write = originalWrite;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const output = writes.join("");
|
|
254
|
+
expect(output).toContain("env:");
|
|
255
|
+
expect(output).toContain("API_KEY: ${{ secrets.API_KEY }}");
|
|
256
|
+
expect(output).toContain(
|
|
257
|
+
"GITHUB_CLIENT_ID: ${{ secrets.APP_GITHUB_CLIENT_ID }}",
|
|
258
|
+
);
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
// -----------------------------------------------------------------------
|
|
263
|
+
// environment name resolution
|
|
264
|
+
// -----------------------------------------------------------------------
|
|
265
|
+
|
|
266
|
+
describe("environment name resolution", () => {
|
|
267
|
+
test("uses default pattern {project}-{env}", async ({ expect }) => {
|
|
268
|
+
const { fs, store, cli, cmd } = createTestEnv();
|
|
269
|
+
|
|
270
|
+
await fs.writeFile("/project/.env.production", "KEY=val");
|
|
271
|
+
|
|
272
|
+
await cli.run(cmd.testApply, {
|
|
273
|
+
root: "/project",
|
|
274
|
+
argv: "--env production",
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
expect(store.wasSet("my-app-production", "KEY")).toBe(true);
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
test("uses custom pattern", async ({ expect }) => {
|
|
281
|
+
const { fs, store, cli, cmd } = createTestEnv({
|
|
282
|
+
secrets: {
|
|
283
|
+
store: "github",
|
|
284
|
+
environmentPattern: "deploy-{project}-{env}",
|
|
285
|
+
},
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
await fs.writeFile("/project/.env.production", "KEY=val");
|
|
289
|
+
|
|
290
|
+
await cli.run(cmd.testApply, {
|
|
291
|
+
root: "/project",
|
|
292
|
+
argv: "--env production",
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
expect(store.wasSet("deploy-my-app-production", "KEY")).toBe(true);
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
});
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { $inject, $use, AlephaError, t } from "alepha";
|
|
2
|
+
import { $command, EnvUtils } from "alepha/command";
|
|
3
|
+
import { $logger, ConsoleColorProvider } from "alepha/logger";
|
|
4
|
+
import { platformOptions } from "../atoms/platformOptions.ts";
|
|
5
|
+
import { GitHubSecretStore } from "../providers/GitHubSecretStore.ts";
|
|
6
|
+
import type { SecretStoreProvider } from "../providers/SecretStoreProvider.ts";
|
|
7
|
+
import { NamingService } from "../services/NamingService.ts";
|
|
8
|
+
import { PlatformInspector } from "../services/PlatformInspector.ts";
|
|
9
|
+
import { SecretFilterService } from "../services/SecretFilterService.ts";
|
|
10
|
+
|
|
11
|
+
export class SecretsCommand {
|
|
12
|
+
protected readonly log = $logger();
|
|
13
|
+
protected readonly options = $use(platformOptions);
|
|
14
|
+
protected readonly inspector = $inject(PlatformInspector);
|
|
15
|
+
protected readonly naming = $inject(NamingService);
|
|
16
|
+
protected readonly envUtils = $inject(EnvUtils);
|
|
17
|
+
protected readonly githubStore = $inject(GitHubSecretStore);
|
|
18
|
+
protected readonly filter = $inject(SecretFilterService);
|
|
19
|
+
protected readonly color = $inject(ConsoleColorProvider);
|
|
20
|
+
|
|
21
|
+
protected readonly envFlags = t.object({
|
|
22
|
+
env: t.optional(
|
|
23
|
+
t.text({
|
|
24
|
+
aliases: ["e"],
|
|
25
|
+
description: "Target environment",
|
|
26
|
+
}),
|
|
27
|
+
),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// -----------------------------------------------------------------------
|
|
31
|
+
// alepha p secrets list
|
|
32
|
+
// -----------------------------------------------------------------------
|
|
33
|
+
|
|
34
|
+
protected readonly list = $command({
|
|
35
|
+
name: "list",
|
|
36
|
+
aliases: ["ls"],
|
|
37
|
+
description: "List secrets in the remote store",
|
|
38
|
+
flags: t.object({
|
|
39
|
+
env: t.optional(
|
|
40
|
+
t.text({
|
|
41
|
+
aliases: ["e"],
|
|
42
|
+
description: "Target environment",
|
|
43
|
+
}),
|
|
44
|
+
),
|
|
45
|
+
format: t.optional(
|
|
46
|
+
t.text({
|
|
47
|
+
aliases: ["f"],
|
|
48
|
+
description: "Output format: table (default), gha",
|
|
49
|
+
}),
|
|
50
|
+
),
|
|
51
|
+
}),
|
|
52
|
+
handler: async ({ flags, root, run }) => {
|
|
53
|
+
const config = await this.inspector.resolveConfig(root);
|
|
54
|
+
const env = flags.env ?? config.defaultEnv;
|
|
55
|
+
const envName = this.resolveEnvironmentName(config.project, env);
|
|
56
|
+
const format = flags.format ?? "table";
|
|
57
|
+
|
|
58
|
+
const store = this.resolveStore();
|
|
59
|
+
await store.ensureAvailable();
|
|
60
|
+
const remoteSecrets = await store.list(envName);
|
|
61
|
+
|
|
62
|
+
run.end();
|
|
63
|
+
|
|
64
|
+
if (format === "gha") {
|
|
65
|
+
process.stdout.write(
|
|
66
|
+
`# Generated by alepha — environment: ${envName}\n`,
|
|
67
|
+
);
|
|
68
|
+
process.stdout.write("env:\n");
|
|
69
|
+
for (const secret of remoteSecrets) {
|
|
70
|
+
const localName = this.filter.toLocalName(secret.name);
|
|
71
|
+
process.stdout.write(
|
|
72
|
+
` ${localName}: \${{ secrets.${secret.name} }}\n`,
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// table format
|
|
79
|
+
const c = this.color;
|
|
80
|
+
|
|
81
|
+
if (remoteSecrets.length === 0) {
|
|
82
|
+
process.stdout.write(
|
|
83
|
+
`\nNo secrets in environment ${c.set("CYAN", envName)}.\n\n`,
|
|
84
|
+
);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
process.stdout.write(
|
|
89
|
+
`\n${c.set("GREY_LIGHT", "Environment:")} ${c.set("CYAN", envName)}\n\n`,
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
const maxNameLen = Math.max(
|
|
93
|
+
...remoteSecrets.map((s) => s.name.length),
|
|
94
|
+
4,
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
process.stdout.write(
|
|
98
|
+
` ${c.set("GREY_LIGHT", "NAME".padEnd(maxNameLen + 2))}${c.set("GREY_LIGHT", "UPDATED")}\n`,
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
for (const secret of remoteSecrets) {
|
|
102
|
+
const updated = secret.updatedAt
|
|
103
|
+
? new Date(secret.updatedAt).toLocaleString()
|
|
104
|
+
: "-";
|
|
105
|
+
process.stdout.write(
|
|
106
|
+
` ${c.set("CYAN", secret.name.padEnd(maxNameLen + 2))}${c.set("GREY_DARK", updated)}\n`,
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
process.stdout.write("\n");
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// -----------------------------------------------------------------------
|
|
115
|
+
// alepha p secrets diff
|
|
116
|
+
// -----------------------------------------------------------------------
|
|
117
|
+
|
|
118
|
+
protected readonly diff = $command({
|
|
119
|
+
name: "diff",
|
|
120
|
+
description: "Compare local .env keys with remote store",
|
|
121
|
+
flags: this.envFlags,
|
|
122
|
+
handler: async ({ flags, root, run }) => {
|
|
123
|
+
const config = await this.inspector.resolveConfig(root);
|
|
124
|
+
const env = flags.env ?? config.defaultEnv;
|
|
125
|
+
const envName = this.resolveEnvironmentName(config.project, env);
|
|
126
|
+
|
|
127
|
+
const envVars = await this.envUtils.parseEnv(root, [`.env.${env}`]);
|
|
128
|
+
const filtered = this.filter.filter(envVars);
|
|
129
|
+
const localKeys = new Set(
|
|
130
|
+
Object.keys(filtered).map((k) => this.filter.toRemoteName(k)),
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
const store = this.resolveStore();
|
|
134
|
+
await store.ensureAvailable();
|
|
135
|
+
const remoteSecrets = await store.list(envName);
|
|
136
|
+
const remoteKeys = new Set(remoteSecrets.map((s) => s.name));
|
|
137
|
+
|
|
138
|
+
run.end();
|
|
139
|
+
|
|
140
|
+
const c = this.color;
|
|
141
|
+
const allKeys = [...new Set([...localKeys, ...remoteKeys])].sort();
|
|
142
|
+
|
|
143
|
+
process.stdout.write(
|
|
144
|
+
`\n${c.set("GREY_LIGHT", "Environment:")} ${c.set("CYAN", envName)}\n\n`,
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
let hasChanges = false;
|
|
148
|
+
for (const key of allKeys) {
|
|
149
|
+
const inLocal = localKeys.has(key);
|
|
150
|
+
const inRemote = remoteKeys.has(key);
|
|
151
|
+
|
|
152
|
+
if (inLocal && !inRemote) {
|
|
153
|
+
process.stdout.write(` ${c.set("GREEN", "+")} ${key}\n`);
|
|
154
|
+
hasChanges = true;
|
|
155
|
+
} else if (!inLocal && inRemote) {
|
|
156
|
+
process.stdout.write(` ${c.set("RED", "-")} ${key}\n`);
|
|
157
|
+
hasChanges = true;
|
|
158
|
+
} else {
|
|
159
|
+
process.stdout.write(` ${c.set("GREY_DARK", "=")} ${key}\n`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (!hasChanges) {
|
|
164
|
+
process.stdout.write(
|
|
165
|
+
` ${c.set("GREEN", "Local and remote are in sync.")}\n`,
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
process.stdout.write("\n");
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// -----------------------------------------------------------------------
|
|
174
|
+
// alepha p secrets apply
|
|
175
|
+
// -----------------------------------------------------------------------
|
|
176
|
+
|
|
177
|
+
protected readonly apply = $command({
|
|
178
|
+
name: "apply",
|
|
179
|
+
description: "Push local .env secrets to the remote store",
|
|
180
|
+
flags: t.object({
|
|
181
|
+
env: t.optional(
|
|
182
|
+
t.text({
|
|
183
|
+
aliases: ["e"],
|
|
184
|
+
description: "Target environment",
|
|
185
|
+
}),
|
|
186
|
+
),
|
|
187
|
+
"dry-run": t.optional(
|
|
188
|
+
t.boolean({
|
|
189
|
+
description: "Preview changes without pushing",
|
|
190
|
+
}),
|
|
191
|
+
),
|
|
192
|
+
}),
|
|
193
|
+
handler: async ({ flags, root, run }) => {
|
|
194
|
+
const config = await this.inspector.resolveConfig(root);
|
|
195
|
+
const env = flags.env ?? config.defaultEnv;
|
|
196
|
+
const envName = this.resolveEnvironmentName(config.project, env);
|
|
197
|
+
const dryRun = flags["dry-run"] ?? false;
|
|
198
|
+
|
|
199
|
+
const envVars = await this.envUtils.parseEnv(root, [`.env.${env}`]);
|
|
200
|
+
const filtered = this.filter.filter(envVars);
|
|
201
|
+
const keys = Object.keys(filtered);
|
|
202
|
+
|
|
203
|
+
if (keys.length === 0) {
|
|
204
|
+
run.end();
|
|
205
|
+
process.stdout.write("\nNo secrets to push.\n\n");
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (dryRun) {
|
|
210
|
+
run.end();
|
|
211
|
+
const c = this.color;
|
|
212
|
+
process.stdout.write(
|
|
213
|
+
`\n${c.set("GREY_LIGHT", "Dry run — environment:")} ${c.set("CYAN", envName)}\n\n`,
|
|
214
|
+
);
|
|
215
|
+
for (const key of keys) {
|
|
216
|
+
process.stdout.write(` ${c.set("GREEN", "+")} ${key}\n`);
|
|
217
|
+
}
|
|
218
|
+
process.stdout.write(
|
|
219
|
+
`\n ${keys.length} secret(s) would be pushed.\n\n`,
|
|
220
|
+
);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const store = this.resolveStore();
|
|
225
|
+
await store.ensureAvailable();
|
|
226
|
+
await store.ensureEnvironment(envName);
|
|
227
|
+
|
|
228
|
+
for (const key of keys) {
|
|
229
|
+
const remoteName = this.filter.toRemoteName(key);
|
|
230
|
+
await run({
|
|
231
|
+
name: `push ${remoteName}`,
|
|
232
|
+
handler: async () => {
|
|
233
|
+
await store.set(envName, remoteName, filtered[key]);
|
|
234
|
+
},
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
run.end();
|
|
239
|
+
process.stdout.write(
|
|
240
|
+
`\n${keys.length} secret(s) pushed to ${envName}.\n`,
|
|
241
|
+
);
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// -----------------------------------------------------------------------
|
|
246
|
+
// Parent command
|
|
247
|
+
// -----------------------------------------------------------------------
|
|
248
|
+
|
|
249
|
+
public readonly secrets = $command({
|
|
250
|
+
name: "secrets",
|
|
251
|
+
aliases: ["sec"],
|
|
252
|
+
description: "Manage secrets in external stores",
|
|
253
|
+
children: [this.list, this.diff, this.apply],
|
|
254
|
+
handler: async ({ help }) => {
|
|
255
|
+
help();
|
|
256
|
+
},
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
// -----------------------------------------------------------------------
|
|
260
|
+
// Helpers
|
|
261
|
+
// -----------------------------------------------------------------------
|
|
262
|
+
|
|
263
|
+
public resolveStore(): SecretStoreProvider {
|
|
264
|
+
const storeName = this.options?.secrets?.store ?? "github";
|
|
265
|
+
switch (storeName) {
|
|
266
|
+
case "github":
|
|
267
|
+
return this.githubStore;
|
|
268
|
+
default:
|
|
269
|
+
throw new AlephaError(
|
|
270
|
+
`Unknown secret store "${storeName}". Available: github`,
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
protected resolveEnvironmentName(project: string, env: string): string {
|
|
276
|
+
const pattern =
|
|
277
|
+
this.options?.secrets?.environmentPattern ?? "{project}-{env}";
|
|
278
|
+
|
|
279
|
+
return pattern
|
|
280
|
+
.replace("{project}", this.naming.slugify(project))
|
|
281
|
+
.replace("{env}", this.naming.slugify(env));
|
|
282
|
+
}
|
|
283
|
+
}
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
type ResolvedPlatformConfig,
|
|
20
20
|
} from "../services/PlatformInspector.ts";
|
|
21
21
|
import { PlatformOrchestrator } from "../services/PlatformOrchestrator.ts";
|
|
22
|
+
import { SecretsCommand } from "./SecretsCommand.ts";
|
|
22
23
|
|
|
23
24
|
export class PlatformCommand {
|
|
24
25
|
protected readonly log = $logger();
|
|
@@ -30,6 +31,7 @@ export class PlatformCommand {
|
|
|
30
31
|
protected readonly viteBuild = $inject(ViteBuildProvider);
|
|
31
32
|
protected readonly color = $inject(ConsoleColorProvider);
|
|
32
33
|
protected readonly envUtils = $inject(EnvUtils);
|
|
34
|
+
protected readonly secretsCommand = $inject(SecretsCommand);
|
|
33
35
|
|
|
34
36
|
/**
|
|
35
37
|
* Common flags for env/app targeting.
|
|
@@ -134,6 +136,15 @@ export class PlatformCommand {
|
|
|
134
136
|
}
|
|
135
137
|
}
|
|
136
138
|
|
|
139
|
+
if (adapterName === "docker" || adapterName === "docker-compose") {
|
|
140
|
+
if (hasDB && !envVars.DATABASE_URL) {
|
|
141
|
+
resources.push({ label: "Postgres", value: "postgres:17-alpine" });
|
|
142
|
+
}
|
|
143
|
+
if (hasBucket && !envVars.S3_ENDPOINT) {
|
|
144
|
+
resources.push({ label: "RustFS", value: "rustfs/rustfs:latest" });
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
137
148
|
const excludedKeys =
|
|
138
149
|
adapterName === "vercel"
|
|
139
150
|
? VercelAdapter.EXCLUDED_SECRET_KEYS
|
|
@@ -609,6 +620,7 @@ export class PlatformCommand {
|
|
|
609
620
|
this.build,
|
|
610
621
|
this.deploy,
|
|
611
622
|
this.migrate,
|
|
623
|
+
this.secretsCommand.secrets,
|
|
612
624
|
],
|
|
613
625
|
handler: async ({ help, root }) => {
|
|
614
626
|
await this.inspector.resolveConfig(root);
|