okengine 0.10.3 → 0.11.1
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/package.json +76 -10
- package/site/content/docs/deployment/docker-swarm.mdx +48 -111
- package/site/content/docs/deployment/docker.mdx +43 -36
- package/site/content/docs/deployment/index.mdx +9 -9
- package/site/content/docs/deployment/kubernetes.mdx +4 -4
- package/site/content/docs/elements/ai.mdx +7 -7
- package/site/content/docs/elements/channel.mdx +9 -7
- package/site/content/docs/elements/clock.mdx +8 -8
- package/site/content/docs/elements/flow.mdx +46 -47
- package/site/content/docs/elements/gate.mdx +6 -5
- package/site/content/docs/elements/signal.mdx +2 -2
- package/site/content/docs/elements/store.mdx +71 -78
- package/site/content/docs/elements/vault.mdx +89 -70
- package/site/content/docs/get-started/basic-usage.mdx +8 -8
- package/site/content/docs/get-started/installation.mdx +36 -36
- package/site/content/docs/get-started/introduction.mdx +11 -0
- package/site/content/docs/get-started/why.mdx +2 -2
- package/site/content/docs/plugins/anonymous.mdx +1 -1
- package/site/content/docs/plugins/magic-link.mdx +11 -11
- package/site/content/docs/plugins/otp.mdx +2 -2
- package/site/content/docs/plugins/passkey.mdx +1 -1
- package/site/content/docs/plugins/two-factor.mdx +1 -1
- package/site/content/docs/plugins/username.mdx +1 -1
- package/site/content/docs/recipes/caddy.mdx +1 -1
- package/site/content/docs/recipes/cockroachdb.mdx +2 -2
- package/site/content/docs/recipes/dragonfly.mdx +1 -1
- package/site/content/docs/recipes/index.mdx +1 -2
- package/site/content/docs/recipes/llama-cpp.mdx +21 -23
- package/site/content/docs/recipes/mailpit.mdx +11 -11
- package/site/content/docs/recipes/meilisearch.mdx +10 -10
- package/site/content/docs/recipes/meta.json +0 -1
- package/site/content/docs/recipes/ollama.mdx +1 -1
- package/site/content/docs/recipes/pgdog.mdx +12 -9
- package/site/content/docs/recipes/postgres.mdx +3 -3
- package/site/content/docs/recipes/redis.mdx +2 -2
- package/site/content/docs/recipes/rustfs.mdx +10 -7
- package/site/content/docs/recipes/sglang.mdx +1 -1
- package/site/content/docs/recipes/supabase-docker.mdx +1 -1
- package/site/content/docs/recipes/timescale.mdx +2 -2
- package/site/content/docs/recipes/valkey.mdx +1 -1
- package/site/content/docs/recipes/vllm.mdx +1 -1
- package/site/content/docs/recipes/yugabytedb.mdx +2 -2
- package/site/content/docs/reference/cli.md +61 -38
- package/site/content/docs/reference/configuration.mdx +145 -70
- package/site/content/docs/reference/environment-variables.mdx +36 -28
- package/site/content/docs/reference/errors.mdx +28 -29
- package/site/content/docs/reference/fx.mdx +11 -4
- package/site/content/docs/reference/i18n.mdx +17 -6
- package/site/content/docs/reference/index.mdx +5 -0
- package/site/content/docs/reference/meta.json +1 -0
- package/site/content/docs/reference/migrating-environments.mdx +158 -0
- package/site/content/docs/reference/plugins.mdx +2 -2
- package/src/auth/gate-auth.test.ts +12 -10
- package/src/cli/ai-setup/ai-setup.test.ts +27 -15
- package/src/cli/ai-setup/apply.ts +111 -15
- package/src/cli/ai-setup/catalog.ts +3 -3
- package/src/cli/ai-setup/index.ts +1 -1
- package/src/cli/ai-setup/prompts.ts +1 -1
- package/src/cli/ai-setup/recommend.test.ts +1 -1
- package/src/cli/ask-seed.test.ts +3 -3
- package/src/cli/build.ts +1 -1
- package/src/cli/db-auto-push.test.ts +6 -3
- package/src/cli/db-auto-push.ts +7 -5
- package/src/cli/db-seed.ts +7 -8
- package/src/cli/db.test.ts +70 -71
- package/src/cli/db.ts +86 -12
- package/src/cli/dev-controller.test.ts +35 -0
- package/src/cli/dev-controller.ts +298 -0
- package/src/cli/dev-controls.ts +11 -65
- package/src/cli/dev-db-push.test.ts +47 -15
- package/src/cli/dev-schema-sync.test.ts +11 -11
- package/src/cli/dev-schema-sync.ts +10 -10
- package/src/cli/dev-session-lock.test.ts +106 -0
- package/src/cli/dev-session-lock.ts +209 -0
- package/src/cli/dev.test.ts +166 -121
- package/src/cli/dev.ts +138 -192
- package/src/cli/doc-staleness.test.ts +3 -6
- package/src/cli/docker-clean.test.ts +33 -1
- package/src/cli/docker-clean.ts +28 -33
- package/src/cli/docker-cli.test.ts +12 -11
- package/src/cli/docker.ts +95 -20
- package/src/cli/doctor.test.ts +40 -0
- package/src/cli/doctor.ts +55 -15
- package/src/cli/drizzle-env.test.ts +11 -13
- package/src/cli/drizzle-env.ts +18 -11
- package/src/cli/ensure-drizzle-config.ts +11 -14
- package/src/cli/hero-meta.test.ts +15 -15
- package/src/cli/hero-meta.ts +10 -9
- package/src/cli/index.ts +36 -6
- package/src/cli/load-config.images.test.ts +16 -12
- package/src/cli/load-config.source.test.ts +50 -0
- package/src/cli/load-config.ts +34 -28
- package/src/cli/meilisearch-local.ts +1 -2
- package/src/cli/mode.ts +7 -58
- package/src/cli/registry.ts +175 -19
- package/src/cli/resolve-dev-sql-env.test.ts +8 -16
- package/src/cli/resolve-dev-sql-env.ts +13 -15
- package/src/cli/safe-defaults.test.ts +28 -10
- package/src/cli/schema.ts +65 -16
- package/src/cli/test.ts +58 -0
- package/src/cli/tui/App.tsx +252 -0
- package/src/cli/tui/DevLive.tsx +116 -0
- package/src/cli/tui/components/ConfirmDialog.tsx +48 -0
- package/src/cli/tui/components/HeaderBar.tsx +67 -0
- package/src/cli/tui/components/LogStream.tsx +47 -0
- package/src/cli/tui/components/PanelCard.tsx +39 -0
- package/src/cli/tui/components/SelectRow.tsx +37 -0
- package/src/cli/tui/components/SlashPalette.tsx +172 -0
- package/src/cli/tui/components/Spinner.tsx +32 -0
- package/src/cli/tui/components/StatusBar.tsx +51 -0
- package/src/cli/tui/components/StatusDot.tsx +37 -0
- package/src/cli/tui/components/TabBar.tsx +49 -0
- package/src/cli/tui/components/Wordmark.tsx +43 -0
- package/src/cli/tui/format.ts +38 -0
- package/src/cli/tui/keys.test.ts +18 -0
- package/src/cli/tui/keys.ts +26 -0
- package/src/cli/tui/launch.test.ts +18 -0
- package/src/cli/tui/launch.ts +57 -0
- package/src/cli/tui/panels/Dashboard.tsx +201 -0
- package/src/cli/tui/panels/Database.tsx +198 -0
- package/src/cli/tui/panels/Dev.tsx +257 -0
- package/src/cli/tui/panels/Docker.tsx +357 -0
- package/src/cli/tui/panels/Navigator.test.ts +22 -0
- package/src/cli/tui/panels/Navigator.tsx +213 -0
- package/src/cli/tui/slash-catalog.test.ts +31 -0
- package/src/cli/tui/slash-catalog.ts +184 -0
- package/src/cli/tui/slash-run.ts +54 -0
- package/src/cli/tui/state/ports.ts +95 -0
- package/src/cli/tui/theme.ts +24 -0
- package/src/cli/vault-cmd.test.ts +402 -0
- package/src/cli/vault-cmd.ts +727 -69
- package/src/cli/vault-secure-input.test.ts +56 -0
- package/src/cli/vault-secure-input.ts +124 -0
- package/src/compiler/effects-infer.ts +7 -0
- package/src/compiler/fixtures/skyport/oke.config.ts +3 -3
- package/src/compiler/fixtures/skyport/src/flows/payments/index.ts +1 -1
- package/src/compiler/fixtures/skyport.expected.json +1 -1
- package/src/compiler-entry.ts +7 -0
- package/src/config/define-config.test.ts +111 -47
- package/src/config/driver-defaults.test.ts +16 -23
- package/src/config/driver-defaults.ts +33 -63
- package/src/config/index.ts +169 -144
- package/src/config/resolve-driver.test.ts +14 -19
- package/src/console/server/app.ts +4 -2
- package/src/console/server/console.test.ts +58 -1
- package/src/console/server/flows.ts +22 -2
- package/src/console/server/index.ts +3 -0
- package/src/console/server/operator-db.test.ts +55 -13
- package/src/console/server/operator-db.ts +305 -263
- package/src/console/server/serve.ts +16 -7
- package/src/console/server/state.ts +31 -9
- package/src/console/server/vault.test.ts +120 -5
- package/src/console/server/vault.ts +208 -12
- package/src/console/ui/dist/assets/{index-D-9KFce5.js → index--Y0Uaz-m.js} +2 -2
- package/src/console/ui/dist/assets/panel-vault-BkZdJPX8.js +1 -0
- package/src/console/ui/dist/assets/style-C3L349iZ.css +3 -0
- package/src/console/ui/dist/index.html +2 -2
- package/src/console/ui/shell/client.ts +16 -0
- package/src/console/ui/shell/panels/vault/VaultPanel.tsx +54 -1
- package/src/console/ui/vault/VaultA11yView.tsx +33 -1
- package/src/console/ui/vault/backend.test.ts +75 -0
- package/src/console/ui/vault/backend.ts +117 -0
- package/src/console/ui/vault/fixture.ts +21 -2
- package/src/console/ui/vault/index.ts +11 -1
- package/src/console/ui/vault/types.ts +26 -0
- package/src/docker/compose.ts +164 -61
- package/src/docker/derive.ts +106 -12
- package/src/docker/docker.test.ts +156 -110
- package/src/docker/helpers.ts +98 -0
- package/src/docker/images-config.test.ts +3 -8
- package/src/docker/index.ts +30 -5
- package/src/docker/recipes/index.ts +0 -3
- package/src/docker/recipes/llama-cpp.ts +4 -4
- package/src/docker/recipes/pgdog.ts +9 -2
- package/src/docker/resources.test.ts +71 -0
- package/src/docker/resources.ts +176 -0
- package/src/docker/stack-id.test.ts +11 -4
- package/src/docker/stack-id.ts +42 -32
- package/src/docker/stack.integration.test.ts +4 -15
- package/src/docker/types.ts +35 -3
- package/src/drivers/ai-ollama.integration.test.ts +2 -2
- package/src/drivers/conformance.test.ts +11 -12
- package/src/drivers/drizzle-dialect.test.ts +0 -4
- package/src/drivers/drizzle-dialect.ts +7 -13
- package/src/drivers/index.ts +24 -7
- package/src/drivers/journal-postgres.test.ts +3 -1
- package/src/drivers/journal-postgres.ts +4 -2
- package/src/drivers/meilisearch.ts +1 -1
- package/src/drivers/pglite.ts +28 -5
- package/src/drivers/types.ts +9 -11
- package/src/drivers/vault-aws-secrets-manager.test.ts +159 -0
- package/src/drivers/vault-aws-secrets-manager.ts +333 -0
- package/src/drivers/vault-builtin.test.ts +110 -0
- package/src/drivers/vault-builtin.ts +184 -0
- package/src/drivers/vault-driver-removal.test.ts +13 -0
- package/src/drivers/vault-managed.test.ts +95 -0
- package/src/drivers/vault-managed.ts +101 -25
- package/src/drivers/vault-types.ts +25 -5
- package/src/elements/ai/runtime.ts +1 -1
- package/src/elements/clock/chaos.test.ts +4 -1
- package/src/elements/clock/durable.ts +57 -4
- package/src/elements/clock.test.ts +13 -14
- package/src/elements/gate/config.ts +13 -3
- package/src/elements/gate/constants.ts +18 -0
- package/src/elements/gate/declare.ts +1 -1
- package/src/elements/gate/strategies.ts +2 -12
- package/src/elements/gate.test.ts +1 -1
- package/src/elements/gate.ts +2 -2
- package/src/elements/store/domain-ddl.test.ts +5 -12
- package/src/elements/store/emit-drizzle.ts +44 -19
- package/src/elements/store/index-boot.test.ts +15 -116
- package/src/elements/store/load-plugin-tables.ts +1 -1
- package/src/elements/store/resource-list-docs.fixture.ts +12 -6
- package/src/elements/store/resource-list-docs.test.ts +64 -44
- package/src/elements/store/resource.test.ts +17 -10
- package/src/elements/store/runtime.ts +9 -12
- package/src/elements/store/schema-decl.test.ts +16 -32
- package/src/elements/store/seed.test.ts +1 -2
- package/src/elements/store/seed.ts +7 -8
- package/src/elements/store/sql-condition.test.ts +2 -2
- package/src/elements/store/sql-session.test.ts +8 -10
- package/src/elements/store/sql-session.ts +10 -2
- package/src/elements/store.test.ts +13 -13
- package/src/elements/vault/audit.ts +233 -0
- package/src/elements/vault/boot-chain.test.ts +78 -0
- package/src/elements/vault/boot-chain.ts +43 -39
- package/src/elements/vault/builtin-adapter.test.ts +479 -0
- package/src/elements/vault/builtin-adapter.ts +1184 -0
- package/src/elements/vault/crypto.test.ts +237 -0
- package/src/elements/vault/crypto.ts +431 -0
- package/src/elements/vault/declare.ts +164 -3
- package/src/elements/vault/errors.ts +56 -0
- package/src/elements/vault/kms-unseal.test.ts +76 -0
- package/src/elements/vault/kms-unseal.ts +181 -0
- package/src/elements/vault/path.ts +90 -0
- package/src/elements/vault/resilience.test.ts +102 -0
- package/src/elements/vault/resilience.ts +107 -0
- package/src/elements/vault/runtime.ts +36 -4
- package/src/elements/vault/security-checklist.test.ts +130 -0
- package/src/elements/vault/storage.ts +448 -0
- package/src/elements/vault/types.ts +288 -0
- package/src/elements/vault/unseal.ts +150 -0
- package/src/elements/vault.test.ts +72 -4
- package/src/elements/vault.ts +91 -2
- package/src/full.ts +248 -0
- package/src/http.ts +41 -0
- package/src/i18n/interpolate-simple.ts +37 -0
- package/src/i18n/messages.ts +51 -4
- package/src/i18n-entry.ts +7 -0
- package/src/index.ts +35 -145
- package/src/journal-entry.ts +20 -0
- package/src/kernel/adopt-barrel-fresh.test.ts +25 -10
- package/src/kernel/app-auth.ts +98 -0
- package/src/kernel/app.ts +77 -110
- package/src/kernel/auto-registry.test.ts +2 -2
- package/src/kernel/boot-bind/ai.test.ts +5 -5
- package/src/kernel/boot-bind/ai.ts +2 -1
- package/src/kernel/boot-bind/channel.test.ts +6 -6
- package/src/kernel/boot-bind/channel.ts +3 -10
- package/src/kernel/boot-bind/clock.ts +2 -2
- package/src/kernel/boot-bind/gate.ts +5 -9
- package/src/kernel/boot-bind/honor-config.test.ts +42 -42
- package/src/kernel/boot-bind/journal.ts +2 -2
- package/src/kernel/boot-bind/store.test.ts +43 -44
- package/src/kernel/boot-bind/store.ts +16 -41
- package/src/kernel/boot-bind/vault.ts +16 -1
- package/src/kernel/boot.test.ts +13 -19
- package/src/kernel/boot.ts +31 -19
- package/src/kernel/budget-entry.ts +1 -1
- package/src/kernel/compensate.test.ts +288 -1
- package/src/kernel/compensate.ts +126 -0
- package/src/kernel/concurrency.test.ts +10 -9
- package/src/kernel/effects-stamping.test.ts +27 -2
- package/src/kernel/element-registries.ts +5 -3
- package/src/kernel/flow.ts +4 -2
- package/src/kernel/fx.test.ts +119 -3
- package/src/kernel/fx.ts +215 -40
- package/src/kernel/index.ts +14 -0
- package/src/kernel/journal.ts +130 -7
- package/src/kernel/pipeline.test.ts +20 -6
- package/src/kernel/redacted.test.ts +35 -0
- package/src/kernel/redacted.ts +24 -2
- package/src/kernel/router/create-default.ts +16 -0
- package/src/kernel/router/create-edge.ts +18 -0
- package/src/kernel/router/create.ts +23 -0
- package/src/kernel/router/index.ts +23 -0
- package/src/kernel/router/linear.ts +88 -0
- package/src/kernel/router/regexp.ts +188 -0
- package/src/kernel/router/smart.ts +120 -0
- package/src/kernel/router/trie.ts +108 -0
- package/src/kernel/router/types.ts +56 -0
- package/src/kernel/router.ts +18 -532
- package/src/kernel-entry.ts +43 -0
- package/src/manifest/fixtures/skyport.excerpt.json +1 -1
- package/src/manifest/fixtures/skyport.manifest.json +1 -1
- package/src/plugins/config-source.test.ts +7 -7
- package/src/release/build-lib.ts +61 -0
- package/src/release/exports.test.ts +4 -2
- package/src/release/exports.ts +30 -4
- package/src/release/measure.ts +101 -22
- package/src/runs/duckdb.ts +7 -2
- package/src/shared/lazy-src.ts +79 -0
- package/src/shared/optional-peer.ts +41 -0
- package/src/term.test.ts +3 -44
- package/src/test/create-test-app.ts +12 -0
- package/src/test/provisions.integration.test.ts +1 -1
- package/src/test/reset-element-registries.ts +2 -0
- package/src/upgrade/codemods.test.ts +7 -20
- package/src/upgrade/codemods.ts +93 -60
- package/site/content/docs/recipes/openbao.mdx +0 -141
- package/src/cli/ask-dev-mode.ts +0 -40
- package/src/cli/dev-mode.test.ts +0 -45
- package/src/cli/dev-mode.ts +0 -78
- package/src/cli/openbao-bootstrap.test.ts +0 -150
- package/src/cli/openbao-bootstrap.ts +0 -321
- package/src/cli/openbao-restart.integration.test.ts +0 -145
- package/src/console/ui/dist/assets/panel-vault-Za1GyJfM.js +0 -1
- package/src/console/ui/dist/assets/style-C8MxEWPd.css +0 -3
- package/src/docker/recipes/openbao.ts +0 -47
- package/src/drivers/libsql.ts +0 -179
- package/src/drivers/sqlite.ts +0 -44
- package/src/drivers/vault-openbao.test.ts +0 -97
- package/src/drivers/vault-openbao.ts +0 -143
|
@@ -12,21 +12,17 @@ import {
|
|
|
12
12
|
runTextIndexConformance,
|
|
13
13
|
} from "./conformance.ts";
|
|
14
14
|
import { fsDriver } from "./fs.ts";
|
|
15
|
-
import { libsqlDriver, libsqlIndexDriver } from "./libsql.ts";
|
|
16
15
|
import { memoryFilesDriver, memoryIndexDriver, memoryKvDriver, memorySqlDriver } from "./memory.ts";
|
|
17
16
|
import { meilisearchDriver } from "./meilisearch.ts";
|
|
18
17
|
import { createMeilisearchFakeFetch } from "./meilisearch.test.ts";
|
|
19
|
-
import { pgliteDriver } from "./pglite.ts";
|
|
18
|
+
import { PGLITE_DEFAULT_DATADIR, pgliteDriver, resolvePgliteDataDir } from "./pglite.ts";
|
|
20
19
|
import { pgvectorDriver } from "./pgvector.ts";
|
|
21
20
|
import { createPostgresFakeClient, postgresDriver } from "./postgres.ts";
|
|
22
21
|
import { createRedisFakeClient, redisDriver } from "./redis.ts";
|
|
23
22
|
import { createS3FakeClient, s3Driver } from "./s3.ts";
|
|
24
|
-
import { sqliteDriver } from "./sqlite.ts";
|
|
25
23
|
|
|
26
24
|
describe("sql conformance", () => {
|
|
27
25
|
test("memory", () => runSqlConformance(memorySqlDriver));
|
|
28
|
-
test("sqlite", () => runSqlConformance(sqliteDriver, { url: ":memory:" }));
|
|
29
|
-
test("libsql", () => runSqlConformance(libsqlDriver, { url: ":memory:" }));
|
|
30
26
|
// pglite cold-starts WASM + extension load — slow disks / CI need > default 5s
|
|
31
27
|
test("pglite", () => runSqlConformance(pgliteDriver, { url: "memory://" }), 15_000);
|
|
32
28
|
test("postgres (fake Bun.SQL client)", () =>
|
|
@@ -35,6 +31,16 @@ describe("sql conformance", () => {
|
|
|
35
31
|
}));
|
|
36
32
|
});
|
|
37
33
|
|
|
34
|
+
describe("pglite dataDir resolution", () => {
|
|
35
|
+
test("memory:// stays in-process; :memory: persists under .oke/pgdata", () => {
|
|
36
|
+
expect(resolvePgliteDataDir("memory://")).toBe("memory");
|
|
37
|
+
expect(resolvePgliteDataDir("memory://suite")).toBe("memory");
|
|
38
|
+
expect(resolvePgliteDataDir(":memory:")).toBe(PGLITE_DEFAULT_DATADIR);
|
|
39
|
+
expect(resolvePgliteDataDir(undefined)).toBe(PGLITE_DEFAULT_DATADIR);
|
|
40
|
+
expect(resolvePgliteDataDir(".oke/custom")).toBe(".oke/custom");
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
38
44
|
describe("kv conformance", () => {
|
|
39
45
|
test("memory", () => runKvConformance(memoryKvDriver));
|
|
40
46
|
test("redis (fake Bun.redis client)", () =>
|
|
@@ -54,7 +60,6 @@ describe("files conformance", () => {
|
|
|
54
60
|
describe("index conformance", () => {
|
|
55
61
|
test("memory", () => runIndexConformance(memoryIndexDriver, { dims: 3 }));
|
|
56
62
|
test("pgvector", () => runIndexConformance(pgvectorDriver, { dims: 3 }));
|
|
57
|
-
test("libsql", () => runIndexConformance(libsqlIndexDriver, { dims: 3 }));
|
|
58
63
|
});
|
|
59
64
|
|
|
60
65
|
describe("text index conformance", () => {
|
|
@@ -70,8 +75,6 @@ describe("protocol naming", () => {
|
|
|
70
75
|
test("driver ids are protocols, never vendors", () => {
|
|
71
76
|
const ids = [
|
|
72
77
|
memorySqlDriver.id,
|
|
73
|
-
sqliteDriver.id,
|
|
74
|
-
libsqlDriver.id,
|
|
75
78
|
pgliteDriver.id,
|
|
76
79
|
postgresDriver.id,
|
|
77
80
|
memoryKvDriver.id,
|
|
@@ -81,13 +84,10 @@ describe("protocol naming", () => {
|
|
|
81
84
|
s3Driver.id,
|
|
82
85
|
memoryIndexDriver.id,
|
|
83
86
|
pgvectorDriver.id,
|
|
84
|
-
libsqlIndexDriver.id,
|
|
85
87
|
meilisearchDriver.id,
|
|
86
88
|
];
|
|
87
89
|
expect(ids).toEqual([
|
|
88
90
|
"memory",
|
|
89
|
-
"sqlite",
|
|
90
|
-
"libsql",
|
|
91
91
|
"pglite",
|
|
92
92
|
"postgres",
|
|
93
93
|
"memory",
|
|
@@ -97,7 +97,6 @@ describe("protocol naming", () => {
|
|
|
97
97
|
"s3",
|
|
98
98
|
"memory",
|
|
99
99
|
"pgvector",
|
|
100
|
-
"libsql",
|
|
101
100
|
"meilisearch",
|
|
102
101
|
]);
|
|
103
102
|
for (const id of ids) {
|
|
@@ -8,17 +8,13 @@ import { drizzleDialectFromSqlDriver, SQL_DRIVER_TO_DRIZZLE_DIALECT } from "./dr
|
|
|
8
8
|
describe("SQL_DRIVER_TO_DRIZZLE_DIALECT", () => {
|
|
9
9
|
test("maps owned SQL drivers", () => {
|
|
10
10
|
expect(SQL_DRIVER_TO_DRIZZLE_DIALECT).toEqual({
|
|
11
|
-
sqlite: "sqlite",
|
|
12
11
|
postgres: "postgresql",
|
|
13
|
-
libsql: "sqlite",
|
|
14
12
|
pglite: "postgresql",
|
|
15
13
|
});
|
|
16
14
|
});
|
|
17
15
|
|
|
18
16
|
test("drizzleDialectFromSqlDriver resolves", () => {
|
|
19
|
-
expect(drizzleDialectFromSqlDriver("sqlite")).toBe("sqlite");
|
|
20
17
|
expect(drizzleDialectFromSqlDriver("postgres")).toBe("postgresql");
|
|
21
|
-
expect(drizzleDialectFromSqlDriver("libsql")).toBe("sqlite");
|
|
22
18
|
expect(drizzleDialectFromSqlDriver("pglite")).toBe("postgresql");
|
|
23
19
|
});
|
|
24
20
|
});
|
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Map OKE `store.sql` driver ids to drizzle-kit dialects.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* `cockroach` · `duckdb`. OKE owns kit-facing SQL drivers `sqlite` /
|
|
7
|
-
* `postgres` / `libsql` / `pglite` only — map those, never infer from
|
|
8
|
-
* connection URLs. `libsql` speaks the sqlite wire dialect; `pglite` speaks
|
|
9
|
-
* postgresql (same dialect as `postgres`, different transport).
|
|
4
|
+
* Owned SQL drivers are Postgres-family only (`postgres` · `pglite`) — both
|
|
5
|
+
* map to kit dialect `postgresql`. Never infer from connection URLs.
|
|
10
6
|
*/
|
|
11
7
|
|
|
12
8
|
import type { StoreDriverId } from "./types.ts";
|
|
13
9
|
|
|
14
|
-
/** drizzle-kit `Dialect` values OKE
|
|
15
|
-
export type OkeDrizzleKitDialect = "
|
|
10
|
+
/** drizzle-kit `Dialect` values OKE emits for owned SQL drivers. */
|
|
11
|
+
export type OkeDrizzleKitDialect = "postgresql";
|
|
16
12
|
|
|
17
13
|
/**
|
|
18
14
|
* Exhaustive map: adding a new SQL id to `StoreDriverId` without updating
|
|
@@ -20,22 +16,20 @@ export type OkeDrizzleKitDialect = "sqlite" | "postgresql";
|
|
|
20
16
|
* dialect months later.
|
|
21
17
|
*/
|
|
22
18
|
export const SQL_DRIVER_TO_DRIZZLE_DIALECT: Record<
|
|
23
|
-
Extract<StoreDriverId, "
|
|
19
|
+
Extract<StoreDriverId, "postgres" | "pglite">,
|
|
24
20
|
OkeDrizzleKitDialect
|
|
25
21
|
> = {
|
|
26
|
-
sqlite: "sqlite",
|
|
27
22
|
postgres: "postgresql",
|
|
28
|
-
libsql: "sqlite",
|
|
29
23
|
pglite: "postgresql",
|
|
30
24
|
};
|
|
31
25
|
|
|
32
26
|
/**
|
|
33
27
|
* Resolve the drizzle-kit dialect for an OKE SQL driver id.
|
|
34
28
|
*
|
|
35
|
-
* @param driverId - Protocol driver id (`
|
|
29
|
+
* @param driverId - Protocol driver id (`postgres` | `pglite`)
|
|
36
30
|
*/
|
|
37
31
|
export function drizzleDialectFromSqlDriver(
|
|
38
|
-
driverId: Extract<StoreDriverId, "
|
|
32
|
+
driverId: Extract<StoreDriverId, "postgres" | "pglite">,
|
|
39
33
|
): OkeDrizzleKitDialect {
|
|
40
34
|
return SQL_DRIVER_TO_DRIZZLE_DIALECT[driverId];
|
|
41
35
|
}
|
package/src/drivers/index.ts
CHANGED
|
@@ -66,8 +66,6 @@ export {
|
|
|
66
66
|
memoryDrivers,
|
|
67
67
|
} from "./memory.ts";
|
|
68
68
|
|
|
69
|
-
export { sqliteDriver, connectSqlite } from "./sqlite.ts";
|
|
70
|
-
|
|
71
69
|
export {
|
|
72
70
|
postgresDriver,
|
|
73
71
|
connectPostgres,
|
|
@@ -86,8 +84,6 @@ export { s3Driver, openS3Bucket, createS3FakeClient } from "./s3.ts";
|
|
|
86
84
|
|
|
87
85
|
export { pgvectorDriver, openPgvectorIndex } from "./pgvector.ts";
|
|
88
86
|
|
|
89
|
-
export { libsqlDriver, connectLibsql, libsqlIndexDriver, openLibsqlIndex } from "./libsql.ts";
|
|
90
|
-
|
|
91
87
|
export {
|
|
92
88
|
meilisearchDriver,
|
|
93
89
|
openMeilisearchIndex,
|
|
@@ -95,7 +91,12 @@ export {
|
|
|
95
91
|
type MeilisearchIndexOptions,
|
|
96
92
|
} from "./meilisearch.ts";
|
|
97
93
|
|
|
98
|
-
export {
|
|
94
|
+
export {
|
|
95
|
+
pgliteDriver,
|
|
96
|
+
connectPglite,
|
|
97
|
+
PGLITE_DEFAULT_DATADIR,
|
|
98
|
+
resolvePgliteDataDir,
|
|
99
|
+
} from "./pglite.ts";
|
|
99
100
|
|
|
100
101
|
export { memorySignalDriver, openMemorySignal } from "./signal-memory.ts";
|
|
101
102
|
|
|
@@ -139,8 +140,24 @@ export type { VaultDriverId, VaultOpenOptions, VaultBag, VaultDriver } from "./v
|
|
|
139
140
|
|
|
140
141
|
export { memoryVaultDriver } from "./vault-memory.ts";
|
|
141
142
|
export { envVaultDriver } from "./vault-env.ts";
|
|
142
|
-
export {
|
|
143
|
-
|
|
143
|
+
export {
|
|
144
|
+
builtinVaultDriver,
|
|
145
|
+
openBuiltinVaultAdapter,
|
|
146
|
+
VAULT_MASTER_KEY_ENV,
|
|
147
|
+
type OpenBuiltinVaultOptions,
|
|
148
|
+
type OpenedBuiltinVault,
|
|
149
|
+
} from "./vault-builtin.ts";
|
|
150
|
+
export {
|
|
151
|
+
managedVaultDriver,
|
|
152
|
+
createManagedVaultBag,
|
|
153
|
+
type ManagedVaultOptions,
|
|
154
|
+
type ManagedVaultProviderId,
|
|
155
|
+
} from "./vault-managed.ts";
|
|
156
|
+
export {
|
|
157
|
+
openAwsSecretsManagerBag,
|
|
158
|
+
type AwsSecretsManagerClient,
|
|
159
|
+
type OpenAwsSecretsManagerOptions,
|
|
160
|
+
} from "./vault-aws-secrets-manager.ts";
|
|
144
161
|
|
|
145
162
|
export type {
|
|
146
163
|
ChannelDriverId,
|
|
@@ -142,18 +142,20 @@ describe("postgres JournalStore (fake)", () => {
|
|
|
142
142
|
await store.close();
|
|
143
143
|
});
|
|
144
144
|
|
|
145
|
-
test("listOrphans: running/sleeping without a live lease; never completed", async () => {
|
|
145
|
+
test("listOrphans: running/sleeping/compensating without a live lease; never completed", async () => {
|
|
146
146
|
const store = await createPostgresJournalStore({ sql: createPostgresJournalFake() });
|
|
147
147
|
await store.put(seedRun({ id: "running-unlocked" }));
|
|
148
148
|
await store.put(seedRun({ id: "running-expired", lockedBy: "dead", leaseExpiresAt: 10 }));
|
|
149
149
|
await store.put(seedRun({ id: "running-live", lockedBy: "alive", leaseExpiresAt: 9_000 }));
|
|
150
150
|
await store.put(seedRun({ id: "sleeping-future", status: "sleeping", wakeAt: 99_000 }));
|
|
151
|
+
await store.put(seedRun({ id: "compensating-open", status: "compensating" }));
|
|
151
152
|
await store.put(seedRun({ id: "done", status: "completed" }));
|
|
152
153
|
|
|
153
154
|
const orphans = (await store.listOrphans(1_000)).map((r) => r.id);
|
|
154
155
|
expect(orphans).toContain("running-unlocked");
|
|
155
156
|
expect(orphans).toContain("running-expired");
|
|
156
157
|
expect(orphans).toContain("sleeping-future");
|
|
158
|
+
expect(orphans).toContain("compensating-open");
|
|
157
159
|
expect(orphans).not.toContain("running-live");
|
|
158
160
|
expect(orphans).not.toContain("done");
|
|
159
161
|
await store.close();
|
|
@@ -60,7 +60,7 @@ const CLAIM_LEASE_SQL = `SELECT * FROM oke_journal_runs WHERE id=? AND ((locked_
|
|
|
60
60
|
const CLAIM_DUE_SQL = `SELECT * FROM oke_journal_runs WHERE status='sleeping' AND wake_at<=? AND ((locked_by IS NULL) OR (lease_expires_at IS NOT NULL AND lease_expires_at<=?)) ORDER BY wake_at ASC LIMIT 1 FOR UPDATE SKIP LOCKED`;
|
|
61
61
|
|
|
62
62
|
/** Boot-time orphan discovery: running/sleeping runs with no live lease. */
|
|
63
|
-
const ORPHANS_SQL = `SELECT * FROM oke_journal_runs WHERE (status='running' OR status='sleeping') AND ((locked_by IS NULL) OR (lease_expires_at IS NOT NULL AND lease_expires_at<=?))`;
|
|
63
|
+
const ORPHANS_SQL = `SELECT * FROM oke_journal_runs WHERE (status='running' OR status='sleeping' OR status='compensating') AND ((locked_by IS NULL) OR (lease_expires_at IS NOT NULL AND lease_expires_at<=?))`;
|
|
64
64
|
|
|
65
65
|
const UPDATE_LEASE_SQL = `UPDATE oke_journal_runs SET locked_by = ?, lease_expires_at = ? WHERE id = ?`;
|
|
66
66
|
|
|
@@ -284,7 +284,9 @@ export function createPostgresJournalFake(): PostgresJournalSql & {
|
|
|
284
284
|
const cutoff = Number(params[0]);
|
|
285
285
|
return state.rows
|
|
286
286
|
.filter(
|
|
287
|
-
(r) =>
|
|
287
|
+
(r) =>
|
|
288
|
+
(r.status === "running" || r.status === "sleeping" || r.status === "compensating") &&
|
|
289
|
+
noLiveLease(r, cutoff),
|
|
288
290
|
)
|
|
289
291
|
.map((r) => ({ ...r }));
|
|
290
292
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `meilisearch` index driver — full-text search over the Meilisearch HTTP API.
|
|
3
3
|
*
|
|
4
|
-
* Product-as-protocol id (same pattern as `
|
|
4
|
+
* Product-as-protocol id (same pattern as `pgvector`); the image
|
|
5
5
|
* pin lives in `images["store.index"]` (e.g. `getmeili/meilisearch`). This is
|
|
6
6
|
* a genuinely different capability from the vector ANN drivers — typo-tolerant
|
|
7
7
|
* / faceted full-text relevance, not cosine similarity.
|
package/src/drivers/pglite.ts
CHANGED
|
@@ -7,9 +7,8 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Honest latency trade-off (measured on `@electric-sql/pglite@0.5.4`): first
|
|
9
9
|
* init ~900 ms one-time (WASM instantiation); reopen of an existing datadir
|
|
10
|
-
* ~44 ms; warm CRUD ~45 ms
|
|
11
|
-
* `
|
|
12
|
-
* latency-competitive default. `local` stays on `sqlite`.
|
|
10
|
+
* ~44 ms; warm CRUD ~45 ms. Default for `env: "test"` (`memory://`);
|
|
11
|
+
* `dev`/`prod` use real Postgres via Docker.
|
|
13
12
|
*/
|
|
14
13
|
|
|
15
14
|
import { toPostgresParams } from "./postgres.ts";
|
|
@@ -39,6 +38,24 @@ async function loadPgliteVector(): Promise<PgliteVectorModule> {
|
|
|
39
38
|
}
|
|
40
39
|
}
|
|
41
40
|
|
|
41
|
+
/** Default on-disk PGlite datadir (under the project `.oke/` tree). */
|
|
42
|
+
export const PGLITE_DEFAULT_DATADIR = ".oke/pgdata";
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Resolve a PGlite URL to either in-memory (`memory://…`) or an on-disk datadir.
|
|
46
|
+
*
|
|
47
|
+
* SQLite's `":memory:"` is **not** in-memory for PGlite — it would create a
|
|
48
|
+
* literal `./:memory:` folder. Map that legacy token to {@link PGLITE_DEFAULT_DATADIR}.
|
|
49
|
+
*
|
|
50
|
+
* @param url - Raw connect URL / path
|
|
51
|
+
*/
|
|
52
|
+
export function resolvePgliteDataDir(url: string | undefined): string | "memory" {
|
|
53
|
+
const raw = url && url.length > 0 ? url : PGLITE_DEFAULT_DATADIR;
|
|
54
|
+
if (raw.startsWith("memory://")) return "memory";
|
|
55
|
+
if (raw === ":memory:") return PGLITE_DEFAULT_DATADIR;
|
|
56
|
+
return raw;
|
|
57
|
+
}
|
|
58
|
+
|
|
42
59
|
/**
|
|
43
60
|
* Open a PGlite connection implementing {@link SqlConnection}.
|
|
44
61
|
*
|
|
@@ -52,8 +69,14 @@ export async function connectPglite(options: SqlConnectOptions = {}): Promise<Sq
|
|
|
52
69
|
const role = options.role ?? "primary";
|
|
53
70
|
const { PGlite } = await loadPglite();
|
|
54
71
|
const { vector } = await loadPgliteVector();
|
|
55
|
-
const
|
|
56
|
-
|
|
72
|
+
const resolved = resolvePgliteDataDir(options.url);
|
|
73
|
+
// `memory://…` must be a fresh in-memory instance every connect — passing the
|
|
74
|
+
// string as dataDir is not reliably isolated across boots (IF NOT EXISTS then
|
|
75
|
+
// keeps a prior INTEGER column after we switch DDL to BIGINT).
|
|
76
|
+
const db =
|
|
77
|
+
resolved === "memory"
|
|
78
|
+
? await PGlite.create({ extensions: { vector } })
|
|
79
|
+
: await PGlite.create(resolved, { extensions: { vector } });
|
|
57
80
|
return {
|
|
58
81
|
driverId: "pglite",
|
|
59
82
|
role,
|
package/src/drivers/types.ts
CHANGED
|
@@ -9,9 +9,7 @@ import type { ColumnClassification, StoreFacet } from "../manifest/types.ts";
|
|
|
9
9
|
|
|
10
10
|
/** Protocol ids for store drivers in scope. */
|
|
11
11
|
export type StoreDriverId =
|
|
12
|
-
| "sqlite"
|
|
13
12
|
| "postgres"
|
|
14
|
-
| "libsql"
|
|
15
13
|
| "pglite"
|
|
16
14
|
| "memory"
|
|
17
15
|
| "redis"
|
|
@@ -31,14 +29,14 @@ export type SqlRow = Record<string, unknown>;
|
|
|
31
29
|
|
|
32
30
|
/** Options when opening a SQL connection. */
|
|
33
31
|
export interface SqlConnectOptions {
|
|
34
|
-
/** Connection URL or path (
|
|
32
|
+
/** Connection URL or path (`memory://`, `.oke/pgdata`, `postgres://…`). */
|
|
35
33
|
readonly url?: string;
|
|
36
34
|
/** Explicit role (defaults to primary). */
|
|
37
35
|
readonly role?: SqlRole;
|
|
38
|
-
/** Pool / open hint — ignored by memory
|
|
36
|
+
/** Pool / open hint — ignored by memory drivers. */
|
|
39
37
|
readonly pool?: { readonly max?: number };
|
|
40
38
|
/**
|
|
41
|
-
* Injected client for tests (Bun.SQL-compatible query fn
|
|
39
|
+
* Injected client for tests (Bun.SQL-compatible query fn).
|
|
42
40
|
* Production code omits this and binds the native client.
|
|
43
41
|
*/
|
|
44
42
|
readonly client?: unknown;
|
|
@@ -47,7 +45,7 @@ export interface SqlConnectOptions {
|
|
|
47
45
|
/** Low-level SQL connection used by every sql driver. */
|
|
48
46
|
export interface SqlConnection {
|
|
49
47
|
/** Protocol driver id. */
|
|
50
|
-
readonly driverId: "
|
|
48
|
+
readonly driverId: "postgres" | "pglite" | "memory";
|
|
51
49
|
/** Primary vs replica. */
|
|
52
50
|
readonly role: SqlRole;
|
|
53
51
|
/**
|
|
@@ -71,7 +69,7 @@ export interface SqlConnection {
|
|
|
71
69
|
/** SQL driver factory. */
|
|
72
70
|
export interface SqlDriver {
|
|
73
71
|
/** Protocol id. */
|
|
74
|
-
readonly id: "
|
|
72
|
+
readonly id: "postgres" | "pglite" | "memory";
|
|
75
73
|
/** Facet this driver serves. */
|
|
76
74
|
readonly facet: "sql";
|
|
77
75
|
/**
|
|
@@ -262,7 +260,7 @@ export interface IndexHit {
|
|
|
262
260
|
|
|
263
261
|
/** Vector (ANN) index handle. */
|
|
264
262
|
export interface VectorIndexStore {
|
|
265
|
-
readonly driverId: "memory" | "pgvector"
|
|
263
|
+
readonly driverId: "memory" | "pgvector";
|
|
266
264
|
/**
|
|
267
265
|
* Upsert a vector.
|
|
268
266
|
*
|
|
@@ -356,7 +354,7 @@ export interface IndexOpenOptions {
|
|
|
356
354
|
|
|
357
355
|
/** Vector index driver factory. */
|
|
358
356
|
export interface VectorIndexDriver {
|
|
359
|
-
readonly id: "memory" | "pgvector"
|
|
357
|
+
readonly id: "memory" | "pgvector";
|
|
360
358
|
readonly facet: "index";
|
|
361
359
|
/**
|
|
362
360
|
* Open a vector index.
|
|
@@ -384,8 +382,8 @@ export type IndexDriver = VectorIndexDriver | TextIndexDriver;
|
|
|
384
382
|
/** True when the index driver shares the sql facet's engine (never memory). */
|
|
385
383
|
export function indexDriverNeedsSql(
|
|
386
384
|
driver: IndexDriver,
|
|
387
|
-
): driver is VectorIndexDriver & { id: "pgvector"
|
|
388
|
-
return driver.id === "pgvector"
|
|
385
|
+
): driver is VectorIndexDriver & { id: "pgvector" } {
|
|
386
|
+
return driver.id === "pgvector";
|
|
389
387
|
}
|
|
390
388
|
|
|
391
389
|
/** Union of all store drivers. */
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AWS Secrets Manager bag — snapshot reads, write-through, fail-loud, peer gap.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { describe, expect, test } from "bun:test";
|
|
6
|
+
import { isVaultError } from "../elements/vault/errors.ts";
|
|
7
|
+
import {
|
|
8
|
+
openAwsSecretsManagerBag,
|
|
9
|
+
type AwsSecretsManagerClient,
|
|
10
|
+
} from "./vault-aws-secrets-manager.ts";
|
|
11
|
+
|
|
12
|
+
/** One recorded call against the fake API. */
|
|
13
|
+
interface Call {
|
|
14
|
+
readonly op: "list" | "get" | "put" | "remove";
|
|
15
|
+
readonly name?: string;
|
|
16
|
+
readonly value?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Fake API options — which operations should reject, and how. */
|
|
20
|
+
interface FakeOptions {
|
|
21
|
+
readonly listError?: Error;
|
|
22
|
+
readonly getError?: Error;
|
|
23
|
+
readonly putError?: Error;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** In-memory stand-in for the SDK-backed client. */
|
|
27
|
+
function fakeClient(
|
|
28
|
+
seed: Record<string, string>,
|
|
29
|
+
calls: Call[],
|
|
30
|
+
options: FakeOptions = {},
|
|
31
|
+
): AwsSecretsManagerClient {
|
|
32
|
+
const store = new Map(Object.entries(seed));
|
|
33
|
+
return {
|
|
34
|
+
async list() {
|
|
35
|
+
calls.push({ op: "list" });
|
|
36
|
+
if (options.listError) throw options.listError;
|
|
37
|
+
return [...store.keys()];
|
|
38
|
+
},
|
|
39
|
+
async get(name) {
|
|
40
|
+
calls.push({ op: "get", name });
|
|
41
|
+
if (options.getError) throw options.getError;
|
|
42
|
+
return store.get(name);
|
|
43
|
+
},
|
|
44
|
+
async put(name, value) {
|
|
45
|
+
calls.push({ op: "put", name, value });
|
|
46
|
+
if (options.putError) throw options.putError;
|
|
47
|
+
store.set(name, value);
|
|
48
|
+
},
|
|
49
|
+
async remove(name) {
|
|
50
|
+
calls.push({ op: "remove", name });
|
|
51
|
+
store.delete(name);
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
describe("aws secrets manager vault bag", () => {
|
|
57
|
+
test("list + get snapshots every secret", async () => {
|
|
58
|
+
const calls: Call[] = [];
|
|
59
|
+
const bag = await openAwsSecretsManagerBag({
|
|
60
|
+
client: fakeClient({ STRIPE_KEY: "sk_live", DATABASE_URL: "postgres://x" }, calls),
|
|
61
|
+
});
|
|
62
|
+
expect([...bag.names()].sort()).toEqual(["DATABASE_URL", "STRIPE_KEY"]);
|
|
63
|
+
expect(bag.get("STRIPE_KEY")).toBe("sk_live");
|
|
64
|
+
expect(calls.filter((c) => c.op === "get")).toHaveLength(2);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test("denied list falls back to the declared names", async () => {
|
|
68
|
+
const calls: Call[] = [];
|
|
69
|
+
const denied = new Error("denied");
|
|
70
|
+
denied.name = "AccessDeniedException";
|
|
71
|
+
const bag = await openAwsSecretsManagerBag({
|
|
72
|
+
secrets: { STRIPE_KEY: "seed" },
|
|
73
|
+
client: fakeClient({ STRIPE_KEY: "sk_live", OTHER: "nope" }, calls, { listError: denied }),
|
|
74
|
+
});
|
|
75
|
+
expect(bag.names()).toEqual(["STRIPE_KEY"]);
|
|
76
|
+
expect(bag.get("STRIPE_KEY")).toBe("sk_live");
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test("denied list with no declared names fails loud", async () => {
|
|
80
|
+
const denied = new Error("denied");
|
|
81
|
+
denied.name = "AccessDeniedException";
|
|
82
|
+
let failed: unknown;
|
|
83
|
+
try {
|
|
84
|
+
await openAwsSecretsManagerBag({
|
|
85
|
+
client: fakeClient({}, [], { listError: denied }),
|
|
86
|
+
});
|
|
87
|
+
} catch (error) {
|
|
88
|
+
failed = error;
|
|
89
|
+
}
|
|
90
|
+
expect(isVaultError(failed, "PERMISSION_DENIED")).toBe(true);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test("a failing read is fatal, never a silently empty bag", async () => {
|
|
94
|
+
let failed: unknown;
|
|
95
|
+
try {
|
|
96
|
+
await openAwsSecretsManagerBag({
|
|
97
|
+
client: fakeClient({ A: "1" }, [], { getError: new Error("boom") }),
|
|
98
|
+
});
|
|
99
|
+
} catch (error) {
|
|
100
|
+
failed = error;
|
|
101
|
+
}
|
|
102
|
+
expect(isVaultError(failed, "BACKEND_ERROR")).toBe(true);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
test("the authored message never carries the SDK error text", async () => {
|
|
106
|
+
let failed: unknown;
|
|
107
|
+
try {
|
|
108
|
+
await openAwsSecretsManagerBag({
|
|
109
|
+
client: fakeClient({ A: "1" }, [], { getError: new Error("SecretString=sk_live_leak") }),
|
|
110
|
+
});
|
|
111
|
+
} catch (error) {
|
|
112
|
+
failed = error;
|
|
113
|
+
}
|
|
114
|
+
expect((failed as Error).message).not.toContain("sk_live_leak");
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test("set writes through and close settles it", async () => {
|
|
118
|
+
const calls: Call[] = [];
|
|
119
|
+
const bag = await openAwsSecretsManagerBag({ client: fakeClient({ A: "1" }, calls) });
|
|
120
|
+
bag.set?.("A", "2");
|
|
121
|
+
expect(bag.get("A")).toBe("2");
|
|
122
|
+
await bag.close?.();
|
|
123
|
+
expect(calls).toContainEqual({ op: "put", name: "A", value: "2" });
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test("delete removes locally and remotely", async () => {
|
|
127
|
+
const calls: Call[] = [];
|
|
128
|
+
const bag = await openAwsSecretsManagerBag({ client: fakeClient({ A: "1" }, calls) });
|
|
129
|
+
expect(bag.delete?.("A")).toBe(true);
|
|
130
|
+
expect(bag.get("A")).toBeUndefined();
|
|
131
|
+
await bag.close?.();
|
|
132
|
+
expect(calls).toContainEqual({ op: "remove", name: "A" });
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test("a lost write surfaces at close instead of vanishing", async () => {
|
|
136
|
+
const bag = await openAwsSecretsManagerBag({
|
|
137
|
+
client: fakeClient({ A: "1" }, [], { putError: new Error("throttled") }),
|
|
138
|
+
});
|
|
139
|
+
bag.set?.("A", "2");
|
|
140
|
+
let failed: unknown;
|
|
141
|
+
try {
|
|
142
|
+
await bag.close?.();
|
|
143
|
+
} catch (error) {
|
|
144
|
+
failed = error;
|
|
145
|
+
}
|
|
146
|
+
expect(isVaultError(failed, "BACKEND_ERROR")).toBe(true);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test("missing optional peer reports the install command", async () => {
|
|
150
|
+
let failed: unknown;
|
|
151
|
+
try {
|
|
152
|
+
await openAwsSecretsManagerBag({ region: "us-east-1" });
|
|
153
|
+
} catch (error) {
|
|
154
|
+
failed = error;
|
|
155
|
+
}
|
|
156
|
+
expect(isVaultError(failed, "MISSING_PEER")).toBe(true);
|
|
157
|
+
expect((failed as Error).message).toContain("@aws-sdk/client-secrets-manager");
|
|
158
|
+
});
|
|
159
|
+
});
|