okengine 0.10.2 → 0.11.0
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/ai/mcp.mdx +0 -1
- 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 -13
- package/site/content/docs/elements/channel.mdx +9 -13
- package/site/content/docs/elements/clock.mdx +8 -14
- package/site/content/docs/elements/flow.mdx +46 -54
- package/site/content/docs/elements/gate.mdx +6 -11
- package/site/content/docs/elements/signal.mdx +2 -8
- package/site/content/docs/elements/store.mdx +79 -93
- package/site/content/docs/elements/vault.mdx +89 -76
- package/site/content/docs/get-started/basic-usage.mdx +8 -14
- 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 +3 -4
- package/site/content/docs/index.mdx +0 -1
- package/site/content/docs/meta.json +0 -1
- 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 +14 -7
- 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 +30 -16
- 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 +8 -9
- 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 +246 -114
- package/src/cli/dev.ts +153 -205
- 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 +142 -9
- 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 +44 -10
- package/src/cli/load-config.source.test.ts +50 -0
- package/src/cli/load-config.ts +35 -29
- 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 +29 -11
- 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/extract.ts +12 -0
- package/src/compiler/fixtures/skyport/oke.config.ts +7 -5
- package/src/compiler/fixtures/skyport/src/flows/payments/index.ts +1 -1
- package/src/compiler/fixtures/skyport.expected.json +1 -1
- package/src/compiler/generate-adopt.ts +27 -1
- package/src/compiler-entry.ts +7 -0
- package/src/config/define-config.test.ts +111 -47
- package/src/config/driver-defaults.test.ts +115 -0
- package/src/config/driver-defaults.ts +156 -0
- package/src/config/index.ts +246 -131
- 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 +163 -0
- 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/constants.ts +18 -0
- 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.ts +40 -42
- 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 +5 -4
- package/src/kernel/boot-bind/clock.ts +5 -5
- package/src/kernel/boot-bind/gate.ts +6 -7
- package/src/kernel/boot-bind/honor-config.test.ts +42 -42
- package/src/kernel/boot-bind/journal.ts +5 -5
- package/src/kernel/boot-bind/signal.ts +3 -1
- package/src/kernel/boot-bind/store.test.ts +55 -37
- package/src/kernel/boot-bind/store.ts +24 -34
- package/src/kernel/boot-bind/vault.ts +19 -4
- package/src/kernel/boot.test.ts +12 -4
- 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 +58 -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/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/console/access.mdx +0 -29
- package/site/content/docs/console/ai.mdx +0 -35
- package/site/content/docs/console/architecture.mdx +0 -35
- package/site/content/docs/console/channels.mdx +0 -37
- package/site/content/docs/console/clock.mdx +0 -51
- package/site/content/docs/console/flows.mdx +0 -31
- package/site/content/docs/console/gates.mdx +0 -73
- package/site/content/docs/console/index.mdx +0 -54
- package/site/content/docs/console/manifest-diff.mdx +0 -34
- package/site/content/docs/console/meta.json +0 -24
- package/site/content/docs/console/overview.mdx +0 -40
- package/site/content/docs/console/plugins.mdx +0 -41
- package/site/content/docs/console/privacy.mdx +0 -32
- package/site/content/docs/console/runs.mdx +0 -50
- package/site/content/docs/console/signals.mdx +0 -40
- package/site/content/docs/console/store.mdx +0 -32
- package/site/content/docs/console/tenancy.mdx +0 -32
- package/site/content/docs/console/traces.mdx +0 -38
- package/site/content/docs/console/vault.mdx +0 -41
- 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
package/src/docker/stack-id.ts
CHANGED
|
@@ -131,9 +131,6 @@ export const STACK_CONTROL_KEYS = [
|
|
|
131
131
|
"OKE_AI_CTX_SIZE",
|
|
132
132
|
"OKE_PROXY_HOST",
|
|
133
133
|
"OKE_PROXY_ACME_EMAIL",
|
|
134
|
-
// OpenBao app token — minted by bootstrap, must survive `writeDerivedFiles`.
|
|
135
|
-
"OKE_VAULT_TOKEN",
|
|
136
|
-
"OKE_VAULT_MOUNT",
|
|
137
134
|
] as const;
|
|
138
135
|
|
|
139
136
|
/**
|
|
@@ -176,9 +173,6 @@ export async function loadExistingStackCredentials(
|
|
|
176
173
|
/**
|
|
177
174
|
* Load optional controls from `docker/.env.docker` when present.
|
|
178
175
|
*
|
|
179
|
-
* Falls back to `.oke/openbao/app.token` for `OKE_VAULT_TOKEN` when the env
|
|
180
|
-
* file was regenerated without the bootstrap overlay (per-project token).
|
|
181
|
-
*
|
|
182
176
|
* @param cwd - Project root
|
|
183
177
|
*/
|
|
184
178
|
export async function loadExistingStackControls(
|
|
@@ -192,31 +186,17 @@ export async function loadExistingStackControls(
|
|
|
192
186
|
controls = parseStackControls(await file.text());
|
|
193
187
|
break;
|
|
194
188
|
}
|
|
195
|
-
// create-oke / `oke ai setup` write the chosen model into `.env.local
|
|
196
|
-
//
|
|
197
|
-
//
|
|
189
|
+
// create-oke / `oke ai setup` write the chosen model into `.env.local` as a
|
|
190
|
+
// commented hint (active would shadow `docker/.env.docker`). Seed active or
|
|
191
|
+
// commented `OKE_AI_MODEL` on first docker boot so `LLAMA_ARG_DOCKER_REPO`
|
|
192
|
+
// is not stuck on the recipe default (`granite3.3:2b`).
|
|
198
193
|
if (!controls.OKE_AI_MODEL) {
|
|
199
194
|
const localEnv = Bun.file(resolve(cwd, ".env.local"));
|
|
200
195
|
if (await localEnv.exists()) {
|
|
201
|
-
const model =
|
|
202
|
-
.get("OKE_AI_MODEL")
|
|
203
|
-
?.trim();
|
|
196
|
+
const model = readEnvAssignment(await localEnv.text(), "OKE_AI_MODEL");
|
|
204
197
|
if (model) controls = { ...controls, OKE_AI_MODEL: model };
|
|
205
198
|
}
|
|
206
199
|
}
|
|
207
|
-
if (!controls.OKE_VAULT_TOKEN) {
|
|
208
|
-
const tokenFile = Bun.file(resolve(cwd, ".oke", "openbao", "app.token"));
|
|
209
|
-
if (await tokenFile.exists()) {
|
|
210
|
-
const token = (await tokenFile.text()).trim();
|
|
211
|
-
if (token) {
|
|
212
|
-
controls = {
|
|
213
|
-
...controls,
|
|
214
|
-
OKE_VAULT_TOKEN: token,
|
|
215
|
-
OKE_VAULT_MOUNT: controls.OKE_VAULT_MOUNT ?? "secret",
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
200
|
return Object.keys(controls).length > 0 ? controls : undefined;
|
|
221
201
|
}
|
|
222
202
|
|
|
@@ -228,14 +208,44 @@ function parseDotenv(text: string): Map<string, string> {
|
|
|
228
208
|
const eq = trimmed.indexOf("=");
|
|
229
209
|
if (eq <= 0) continue;
|
|
230
210
|
const key = trimmed.slice(0, eq);
|
|
231
|
-
|
|
232
|
-
if (
|
|
233
|
-
(value.startsWith('"') && value.endsWith('"')) ||
|
|
234
|
-
(value.startsWith("'") && value.endsWith("'"))
|
|
235
|
-
) {
|
|
236
|
-
value = value.slice(1, -1);
|
|
237
|
-
}
|
|
211
|
+
const value = unquoteEnvValue(trimmed.slice(eq + 1));
|
|
238
212
|
map.set(key, value);
|
|
239
213
|
}
|
|
240
214
|
return map;
|
|
241
215
|
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Read `KEY=value` from dotenv text — active line wins; otherwise the last
|
|
219
|
+
* `# KEY=value` hint (create-oke / `oke ai setup` leave AI stack keys commented).
|
|
220
|
+
*
|
|
221
|
+
* @param text - Dotenv contents
|
|
222
|
+
* @param key - Variable name
|
|
223
|
+
*/
|
|
224
|
+
function readEnvAssignment(text: string, key: string): string | undefined {
|
|
225
|
+
const active = parseDotenv(text).get(key)?.trim();
|
|
226
|
+
if (active) return active;
|
|
227
|
+
let hinted: string | undefined;
|
|
228
|
+
const prefix = `# ${key}=`;
|
|
229
|
+
const altPrefix = `#${key}=`;
|
|
230
|
+
for (const line of text.split("\n")) {
|
|
231
|
+
const trimmed = line.trim();
|
|
232
|
+
if (trimmed.startsWith(prefix)) {
|
|
233
|
+
hinted = unquoteEnvValue(trimmed.slice(prefix.length));
|
|
234
|
+
} else if (trimmed.startsWith(altPrefix)) {
|
|
235
|
+
hinted = unquoteEnvValue(trimmed.slice(altPrefix.length));
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
const value = hinted?.trim();
|
|
239
|
+
return value || undefined;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function unquoteEnvValue(raw: string): string {
|
|
243
|
+
let value = raw;
|
|
244
|
+
if (
|
|
245
|
+
(value.startsWith('"') && value.endsWith('"')) ||
|
|
246
|
+
(value.startsWith("'") && value.endsWith("'"))
|
|
247
|
+
) {
|
|
248
|
+
value = value.slice(1, -1);
|
|
249
|
+
}
|
|
250
|
+
return value;
|
|
251
|
+
}
|
|
@@ -55,8 +55,8 @@ describe("oke dev --docker postgres integration", () => {
|
|
|
55
55
|
writeStackEnv: true,
|
|
56
56
|
});
|
|
57
57
|
|
|
58
|
-
// Infra-only:
|
|
59
|
-
const composeFiles = ["compose.yml"
|
|
58
|
+
// Infra-only: single docker-compose.yml (no app build).
|
|
59
|
+
const composeFiles = ["docker-compose.yml"];
|
|
60
60
|
const up = Bun.spawn(
|
|
61
61
|
[
|
|
62
62
|
"docker",
|
|
@@ -122,24 +122,13 @@ describe("oke dev --docker postgres integration", () => {
|
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
// Prove credentials live in docker/.env.docker, not YAML.
|
|
125
|
-
const yml = await Bun.file(join(dockerDir, "compose.
|
|
125
|
+
const yml = await Bun.file(join(dockerDir, "docker-compose.yml")).text();
|
|
126
126
|
expect(yml).not.toContain("stack-integration-pass");
|
|
127
127
|
expect(formatStackEnv(derived.stackEnv)).toContain("stack-integration-pass");
|
|
128
128
|
expect(await Bun.file(join(dockerDir, ".env.docker")).exists()).toBe(true);
|
|
129
129
|
} finally {
|
|
130
130
|
await Bun.spawn(
|
|
131
|
-
[
|
|
132
|
-
"docker",
|
|
133
|
-
"compose",
|
|
134
|
-
"-p",
|
|
135
|
-
project,
|
|
136
|
-
"-f",
|
|
137
|
-
"compose.yml",
|
|
138
|
-
"-f",
|
|
139
|
-
"compose.store.sql.yml",
|
|
140
|
-
"down",
|
|
141
|
-
"-v",
|
|
142
|
-
],
|
|
131
|
+
["docker", "compose", "-p", project, "-f", "docker-compose.yml", "down", "-v"],
|
|
143
132
|
{ cwd: dockerDir, stdout: "pipe", stderr: "pipe" },
|
|
144
133
|
).exited.catch(() => {});
|
|
145
134
|
await rm(dir, { recursive: true, force: true }).catch(() => {});
|
package/src/docker/types.ts
CHANGED
|
@@ -132,6 +132,15 @@ export interface ImageRecipe {
|
|
|
132
132
|
url(spec: ServiceSpec, endpoint: ServiceEndpoint): string;
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
+
/**
|
|
136
|
+
* How derived compose artefacts are laid out under {@link DeriveOptions.composeDir}.
|
|
137
|
+
*
|
|
138
|
+
* - `single` (default) — one production-grade `docker-compose.yml`
|
|
139
|
+
* - `split` — `compose.yml` + per-role `compose.<role>.yml` (+ `compose.prod.yml` when prod)
|
|
140
|
+
* - `stack` — one Swarm-oriented `docker-stack.yml`
|
|
141
|
+
*/
|
|
142
|
+
export type ComposeLayout = "single" | "split" | "stack";
|
|
143
|
+
|
|
135
144
|
/** Options for compose / Dockerfile derivation. */
|
|
136
145
|
export interface DeriveOptions {
|
|
137
146
|
/** Role → image pin (from `oke.config.ts` / Manifest). */
|
|
@@ -140,10 +149,30 @@ export interface DeriveOptions {
|
|
|
140
149
|
readonly app?: string;
|
|
141
150
|
/** App listen port (default 6530). */
|
|
142
151
|
readonly appPort?: number;
|
|
143
|
-
/**
|
|
152
|
+
/**
|
|
153
|
+
* When true, fold production readiness (`/_/ready` HEALTHCHECK, deploy,
|
|
154
|
+
* restart policy, secret refs) and apportion {@link serverCpus} /
|
|
155
|
+
* {@link serverMemoryGb} across services. `oke docker` defaults true;
|
|
156
|
+
* `oke dev --docker` keeps false.
|
|
157
|
+
*/
|
|
144
158
|
readonly prod?: boolean;
|
|
145
159
|
/**
|
|
146
|
-
*
|
|
160
|
+
* Compose file layout (default `single` → `docker-compose.yml`).
|
|
161
|
+
* Pass `split` for layered `compose.<role>.yml`, or `stack` for `docker-stack.yml`.
|
|
162
|
+
*/
|
|
163
|
+
readonly layout?: ComposeLayout;
|
|
164
|
+
/**
|
|
165
|
+
* Host CPU count used to size `deploy.resources` when {@link prod} is true
|
|
166
|
+
* (default 4).
|
|
167
|
+
*/
|
|
168
|
+
readonly serverCpus?: number;
|
|
169
|
+
/**
|
|
170
|
+
* Host RAM in GiB used to size `deploy.resources` when {@link prod} is true
|
|
171
|
+
* (default 8).
|
|
172
|
+
*/
|
|
173
|
+
readonly serverMemoryGb?: number;
|
|
174
|
+
/**
|
|
175
|
+
* Include the `app` service in the compose document (default true).
|
|
147
176
|
* `oke dev --docker` sets false — host Bun runs the app; Docker is infra only.
|
|
148
177
|
*/
|
|
149
178
|
readonly includeApp?: boolean;
|
|
@@ -193,6 +222,9 @@ export interface DeriveResult {
|
|
|
193
222
|
* never embedded in YAML.
|
|
194
223
|
*/
|
|
195
224
|
readonly stackEnv: Readonly<Record<string, string>>;
|
|
196
|
-
/**
|
|
225
|
+
/**
|
|
226
|
+
* Compose `-f` merge order (includes a user-owned override that oke never
|
|
227
|
+
* writes — callers should skip it when the file is absent).
|
|
228
|
+
*/
|
|
197
229
|
readonly composeFiles: readonly string[];
|
|
198
230
|
}
|
|
@@ -147,12 +147,12 @@ describe("ollama live — real completion", () => {
|
|
|
147
147
|
|
|
148
148
|
const runtime = bindAi(
|
|
149
149
|
{
|
|
150
|
-
config: { drivers: { ai: {
|
|
150
|
+
config: { drivers: { ai: { test: "ollama", dev: "ollama" } } },
|
|
151
151
|
ai: { models: [smart], prompts: [ping] },
|
|
152
152
|
},
|
|
153
153
|
undefined,
|
|
154
154
|
() => Date.now(),
|
|
155
|
-
"
|
|
155
|
+
"test",
|
|
156
156
|
false,
|
|
157
157
|
);
|
|
158
158
|
expect(runtime.prompts.has("ollama-ping")).toBe(true);
|
|
@@ -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. */
|