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
|
@@ -6,11 +6,10 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { afterEach, describe, expect, test } from "bun:test";
|
|
9
|
-
import {
|
|
10
|
-
import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
|
9
|
+
import { integer, pgTable, text } from "drizzle-orm/pg-core";
|
|
11
10
|
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
|
|
12
11
|
import { z } from "zod";
|
|
13
|
-
import {
|
|
12
|
+
import { pgliteDriver } from "../../drivers/pglite.ts";
|
|
14
13
|
import { oke } from "../../kernel/app.ts";
|
|
15
14
|
import { resetFlowSeq } from "../../kernel/flow.ts";
|
|
16
15
|
import { on, resetBindings } from "../../kernel/on.ts";
|
|
@@ -26,7 +25,7 @@ afterEach(() => {
|
|
|
26
25
|
});
|
|
27
26
|
|
|
28
27
|
describe("mapRowToJs — declared keys only", () => {
|
|
29
|
-
const posts =
|
|
28
|
+
const posts = pgTable("posts", {
|
|
30
29
|
id: text("id").primaryKey(),
|
|
31
30
|
createdAt: integer("created_at").notNull(),
|
|
32
31
|
});
|
|
@@ -48,15 +47,15 @@ describe("mapRowToJs — declared keys only", () => {
|
|
|
48
47
|
});
|
|
49
48
|
|
|
50
49
|
describe("SqlStoreHandle exit — list/get/create return JS keys only", () => {
|
|
51
|
-
const posts =
|
|
50
|
+
const posts = pgTable("posts", {
|
|
52
51
|
id: text("id").primaryKey(),
|
|
53
52
|
title: text("title").notNull(),
|
|
54
53
|
createdAt: integer("created_at").notNull(),
|
|
55
54
|
});
|
|
56
55
|
|
|
57
56
|
test("select / findById / insert.returning never emit created_at", async () => {
|
|
58
|
-
const conn = await
|
|
59
|
-
|
|
57
|
+
const conn = await pgliteDriver.connect({
|
|
58
|
+
url: "memory://",
|
|
60
59
|
role: "primary",
|
|
61
60
|
});
|
|
62
61
|
const handle = createSqlStoreHandle("sql:app", {
|
|
@@ -87,7 +86,7 @@ describe("SqlStoreHandle exit — list/get/create return JS keys only", () => {
|
|
|
87
86
|
|
|
88
87
|
describe("resource HTTP — exact keys + PII with differing TS/SQL names", () => {
|
|
89
88
|
// TS `email` ↔ SQL `email_addr`; TS `createdAt` ↔ SQL `created_at`.
|
|
90
|
-
const contacts =
|
|
89
|
+
const contacts = pgTable("contacts", {
|
|
91
90
|
id: text("id").primaryKey().$defaultFn(id),
|
|
92
91
|
email: text("email_addr").notNull(),
|
|
93
92
|
createdAt: integer("created_at").notNull().$defaultFn(now),
|
|
@@ -122,7 +121,11 @@ describe("resource HTTP — exact keys + PII with differing TS/SQL names", () =>
|
|
|
122
121
|
|
|
123
122
|
const mounted = on(http.resource("/contacts", contactsR.all()));
|
|
124
123
|
const app = oke({ name: "contacts-resource-test" }).adopt({ contacts: mounted });
|
|
125
|
-
Object.assign(app.$options, {
|
|
124
|
+
Object.assign(app.$options, {
|
|
125
|
+
env: "test",
|
|
126
|
+
stores: [db],
|
|
127
|
+
config: { drivers: { store: { sql: { test: "pglite" } } } },
|
|
128
|
+
});
|
|
126
129
|
return app;
|
|
127
130
|
}
|
|
128
131
|
|
|
@@ -229,7 +232,11 @@ describe("resource HTTP — exact keys + PII with differing TS/SQL names", () =>
|
|
|
229
232
|
|
|
230
233
|
const mounted = on(http.resource("/people", peopleR.all()));
|
|
231
234
|
const app = oke({ name: "people-pii-test" }).adopt({ people: mounted });
|
|
232
|
-
Object.assign(app.$options, {
|
|
235
|
+
Object.assign(app.$options, {
|
|
236
|
+
env: "test",
|
|
237
|
+
stores: [db],
|
|
238
|
+
config: { drivers: { store: { sql: { test: "pglite" } } } },
|
|
239
|
+
});
|
|
233
240
|
|
|
234
241
|
const t = await createTestApp(app);
|
|
235
242
|
const created = await app.fetch(
|
|
@@ -158,7 +158,7 @@ export interface FilesStoreFxHandle {
|
|
|
158
158
|
/** Vector index handle on `fx.store`. */
|
|
159
159
|
export interface VectorIndexStoreFxHandle {
|
|
160
160
|
readonly ref: `index:${string}`;
|
|
161
|
-
readonly driverId: "memory" | "pgvector"
|
|
161
|
+
readonly driverId: "memory" | "pgvector";
|
|
162
162
|
upsert(id: string, vector: readonly number[], meta?: Record<string, unknown>): Promise<void>;
|
|
163
163
|
search(
|
|
164
164
|
vector: readonly number[],
|
|
@@ -290,7 +290,10 @@ export function createStoreRuntime(options: CreateStoreRuntimeOptions): StoreRun
|
|
|
290
290
|
async function openSql(decl: SqlStoreDecl, ctx: StoreInvokeContext): Promise<SqlStoreHandle> {
|
|
291
291
|
const binding = options.sql?.[decl.name] ?? {
|
|
292
292
|
name: decl.name,
|
|
293
|
-
|
|
293
|
+
// PGlite / postgres-shaped drivers persist under `.oke/`; the in-process
|
|
294
|
+
// `memory` SQL driver ignores `url`. Never use SQLite's `:memory:` here —
|
|
295
|
+
// PGlite treats that string as a filesystem path and creates `./:memory:`.
|
|
296
|
+
primary: { url: ".oke/pgdata" },
|
|
294
297
|
};
|
|
295
298
|
const target = resolveSqlTarget(binding, ctx.effects);
|
|
296
299
|
const driver = options.drivers.sql;
|
|
@@ -327,7 +330,7 @@ export function createStoreRuntime(options: CreateStoreRuntimeOptions): StoreRun
|
|
|
327
330
|
|
|
328
331
|
/** SQL-backed index drivers borrow the sql facet's connection. */
|
|
329
332
|
async function sqlConnForIndex(
|
|
330
|
-
driver: VectorIndexDriver & { id: "pgvector"
|
|
333
|
+
driver: VectorIndexDriver & { id: "pgvector" },
|
|
331
334
|
url: string | undefined,
|
|
332
335
|
): Promise<SqlConnection> {
|
|
333
336
|
const sqlDriver = options.drivers.sql;
|
|
@@ -336,16 +339,10 @@ export function createStoreRuntime(options: CreateStoreRuntimeOptions): StoreRun
|
|
|
336
339
|
`oke store: index driver "${driver.id}" needs a configured sql driver to share its connection`,
|
|
337
340
|
);
|
|
338
341
|
}
|
|
339
|
-
|
|
340
|
-
driver.id === "pgvector"
|
|
341
|
-
? sqlDriver.id === "postgres" || sqlDriver.id === "pglite"
|
|
342
|
-
: sqlDriver.id === "libsql";
|
|
343
|
-
if (!compatible) {
|
|
342
|
+
if (sqlDriver.id !== "postgres" && sqlDriver.id !== "pglite") {
|
|
344
343
|
throw new Error(
|
|
345
|
-
`oke store: index driver "
|
|
346
|
-
|
|
347
|
-
? `pgvector needs store.sql on "postgres" or "pglite"`
|
|
348
|
-
: `libsql index needs store.sql on "libsql"`),
|
|
344
|
+
`oke store: index driver "pgvector" cannot share sql driver "${sqlDriver.id}" — ` +
|
|
345
|
+
`pgvector needs store.sql on "postgres" or "pglite"`,
|
|
349
346
|
);
|
|
350
347
|
}
|
|
351
348
|
return sharedSqlConn(sqlDriver, "primary", { url });
|
|
@@ -56,7 +56,7 @@ describe("store.schema.table + field.*", () => {
|
|
|
56
56
|
const decl = store.sql("notes", { schema: { notes } });
|
|
57
57
|
const runtime = createStoreRuntime({
|
|
58
58
|
drivers: {},
|
|
59
|
-
sql: { notes: { name: "notes", primary: {
|
|
59
|
+
sql: { notes: { name: "notes", primary: {} } },
|
|
60
60
|
});
|
|
61
61
|
// Register so classificationsFor merges table columns.
|
|
62
62
|
runtime.register(decl);
|
|
@@ -68,10 +68,10 @@ describe("store.schema.table + field.*", () => {
|
|
|
68
68
|
expect(masked[0]!.email).toBe(PII_MASK);
|
|
69
69
|
|
|
70
70
|
// Runtime path: open handle and query — ensure classificationsFromTable feeds mask.
|
|
71
|
-
const {
|
|
71
|
+
const { memorySqlDriver } = await import("../../drivers/index.ts");
|
|
72
72
|
const rt = createStoreRuntime({
|
|
73
|
-
drivers: { sql:
|
|
74
|
-
sql: { notes: { name: "notes", primary: {
|
|
73
|
+
drivers: { sql: memorySqlDriver },
|
|
74
|
+
sql: { notes: { name: "notes", primary: {} } },
|
|
75
75
|
});
|
|
76
76
|
rt.register(decl);
|
|
77
77
|
const handle = (await rt.open(decl, {
|
|
@@ -84,7 +84,7 @@ describe("store.schema.table + field.*", () => {
|
|
|
84
84
|
});
|
|
85
85
|
});
|
|
86
86
|
|
|
87
|
-
describe("emitDrizzleSource —
|
|
87
|
+
describe("emitDrizzleSource — postgres pgTable from one declaration", () => {
|
|
88
88
|
const notes = store.schema.table("notes", {
|
|
89
89
|
id: field.text().primaryKey().defaultFn(id),
|
|
90
90
|
title: field.text().notNull(),
|
|
@@ -92,24 +92,17 @@ describe("emitDrizzleSource — both dialects from one declaration", () => {
|
|
|
92
92
|
createdAt: field.integer().notNull().defaultFn(now),
|
|
93
93
|
});
|
|
94
94
|
|
|
95
|
-
test("
|
|
96
|
-
const src = emitDrizzleSource([notes], "sqlite");
|
|
97
|
-
expect(src.startsWith(GENERATED_SCHEMA_HEADER)).toBe(true);
|
|
98
|
-
expect(src).toContain('from "drizzle-orm/sqlite-core"');
|
|
99
|
-
expect(src).toContain("sqliteTable");
|
|
100
|
-
expect(src).not.toContain("pgTable");
|
|
101
|
-
expect(src).toContain('text("id").primaryKey().$defaultFn(id)');
|
|
102
|
-
expect(src).toContain('integer("created_at").notNull().$defaultFn(now)');
|
|
103
|
-
expect(src).toContain('text("body").notNull()');
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
test("postgres emits pgTable from the same decl", () => {
|
|
95
|
+
test("postgres emits pgTable", () => {
|
|
107
96
|
const src = emitDrizzleSource([notes], "postgres");
|
|
97
|
+
expect(src.startsWith(GENERATED_SCHEMA_HEADER)).toBe(true);
|
|
108
98
|
expect(src).toContain('from "drizzle-orm/pg-core"');
|
|
109
99
|
expect(src).toContain("pgTable");
|
|
110
100
|
expect(src).not.toContain("sqliteTable");
|
|
101
|
+
expect(src).not.toContain("drizzle-orm/sqlite-core");
|
|
111
102
|
expect(src).toContain('text("id").primaryKey().$defaultFn(id)');
|
|
112
|
-
|
|
103
|
+
// Postgres INTEGER is 32-bit — abstract integer maps to bigint for ms clocks.
|
|
104
|
+
expect(src).toContain('bigint("created_at", { mode: "number" }).notNull().$defaultFn(now)');
|
|
105
|
+
expect(src).toContain('text("body").notNull()');
|
|
113
106
|
});
|
|
114
107
|
});
|
|
115
108
|
|
|
@@ -142,9 +135,9 @@ describe("plugin table columns in generated schema", () => {
|
|
|
142
135
|
expect(pluginTables[0]!.columns.actorId!.classification?.pii).toBe(true);
|
|
143
136
|
|
|
144
137
|
const merged = mergeSchemaTables([notes], pluginTables);
|
|
145
|
-
const src = emitDrizzleSource(merged, "
|
|
146
|
-
expect(src).toContain('
|
|
147
|
-
expect(src).toContain('
|
|
138
|
+
const src = emitDrizzleSource(merged, "postgres");
|
|
139
|
+
expect(src).toContain('pgTable("notes"');
|
|
140
|
+
expect(src).toContain('pgTable("audit_events"');
|
|
148
141
|
expect(src).toContain('text("actor_id").notNull()');
|
|
149
142
|
});
|
|
150
143
|
|
|
@@ -195,21 +188,12 @@ describe("emitDrizzleSource — references + relations (Linkly-shaped)", () => {
|
|
|
195
188
|
},
|
|
196
189
|
}));
|
|
197
190
|
|
|
198
|
-
test("
|
|
199
|
-
const src = emitDrizzleSource([links, daily], "sqlite", { relations: [relations] });
|
|
200
|
-
expect(src).toContain("sqliteTable");
|
|
201
|
-
expect(src).toContain(".references(() => links.code)");
|
|
202
|
-
expect(src).toContain('import { defineRelations } from "drizzle-orm"');
|
|
203
|
-
expect(src).toContain("defineRelations({ links, daily }");
|
|
204
|
-
expect(src).toContain("r.many.daily({ from: r.links.code, to: r.daily.code })");
|
|
205
|
-
expect(src).toContain("r.one.links({ from: r.daily.code, to: r.links.code, optional: false })");
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
test("postgres emit includes same FK + defineRelations from one decl", () => {
|
|
191
|
+
test("postgres emit includes FK + defineRelations", () => {
|
|
209
192
|
const src = emitDrizzleSource([links, daily], "postgres", { relations: [relations] });
|
|
210
193
|
expect(src).toContain("pgTable");
|
|
211
194
|
expect(src).not.toContain("sqliteTable");
|
|
212
195
|
expect(src).toContain(".references(() => links.code)");
|
|
196
|
+
expect(src).toContain('import { defineRelations } from "drizzle-orm"');
|
|
213
197
|
expect(src).toContain("defineRelations({ links, daily }");
|
|
214
198
|
expect(src).toContain("r.many.daily({ from: r.links.code, to: r.daily.code })");
|
|
215
199
|
expect(src).toContain("r.one.links({ from: r.daily.code, to: r.links.code, optional: false })");
|
|
@@ -19,8 +19,7 @@ describe("defineSeed / resolveSeedCategory", () => {
|
|
|
19
19
|
});
|
|
20
20
|
|
|
21
21
|
test("resolveSeedCategory matches the env matrix", () => {
|
|
22
|
-
expect(resolveSeedCategory("
|
|
23
|
-
expect(resolveSeedCategory("docker")).toBe("dev");
|
|
22
|
+
expect(resolveSeedCategory("dev")).toBe("dev");
|
|
24
23
|
expect(resolveSeedCategory("prod")).toBe("prod");
|
|
25
24
|
expect(resolveSeedCategory("test")).toBe(null);
|
|
26
25
|
});
|
|
@@ -17,7 +17,7 @@ export type SeedFns = SeedFn | readonly SeedFn[];
|
|
|
17
17
|
* Seed categories for {@link defineSeed}.
|
|
18
18
|
*
|
|
19
19
|
* - `essential` — every environment, always
|
|
20
|
-
* - `dev` — `
|
|
20
|
+
* - `dev` — `dev` ConfigEnv only (Docker Compose laptop)
|
|
21
21
|
* - `prod` — `prod` only
|
|
22
22
|
*/
|
|
23
23
|
export interface SeedDef {
|
|
@@ -52,17 +52,16 @@ export function normalizeSeedFns(fns?: SeedFns): SeedFn[] {
|
|
|
52
52
|
/**
|
|
53
53
|
* Which optional category runs for `env` (single source of truth).
|
|
54
54
|
*
|
|
55
|
-
* | env
|
|
56
|
-
* |
|
|
57
|
-
* |
|
|
58
|
-
* |
|
|
59
|
-
* |
|
|
60
|
-
* | prod | prod |
|
|
55
|
+
* | env | category |
|
|
56
|
+
* | ---- | -------- |
|
|
57
|
+
* | dev | dev |
|
|
58
|
+
* | test | (none) |
|
|
59
|
+
* | prod | prod |
|
|
61
60
|
*
|
|
62
61
|
* @param env - Resolved {@link ConfigEnv}
|
|
63
62
|
*/
|
|
64
63
|
export function resolveSeedCategory(env: ConfigEnv): SeedCategory | null {
|
|
65
|
-
if (env === "
|
|
64
|
+
if (env === "dev") return "dev";
|
|
66
65
|
if (env === "prod") return "prod";
|
|
67
66
|
return null;
|
|
68
67
|
}
|
|
@@ -20,10 +20,10 @@ import {
|
|
|
20
20
|
or,
|
|
21
21
|
sql,
|
|
22
22
|
} from "drizzle-orm";
|
|
23
|
-
import { integer,
|
|
23
|
+
import { integer, pgTable, text } from "drizzle-orm/pg-core";
|
|
24
24
|
import { compileOrderBy, compileWhere } from "./sql-condition.ts";
|
|
25
25
|
|
|
26
|
-
const notes =
|
|
26
|
+
const notes = pgTable("notes", {
|
|
27
27
|
id: text("id").primaryKey(),
|
|
28
28
|
title: text("title").notNull(),
|
|
29
29
|
createdAt: integer("created_at").notNull(),
|
|
@@ -7,22 +7,21 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { describe, expect, test } from "bun:test";
|
|
10
|
-
import { Database } from "bun:sqlite";
|
|
11
10
|
import { and, desc, eq, like, lt, or } from "drizzle-orm";
|
|
12
|
-
import { integer,
|
|
13
|
-
import {
|
|
11
|
+
import { integer, pgTable, text } from "drizzle-orm/pg-core";
|
|
12
|
+
import { pgliteDriver } from "../../drivers/pglite.ts";
|
|
14
13
|
import type { SqlConnection } from "../../drivers/types.ts";
|
|
15
14
|
import { createSqlStoreHandle, type SqlStoreHandle } from "./sql-session.ts";
|
|
16
15
|
|
|
17
|
-
const posts =
|
|
16
|
+
const posts = pgTable("posts", {
|
|
18
17
|
id: text("id").primaryKey(),
|
|
19
18
|
title: text("title").notNull(),
|
|
20
19
|
createdAt: integer("created_at").notNull(),
|
|
21
20
|
});
|
|
22
21
|
|
|
23
22
|
async function openHandle(): Promise<{ handle: SqlStoreHandle; conn: SqlConnection }> {
|
|
24
|
-
const conn = await
|
|
25
|
-
|
|
23
|
+
const conn = await pgliteDriver.connect({
|
|
24
|
+
url: "memory://",
|
|
26
25
|
role: "primary",
|
|
27
26
|
});
|
|
28
27
|
const handle = createSqlStoreHandle("sql:app", {
|
|
@@ -36,8 +35,7 @@ async function openHandle(): Promise<{ handle: SqlStoreHandle; conn: SqlConnecti
|
|
|
36
35
|
|
|
37
36
|
describe("SqlStoreHandle — no relational query surface (path b)", () => {
|
|
38
37
|
test("created handle exposes exactly the single-table surface", async () => {
|
|
39
|
-
const
|
|
40
|
-
const conn = await sqliteDriver.connect({ client: db, role: "primary" });
|
|
38
|
+
const conn = await pgliteDriver.connect({ url: "memory://", role: "primary" });
|
|
41
39
|
const handle = createSqlStoreHandle("sql:app", {
|
|
42
40
|
connection: conn,
|
|
43
41
|
classifications: new Map(),
|
|
@@ -124,12 +122,12 @@ describe("SqlStoreHandle — orderBy / limit select chain", () => {
|
|
|
124
122
|
await conn.close();
|
|
125
123
|
});
|
|
126
124
|
|
|
127
|
-
test("like filters rows through the session (
|
|
125
|
+
test("like filters rows through the session (postgres case-sensitive)", async () => {
|
|
128
126
|
const { handle, conn } = await openHandle();
|
|
129
127
|
await handle.insert(posts).values({ id: "p1", title: "alpha", createdAt: 100 });
|
|
130
128
|
await handle.insert(posts).values({ id: "p2", title: "bravo", createdAt: 200 });
|
|
131
129
|
|
|
132
|
-
const rows = await handle.select().from(posts).where(like(posts.title, "
|
|
130
|
+
const rows = await handle.select().from(posts).where(like(posts.title, "a%"));
|
|
133
131
|
expect(rows.map((r) => r.id)).toEqual(["p1"]);
|
|
134
132
|
await conn.close();
|
|
135
133
|
});
|
|
@@ -363,9 +363,13 @@ export function createSqlStoreHandle(
|
|
|
363
363
|
if (cols.length === 0) return;
|
|
364
364
|
const name = resolveTableName(table);
|
|
365
365
|
const pk = cols.find((c) => c.primary)?.sqlName;
|
|
366
|
+
// Postgres/PGLite INTEGER is 32-bit — abstract `integer` (ms timestamps via
|
|
367
|
+
// `now`) must map to BIGINT. SQLite INTEGER is flexible up to 64-bit.
|
|
368
|
+
const pgWideInt = connection.driverId === "postgres" || connection.driverId === "pglite";
|
|
366
369
|
const colSql = cols
|
|
367
370
|
.map((c) => {
|
|
368
|
-
const
|
|
371
|
+
const base = pgWideInt && c.sqlType === "INTEGER" ? "BIGINT" : c.sqlType;
|
|
372
|
+
const typ = pk && c.sqlName === pk ? `${base} PRIMARY KEY` : base;
|
|
369
373
|
return `${quoteIdent(c.sqlName)} ${typ}`;
|
|
370
374
|
})
|
|
371
375
|
.join(", ");
|
|
@@ -734,6 +738,10 @@ export function createSqlStoreHandle(
|
|
|
734
738
|
async ensureTable(table) {
|
|
735
739
|
const cols = Object.values(table.columns);
|
|
736
740
|
const pk = resolvePkColumn(table);
|
|
741
|
+
const intType =
|
|
742
|
+
connection.driverId === "postgres" || connection.driverId === "pglite"
|
|
743
|
+
? "BIGINT"
|
|
744
|
+
: "INTEGER";
|
|
737
745
|
const colSql = cols
|
|
738
746
|
.map((c) => {
|
|
739
747
|
const typ =
|
|
@@ -743,7 +751,7 @@ export function createSqlStoreHandle(
|
|
|
743
751
|
c.name === "qty" ||
|
|
744
752
|
c.name === "createdAt" ||
|
|
745
753
|
c.name === "created_at"
|
|
746
|
-
?
|
|
754
|
+
? intType
|
|
747
755
|
: "TEXT";
|
|
748
756
|
return `${quoteIdent(c.name)} ${typ}`;
|
|
749
757
|
})
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Store element acceptance:
|
|
3
|
-
* - same flow runs unchanged against
|
|
3
|
+
* - same flow runs unchanged against memory and postgres
|
|
4
4
|
* - read-only flow provably hits a replica
|
|
5
5
|
* - auto-invalidation fires on exactly the writes touching the read's keys
|
|
6
6
|
* - SELECT * masks classified columns
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { describe, expect, test } from "bun:test";
|
|
10
|
-
import { createPostgresFakeClient,
|
|
10
|
+
import { createPostgresFakeClient, memorySqlDriver, postgresDriver } from "../drivers/index.ts";
|
|
11
11
|
import type { Effects } from "../manifest/types.ts";
|
|
12
12
|
import {
|
|
13
13
|
classify,
|
|
@@ -73,7 +73,7 @@ describe("store facets", () => {
|
|
|
73
73
|
});
|
|
74
74
|
});
|
|
75
75
|
|
|
76
|
-
describe("same flow against
|
|
76
|
+
describe("same flow against memory and postgres", () => {
|
|
77
77
|
test("insert / select / findById unchanged across drivers", async () => {
|
|
78
78
|
const decl = store.sql("notes", {
|
|
79
79
|
schema: { notes },
|
|
@@ -81,7 +81,7 @@ describe("same flow against sqlite and postgres", () => {
|
|
|
81
81
|
});
|
|
82
82
|
|
|
83
83
|
for (const [label, driver, client] of [
|
|
84
|
-
["
|
|
84
|
+
["memory", memorySqlDriver, undefined],
|
|
85
85
|
["postgres", postgresDriver, createPostgresFakeClient()],
|
|
86
86
|
] as const) {
|
|
87
87
|
const runtime = createStoreRuntime({
|
|
@@ -89,7 +89,7 @@ describe("same flow against sqlite and postgres", () => {
|
|
|
89
89
|
sql: {
|
|
90
90
|
notes: {
|
|
91
91
|
name: "notes",
|
|
92
|
-
primary: {
|
|
92
|
+
primary: { client },
|
|
93
93
|
},
|
|
94
94
|
},
|
|
95
95
|
});
|
|
@@ -218,8 +218,8 @@ describe("tier-1 cache invalidation from effects", () => {
|
|
|
218
218
|
|
|
219
219
|
test("runtime putTier1 + onWriteEffects", async () => {
|
|
220
220
|
const runtime = createStoreRuntime({
|
|
221
|
-
drivers: { sql:
|
|
222
|
-
sql: { notes: { name: "notes", primary: {
|
|
221
|
+
drivers: { sql: memorySqlDriver },
|
|
222
|
+
sql: { notes: { name: "notes", primary: {} } },
|
|
223
223
|
});
|
|
224
224
|
const keys = runtime.putTier1({ reads: ["sql:notes"] }, ["cached"]);
|
|
225
225
|
expect(runtime.cache.get<string[]>(keys[0]!)).toEqual(["cached"]);
|
|
@@ -237,7 +237,7 @@ describe("exists and increment helpers", () => {
|
|
|
237
237
|
|
|
238
238
|
test("exists returns correctly for present / absent rows across sqlite and postgres", async () => {
|
|
239
239
|
for (const [label, driver, client] of [
|
|
240
|
-
["
|
|
240
|
+
["memory", memorySqlDriver, undefined],
|
|
241
241
|
["postgres", postgresDriver, createPostgresFakeClient()],
|
|
242
242
|
] as const) {
|
|
243
243
|
const decl = store.sql("counters");
|
|
@@ -246,7 +246,7 @@ describe("exists and increment helpers", () => {
|
|
|
246
246
|
sql: {
|
|
247
247
|
counters: {
|
|
248
248
|
name: "counters",
|
|
249
|
-
primary: {
|
|
249
|
+
primary: { client },
|
|
250
250
|
},
|
|
251
251
|
},
|
|
252
252
|
});
|
|
@@ -267,7 +267,7 @@ describe("exists and increment helpers", () => {
|
|
|
267
267
|
|
|
268
268
|
test("increment under 100 concurrent callers lands on the correct final value", async () => {
|
|
269
269
|
for (const [label, driver, client] of [
|
|
270
|
-
["
|
|
270
|
+
["memory", memorySqlDriver, undefined],
|
|
271
271
|
["postgres", postgresDriver, createPostgresFakeClient()],
|
|
272
272
|
] as const) {
|
|
273
273
|
const decl = store.sql("counters");
|
|
@@ -276,7 +276,7 @@ describe("exists and increment helpers", () => {
|
|
|
276
276
|
sql: {
|
|
277
277
|
counters: {
|
|
278
278
|
name: "counters",
|
|
279
|
-
primary: {
|
|
279
|
+
primary: { client },
|
|
280
280
|
},
|
|
281
281
|
},
|
|
282
282
|
});
|
|
@@ -308,8 +308,8 @@ describe("PII masking at the driver boundary", () => {
|
|
|
308
308
|
classify: { notes: { email: classify({ pii: true }) } },
|
|
309
309
|
});
|
|
310
310
|
const runtime = createStoreRuntime({
|
|
311
|
-
drivers: { sql:
|
|
312
|
-
sql: { notes: { name: "notes", primary: {
|
|
311
|
+
drivers: { sql: memorySqlDriver },
|
|
312
|
+
sql: { notes: { name: "notes", primary: {} } },
|
|
313
313
|
});
|
|
314
314
|
runtime.register(decl);
|
|
315
315
|
const handle = asSql(
|