okengine 0.17.2 → 0.18.4
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/AGENTS.md +5 -3
- package/README.md +14 -10
- package/manifest.v1.schema.json +61 -2
- package/package.json +19 -5
- package/site/content/docs/ai/index.mdx +1 -1
- package/site/content/docs/ai/mcp.mdx +10 -1
- package/site/content/docs/ai/skills.mdx +9 -9
- package/site/content/docs/elements/ai.mdx +1 -1
- package/site/content/docs/elements/clock.mdx +1 -1
- package/site/content/docs/elements/flow.mdx +25 -1
- package/site/content/docs/elements/gate.mdx +3 -2
- package/site/content/docs/elements/store.mdx +289 -341
- package/site/content/docs/elements/vault.mdx +5 -5
- package/site/content/docs/get-started/basic-usage.mdx +3 -10
- package/site/content/docs/get-started/index.mdx +1 -1
- package/site/content/docs/get-started/installation.mdx +2 -3
- package/site/content/docs/get-started/introduction.mdx +58 -121
- package/site/content/docs/get-started/meta.json +9 -1
- package/site/content/docs/get-started/project-structure.mdx +4 -11
- package/site/content/docs/get-started/testing.mdx +328 -0
- package/site/content/docs/get-started/why.mdx +93 -71
- package/site/content/docs/index.mdx +44 -11
- package/site/content/docs/meta.json +8 -5
- package/site/content/docs/plugins/apple.mdx +151 -0
- package/site/content/docs/plugins/discord.mdx +139 -0
- package/site/content/docs/plugins/facebook.mdx +134 -0
- package/site/content/docs/plugins/figma.mdx +138 -0
- package/site/content/docs/plugins/github.mdx +138 -0
- package/site/content/docs/plugins/google.mdx +153 -0
- package/site/content/docs/plugins/index.mdx +47 -1
- package/site/content/docs/plugins/meta.json +10 -0
- package/site/content/docs/plugins/microsoft.mdx +151 -0
- package/site/content/docs/plugins/oauth.mdx +188 -0
- package/site/content/docs/plugins/x.mdx +125 -0
- package/site/content/docs/providers/index.mdx +2 -0
- package/site/content/docs/recipes/index.mdx +2 -0
- package/site/content/docs/reference/cli.md +3 -2
- package/site/content/docs/reference/client.mdx +58 -1
- package/site/content/docs/reference/configuration.mdx +2 -4
- package/site/content/docs/reference/fx.mdx +3 -1
- package/site/content/docs/reference/index.mdx +0 -5
- package/site/content/docs/reference/meta.json +2 -2
- package/site/content/docs/reference/okid.mdx +137 -0
- package/src/auth/bindings.ts +1 -1
- package/src/auth/config.ts +9 -0
- package/src/auth/identity-sql.ts +314 -0
- package/src/auth/identity.ts +140 -2
- package/src/auth/index.ts +17 -1
- package/src/auth/method-context.ts +3 -0
- package/src/auth/oauth-as/cimd.ts +132 -0
- package/src/auth/oauth-as/crypto.test.ts +101 -0
- package/src/auth/oauth-as/crypto.ts +393 -0
- package/src/auth/oauth-as/errors.ts +68 -0
- package/src/auth/oauth-as/http.test.ts +419 -0
- package/src/auth/oauth-as/http.ts +842 -0
- package/src/auth/oauth-as/stores.ts +61 -0
- package/src/auth/oauth-as/tables.ts +142 -0
- package/src/auth/tables.ts +0 -11
- package/src/bench/README.md +83 -0
- package/src/bench/REPORT.md +176 -0
- package/src/bench/g01-rls-stamp.bench.ts +194 -0
- package/src/bench/g02-clock-per-tenant.bench.ts +158 -0
- package/src/bench/g03-signal-once.bench.ts +157 -0
- package/src/bench/g03-signal-reconnect.bench.ts +254 -0
- package/src/bench/g03-signal-sse-memory.bench.ts +191 -0
- package/src/bench/g04-auth-vault-hotpath.bench.ts +170 -0
- package/src/bench/g05-sustained-full.bench.ts +265 -0
- package/src/bench/g06-mixed-load.bench.ts +260 -0
- package/src/bench/g07-vault-crypto.bench.ts +100 -0
- package/src/bench/g07-vault-rotate-under-read.bench.ts +285 -0
- package/src/bench/g08-conn-oversubscribe.bench.ts +194 -0
- package/src/bench/g08-store-kv-durable.bench.ts +133 -0
- package/src/bench/g08-store-sql.bench.ts +178 -0
- package/src/bench/g09-journal-sustained.bench.ts +203 -0
- package/src/bench/g10-observability-contention.bench.ts +246 -0
- package/src/bench/g11-cold-start-cycle.bench.ts +164 -0
- package/src/bench/g13-elements.bench.ts +427 -0
- package/src/bench/g14-graceful-shutdown.bench.ts +244 -0
- package/src/bench/g15-postgres-degradation.bench.ts +264 -0
- package/src/bench/g16-live-query-fanout.bench.ts +206 -0
- package/src/bench/lib/event-loop-lag.ts +26 -0
- package/src/bench/lib/infra.ts +60 -0
- package/src/bench/lib/report.ts +52 -0
- package/src/bench/lib/rss-sampler.ts +61 -0
- package/src/bench/lib/signal-pg.ts +88 -0
- package/src/bench/load-app.ts +337 -0
- package/src/bench/load-child.ts +108 -0
- package/src/bench/smoke.bench.ts +43 -0
- package/src/cli/competitor-mention-removal.test.ts +28 -0
- package/src/cli/doctor-fd.ts +117 -0
- package/src/cli/doctor.test.ts +192 -0
- package/src/cli/doctor.ts +129 -1
- package/src/client/create.ts +95 -1
- package/src/client/index.ts +9 -2
- package/src/client/transport.ts +11 -4
- package/src/client/use-live-query.ts +154 -0
- package/src/client-react/index.ts +15 -1
- package/src/client-react/live-resource.ts +246 -0
- package/src/client-react/use-live-query.test.ts +475 -0
- package/src/client-react/use-live-query.ts +530 -0
- package/src/compiler/extract.test.ts +518 -0
- package/src/compiler/extract.ts +386 -19
- package/src/console/server/invoke-user-flow.ts +2 -1
- package/src/console/ui-next/dist/assets/{access-page-DnWbnGzq.js → access-page-De7Lc2JC.js} +1 -1
- package/src/console/ui-next/dist/assets/{flows-page-BiZ4-6yQ.js → flows-page-RGy7VEA_.js} +1 -1
- package/src/console/ui-next/dist/assets/{index-C8NRK2R-.js → index-_rgpdVzo.js} +3 -3
- package/src/console/ui-next/dist/assets/{observability-page-CrB6vd1T.js → observability-page-Ds6pcnh-.js} +1 -1
- package/src/console/ui-next/dist/assets/{store-page-CS5-aETQ.js → store-page-02xOiqIK.js} +3 -3
- package/src/console/ui-next/dist/assets/{units-page-CjtdlW8l.js → units-page-4rHOePuE.js} +1 -1
- package/src/console/ui-next/dist/assets/{vault-page-C6Xxm9SA.js → vault-page-DISPgxLM.js} +1 -1
- package/src/console/ui-next/dist/index.html +1 -1
- package/src/console/ui-next/src/features/store/lib/fields-from-table.ts +36 -2
- package/src/drivers/cdc-outbox.ts +389 -0
- package/src/drivers/memory.ts +20 -0
- package/src/drivers/oauth-apple.ts +156 -0
- package/src/drivers/oauth-discord.ts +79 -0
- package/src/drivers/oauth-facebook.ts +80 -0
- package/src/drivers/oauth-figma.ts +116 -0
- package/src/drivers/oauth-github.ts +92 -0
- package/src/drivers/oauth-google.ts +142 -0
- package/src/drivers/oauth-microsoft.ts +174 -0
- package/src/drivers/oauth-oidc.ts +293 -0
- package/src/drivers/oauth-shared.ts +326 -0
- package/src/drivers/oauth-types.ts +159 -0
- package/src/drivers/oauth-x.ts +77 -0
- package/src/drivers/oauth2-common.ts +95 -0
- package/src/drivers/oauth2-token.ts +61 -0
- package/src/drivers/pg-rls-row-passes.ts +251 -0
- package/src/drivers/pg-rls.ts +2 -0
- package/src/drivers/postgres.ts +45 -2
- package/src/drivers/signal-postgres.ts +2 -1
- package/src/elements/channel/runtime.ts +29 -2
- package/src/elements/channel.test.ts +52 -0
- package/src/elements/gate/boot.ts +29 -2
- package/src/elements/store/emit-drizzle.ts +147 -14
- package/src/elements/store/field-ddl.test.ts +118 -0
- package/src/elements/store/field-types.test.ts +455 -0
- package/src/elements/store/list-query.golden.json +777 -0
- package/src/elements/store/list-query.parity.test.ts +396 -0
- package/src/elements/store/list-query.ts +792 -0
- package/src/elements/store/live-default.test.ts +136 -0
- package/src/elements/store/live-http.test.ts +160 -0
- package/src/elements/store/live-isolation.test.ts +291 -0
- package/src/elements/store/live-query-runtime.test.ts +323 -0
- package/src/elements/store/live-query-runtime.ts +403 -0
- package/src/elements/store/live-query-server.test.ts +377 -0
- package/src/elements/store/live-query-server.ts +102 -0
- package/src/elements/store/live-query.ts +97 -0
- package/src/elements/store/resource.ts +189 -680
- package/src/elements/store/rls-row-passes-policies.parity.test.ts +665 -0
- package/src/elements/store/schema-decl.ts +539 -41
- package/src/elements/store/sql-rls-stamp.test.ts +27 -0
- package/src/elements/store/sql-session.ts +297 -35
- package/src/elements/store/table.ts +102 -21
- package/src/elements/store.test.ts +3 -1
- package/src/elements/store.ts +12 -1
- package/src/elements/vault/chaos-child.ts +74 -1
- package/src/elements/vault/chaos.test.ts +4 -2
- package/src/elements/vault/storage.ts +4 -2
- package/src/index.ts +5 -2
- package/src/kernel/app-auth.ts +1 -0
- package/src/kernel/app.ts +116 -2
- package/src/kernel/auth-sharing.test.ts +196 -0
- package/src/kernel/boot.test.ts +3 -3
- package/src/kernel/errors.ts +8 -0
- package/src/kernel/fx.test.ts +1 -0
- package/src/kernel/fx.ts +14 -2
- package/src/kernel/horizontal-child.ts +2 -1
- package/src/kernel/http-resource.ts +33 -7
- package/src/kernel/identity-host-persist.test.ts +119 -0
- package/src/kernel/instance-id.ts +4 -2
- package/src/kernel/journal.ts +2 -1
- package/src/kernel/mcp-tool.test.ts +95 -0
- package/src/kernel/on.ts +9 -0
- package/src/kernel/realtime-bind.ts +326 -0
- package/src/kernel/resource-live.ts +117 -0
- package/src/kernel/triggers.ts +86 -4
- package/src/manifest/diff.ts +37 -0
- package/src/manifest/types.ts +64 -2
- package/src/okid.bench.test.ts +64 -0
- package/src/okid.test.ts +338 -0
- package/src/okid.ts +245 -0
- package/src/plugins/anonymous.ts +19 -1
- package/src/plugins/auth/shared.ts +15 -0
- package/src/plugins/index.ts +2 -0
- package/src/plugins/magic-link.ts +10 -8
- package/src/plugins/mcp-oauth.ts +208 -0
- package/src/plugins/oauth/flow-store.ts +117 -0
- package/src/plugins/oauth/link.ts +69 -0
- package/src/plugins/oauth/shared.ts +108 -0
- package/src/plugins/oauth/token-vault.ts +100 -0
- package/src/plugins/oauth.security.test.ts +535 -0
- package/src/plugins/oauth.ts +532 -0
- package/src/plugins/otp.ts +48 -6
- package/src/plugins/passkey.ts +20 -1
- package/src/plugins/two-factor.ts +11 -0
- package/src/plugins/username.ts +40 -7
- package/src/release/build-lib.ts +7 -1
- package/src/release/measure.ts +1 -0
- package/src/release/official-plugins.ts +4 -1
- package/src/runs/collect.ts +2 -1
- package/src/runs/drivers/files.ts +2 -1
- package/src/test/create-test-app.ts +114 -5
- package/src/test/export-bundle.test.ts +33 -0
- package/src/test/live-signals.test.ts +83 -0
- package/src/test/tenant-isolation.test.ts +175 -0
- package/src/testing.ts +26 -0
- package/src/upgrade/codemods.ts +1 -1
- package/site/content/docs/reference/migrating-environments.mdx +0 -158
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `createTestApp` multi-tenancy testing & real RLS isolation.
|
|
3
|
+
*
|
|
4
|
+
* RLS policies / helper functions are installed by `oke db push` in real apps;
|
|
5
|
+
* a test boot does not run migrations, so this harness test installs the
|
|
6
|
+
* tenant policy + `oke.tenant()` helper on the booted PGlite connection
|
|
7
|
+
* (mirroring `src/elements/store/sql-rls-isolation.test.ts`).
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { describe, expect, test } from "bun:test";
|
|
11
|
+
import { z } from "zod";
|
|
12
|
+
import { oke } from "../kernel/app.ts";
|
|
13
|
+
import { flow, resetFlowSeq } from "../kernel/flow.ts";
|
|
14
|
+
import { on, resetBindings } from "../kernel/on.ts";
|
|
15
|
+
import { http } from "../kernel/triggers.ts";
|
|
16
|
+
import { gate } from "../elements/gate.ts";
|
|
17
|
+
import { field } from "../elements/store/schema-decl.ts";
|
|
18
|
+
import { store } from "../elements/store.ts";
|
|
19
|
+
import { installOkeRlsHelpers } from "../drivers/pg-rls.ts";
|
|
20
|
+
import type { SqlConnection } from "../drivers/types.ts";
|
|
21
|
+
import { createTestApp } from "./create-test-app.ts";
|
|
22
|
+
|
|
23
|
+
describe("createTestApp tenancy testing & RLS isolation", () => {
|
|
24
|
+
test("loginAs with tenantId stamps fx.tenant.id and isolates queries via real RLS", async () => {
|
|
25
|
+
resetBindings();
|
|
26
|
+
resetFlowSeq();
|
|
27
|
+
|
|
28
|
+
const memberGate = gate.policy("member", ({ auth }) => !!auth.userId && !!auth.verified);
|
|
29
|
+
|
|
30
|
+
const documents = store.schema.table(
|
|
31
|
+
"documents",
|
|
32
|
+
{
|
|
33
|
+
id: field.text().primaryKey(),
|
|
34
|
+
tenant_id: field.text().notNull(),
|
|
35
|
+
title: field.text().notNull(),
|
|
36
|
+
},
|
|
37
|
+
[store.schema.policy.tenant("tenant_id", { for: "all" })],
|
|
38
|
+
);
|
|
39
|
+
const docStore = store.sql("docs", { schema: { documents } });
|
|
40
|
+
|
|
41
|
+
on(
|
|
42
|
+
http.post("/docs").gate(memberGate),
|
|
43
|
+
flow("docs.create", {
|
|
44
|
+
in: z.object({ title: z.string() }),
|
|
45
|
+
out: z.object({ id: z.string(), tenantId: z.string().nullable() }),
|
|
46
|
+
effects: { writes: ["sql:docs"], reads: ["sql:docs"] },
|
|
47
|
+
do: async (input, fx) => {
|
|
48
|
+
const id = fx.id();
|
|
49
|
+
await fx.store(docStore).insert(documents).values({
|
|
50
|
+
id,
|
|
51
|
+
tenant_id: fx.tenant.id!,
|
|
52
|
+
title: input.title,
|
|
53
|
+
});
|
|
54
|
+
return { id, tenantId: fx.tenant.id };
|
|
55
|
+
},
|
|
56
|
+
}),
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
on(
|
|
60
|
+
http.get("/docs").gate(memberGate),
|
|
61
|
+
flow("docs.list", {
|
|
62
|
+
in: z.void(),
|
|
63
|
+
out: z.array(z.object({ id: z.string(), title: z.string() })),
|
|
64
|
+
effects: { reads: ["sql:docs"] },
|
|
65
|
+
do: async (_input, fx) => {
|
|
66
|
+
const rows = await fx.store(docStore).select().from(documents);
|
|
67
|
+
return rows.map((r) => ({ id: r.id, title: r.title }));
|
|
68
|
+
},
|
|
69
|
+
}),
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const app = oke({
|
|
73
|
+
name: "tenant-app",
|
|
74
|
+
gate: {
|
|
75
|
+
policies: [memberGate],
|
|
76
|
+
auth: { tenant: true },
|
|
77
|
+
},
|
|
78
|
+
stores: [docStore],
|
|
79
|
+
env: "test",
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
const t = await createTestApp(app, {
|
|
83
|
+
gates: [memberGate],
|
|
84
|
+
boot: {
|
|
85
|
+
config: {
|
|
86
|
+
drivers: {
|
|
87
|
+
store: {
|
|
88
|
+
sql: { test: "pglite" }, // Real PGlite RLS engine
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const userAcme = await t.auth.loginAs({ id: "alice", tenantId: "acme" });
|
|
96
|
+
const userGlobex = await t.auth.loginAs({ id: "bob", tenantId: "globex" });
|
|
97
|
+
|
|
98
|
+
expect(userAcme.tenantId).toBe("acme");
|
|
99
|
+
expect(userGlobex.tenantId).toBe("globex");
|
|
100
|
+
|
|
101
|
+
// Install RLS helper functions + tenant policy on the booted connection.
|
|
102
|
+
// Real deployments get these via `oke db push`; the harness boot does not
|
|
103
|
+
// run migrations, so the test installs them explicitly (same as the
|
|
104
|
+
// codebase's own sql-rls-isolation tests).
|
|
105
|
+
const conn = (await app.bootResult?.store?.primarySql()) as SqlConnection | undefined;
|
|
106
|
+
if (!conn) throw new Error("no primary sql connection");
|
|
107
|
+
await conn.exec(`CREATE TABLE IF NOT EXISTS "documents" (
|
|
108
|
+
id text PRIMARY KEY,
|
|
109
|
+
tenant_id text NOT NULL,
|
|
110
|
+
title text NOT NULL
|
|
111
|
+
)`);
|
|
112
|
+
await conn.exec(`ALTER TABLE "documents" ENABLE ROW LEVEL SECURITY`);
|
|
113
|
+
await installOkeRlsHelpers((sql) => conn.exec(sql));
|
|
114
|
+
await conn.exec(
|
|
115
|
+
`CREATE POLICY tenant_tenant_id_all ON "documents"
|
|
116
|
+
AS PERMISSIVE FOR ALL TO public
|
|
117
|
+
USING (tenant_id = oke.tenant())
|
|
118
|
+
WITH CHECK (tenant_id = oke.tenant())`,
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
// Alice creates document in Acme
|
|
122
|
+
const createRes1 = await t.api.docs!.create!({ title: "Acme Roadmap" }, { as: userAcme });
|
|
123
|
+
expect(createRes1.error).toBeNull();
|
|
124
|
+
expect((createRes1.data as { tenantId: string | null }).tenantId).toBe("acme");
|
|
125
|
+
|
|
126
|
+
// Bob creates document in Globex
|
|
127
|
+
const createRes2 = await t.api.docs!.create!({ title: "Globex Secrets" }, { as: userGlobex });
|
|
128
|
+
expect(createRes2.error).toBeNull();
|
|
129
|
+
expect((createRes2.data as { tenantId: string | null }).tenantId).toBe("globex");
|
|
130
|
+
|
|
131
|
+
// Alice lists docs -> should only see Acme
|
|
132
|
+
const listAcme = await t.api.docs!.list!(undefined, { as: userAcme });
|
|
133
|
+
expect(listAcme.error).toBeNull();
|
|
134
|
+
expect(listAcme.data).toHaveLength(1);
|
|
135
|
+
expect((listAcme.data as { title: string }[])[0]!.title).toBe("Acme Roadmap");
|
|
136
|
+
|
|
137
|
+
// Bob lists docs -> should only see Globex
|
|
138
|
+
const listGlobex = await t.api.docs!.list!(undefined, { as: userGlobex });
|
|
139
|
+
expect(listGlobex.error).toBeNull();
|
|
140
|
+
expect(listGlobex.data).toHaveLength(1);
|
|
141
|
+
expect((listGlobex.data as { title: string }[])[0]!.title).toBe("Globex Secrets");
|
|
142
|
+
|
|
143
|
+
// The `{ tenant }` call override re-scopes RLS even when it differs from the
|
|
144
|
+
// principal's own `tenantId`. Carol belongs to Acme; forcing `tenant: "globex"`
|
|
145
|
+
// writes a Globex row (proving fx.tenant.id + RLS WITH CHECK re-scoped) and,
|
|
146
|
+
// through a distinct principal (no tier-1 cache-dim collision), reads only
|
|
147
|
+
// Globex rows back.
|
|
148
|
+
const carol = await t.auth.loginAs({ id: "carol", tenantId: "acme" });
|
|
149
|
+
|
|
150
|
+
const createOverride = await t.api.docs!.create!(
|
|
151
|
+
{ title: "Globex Carol" },
|
|
152
|
+
{ as: carol, tenant: "globex" },
|
|
153
|
+
);
|
|
154
|
+
expect(createOverride.error).toBeNull();
|
|
155
|
+
expect((createOverride.data as { tenantId: string | null }).tenantId).toBe("globex");
|
|
156
|
+
|
|
157
|
+
const listHome = await t.api.docs!.list!(undefined, { as: carol });
|
|
158
|
+
expect(listHome.error).toBeNull();
|
|
159
|
+
expect((listHome.data as { title: string }[]).length).toBe(1);
|
|
160
|
+
expect((listHome.data as { title: string }[])[0]!.title).toBe("Acme Roadmap");
|
|
161
|
+
|
|
162
|
+
// Distinct call identity keeps the tier-1 read-cache key apart from the
|
|
163
|
+
// acme-scoped list above (cache dims: flow, input, userId — tenant is a
|
|
164
|
+
// row-level RLS scope, not a cache dimension).
|
|
165
|
+
const dave = await t.auth.loginAs({ id: "dave", tenantId: "acme" });
|
|
166
|
+
const listOverride = await t.api.docs!.list!(undefined, { as: dave, tenant: "globex" });
|
|
167
|
+
expect(listOverride.error).toBeNull();
|
|
168
|
+
// Two Globex rows now: Bob's original + Carol's override write.
|
|
169
|
+
expect((listOverride.data as { title: string }[]).length).toBe(2);
|
|
170
|
+
const overrideTitles = (listOverride.data as { title: string }[]).map((r) => r.title).sort();
|
|
171
|
+
expect(overrideTitles).toEqual(["Globex Carol", "Globex Secrets"]);
|
|
172
|
+
|
|
173
|
+
await t.close();
|
|
174
|
+
});
|
|
175
|
+
});
|
package/src/testing.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test harness (`createTestApp`). Subpath: `okengine/testing` or `okengine/test`.
|
|
3
|
+
*
|
|
4
|
+
* Kept out of core/client bundles via a dedicated `dist/testing.js` build.
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
createTestApp,
|
|
10
|
+
type CreateTestAppOptions,
|
|
11
|
+
type LoginAsOptions,
|
|
12
|
+
type TestAi,
|
|
13
|
+
type TestApi,
|
|
14
|
+
type TestApiCall,
|
|
15
|
+
type TestApp,
|
|
16
|
+
type TestAuth,
|
|
17
|
+
type TestCallOptions,
|
|
18
|
+
type TestChannels,
|
|
19
|
+
type TestClock,
|
|
20
|
+
type TestCron,
|
|
21
|
+
type TestEffects,
|
|
22
|
+
type TestLiveHandlers,
|
|
23
|
+
type TestLiveUnsubscribe,
|
|
24
|
+
type TestSignals,
|
|
25
|
+
type TestUser,
|
|
26
|
+
} from "./test/create-test-app.ts";
|
package/src/upgrade/codemods.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* registry is the checklist.
|
|
7
7
|
*
|
|
8
8
|
* Environment-model migrations (`local`/`docker` → `dev`, sqlite removal)
|
|
9
|
-
* are documented only
|
|
9
|
+
* are documented only in the site docs configuration reference.
|
|
10
10
|
* No soft-compat rewriter for those.
|
|
11
11
|
*/
|
|
12
12
|
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Migrating environments"
|
|
3
|
-
description: "Move from local/docker/test/prod driver maps to the Docker-first dev/test/prod model."
|
|
4
|
-
icon: "ArrowRightLeft"
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
Older projects used four driver-map keys (`local` · `docker` · `test` · `prod`) and an optional
|
|
8
|
-
`oke mode` switch. Today there are three environments, `oke dev` always starts Docker Compose, and
|
|
9
|
-
SQLite-family drivers (`sqlite`, `libsql`) are gone.
|
|
10
|
-
|
|
11
|
-
There is **no** soft-compat and **no** upgrade codemod for this change. Edit `oke.config.ts` by
|
|
12
|
-
hand using this page.
|
|
13
|
-
|
|
14
|
-
<Callout title="The one rule">
|
|
15
|
-
Rename maps to `dev` / `test` / `prod`, pin `pglite` for SQL tests, delete `.oke/mode`, then run
|
|
16
|
-
`oke dev` / `oke test`.
|
|
17
|
-
</Callout>
|
|
18
|
-
|
|
19
|
-
## Quick start
|
|
20
|
-
|
|
21
|
-
<Steps>
|
|
22
|
-
|
|
23
|
-
<Step>
|
|
24
|
-
### Edit the three-key shape
|
|
25
|
-
|
|
26
|
-
```typescript title="oke.config.ts"
|
|
27
|
-
import { defineConfig } from "okengine/config";
|
|
28
|
-
|
|
29
|
-
export default defineConfig({
|
|
30
|
-
drivers: {
|
|
31
|
-
store: {
|
|
32
|
-
sql: { dev: "postgres", test: "pglite", prod: "postgres" },
|
|
33
|
-
kv: { dev: "redis", test: "memory", prod: "redis" },
|
|
34
|
-
},
|
|
35
|
-
},
|
|
36
|
-
});
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
</Step>
|
|
40
|
-
|
|
41
|
-
<Step>
|
|
42
|
-
### Drop mode and use the new commands
|
|
43
|
-
|
|
44
|
-
```bash title="Terminal"
|
|
45
|
-
rm -f .oke/mode # no longer read
|
|
46
|
-
oke dev # always Docker Compose
|
|
47
|
-
oke test # PGLite test posture (no Compose)
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
`oke mode` prints an error and exits — it was removed.
|
|
51
|
-
|
|
52
|
-
</Step>
|
|
53
|
-
|
|
54
|
-
</Steps>
|
|
55
|
-
|
|
56
|
-
## Key rename table
|
|
57
|
-
|
|
58
|
-
| Old key | New key | Notes |
|
|
59
|
-
| -------- | ------- | ------------------------------------------------ |
|
|
60
|
-
| `local` | `dev` | Compose laptop |
|
|
61
|
-
| `docker` | `dev` | Same Compose / prod-shaped protocols |
|
|
62
|
-
| `stack` | `dev` | Legacy alias |
|
|
63
|
-
| `test` | `test` | Unchanged; SQL must be `pglite` |
|
|
64
|
-
| `prod` | `prod` | Unchanged; missing `dev` still fills from `prod` |
|
|
65
|
-
|
|
66
|
-
## sqlite / libsql removal
|
|
67
|
-
|
|
68
|
-
| Old pin | Replacement |
|
|
69
|
-
| --------------------------------- | --------------------------------------------- |
|
|
70
|
-
| `sql.*: "sqlite"` / `"libsql"` | `dev` / `prod`: `postgres` |
|
|
71
|
-
| `sql.test: "sqlite"` / `"libsql"` | `test: "pglite"` |
|
|
72
|
-
| `sql.test: "memory"` | `test: "pglite"` (required by `defineConfig`) |
|
|
73
|
-
| `index.*: "libsql"` | `dev` / `prod`: `pgvector`; `test`: `memory` |
|
|
74
|
-
|
|
75
|
-
`OKE_SQLITE_URL` / `OKE_LIBSQL_URL` are unused — use `DATABASE_URL` (Compose Postgres) or
|
|
76
|
-
`OKE_PGLITE_URL` (`memory://` under `oke test`).
|
|
77
|
-
|
|
78
|
-
## Before / after
|
|
79
|
-
|
|
80
|
-
```typescript title="Before (removed)"
|
|
81
|
-
drivers: {
|
|
82
|
-
store: {
|
|
83
|
-
sql: { local: "sqlite", docker: "postgres", test: "memory", prod: "postgres" },
|
|
84
|
-
kv: { local: "memory", docker: "redis", test: "memory", prod: "redis" },
|
|
85
|
-
},
|
|
86
|
-
},
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
```typescript title="After"
|
|
90
|
-
drivers: {
|
|
91
|
-
store: {
|
|
92
|
-
sql: { dev: "postgres", test: "pglite", prod: "postgres" },
|
|
93
|
-
kv: { dev: "redis", test: "memory", prod: "redis" },
|
|
94
|
-
},
|
|
95
|
-
},
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
## CLI changes
|
|
99
|
-
|
|
100
|
-
| Old | New |
|
|
101
|
-
| ------------------------- | ----------------------------------------------- |
|
|
102
|
-
| `oke mode local\|docker` | Removed — error message points at `oke dev` |
|
|
103
|
-
| `oke dev --local` / `-l` | Removed — exits with guidance to use `oke test` |
|
|
104
|
-
| `oke dev` (local default) | Always Docker Compose |
|
|
105
|
-
| `oke dev --docker` / `-d` | Optional **role filter** only (still Compose) |
|
|
106
|
-
| — | `oke test` — `bun test` + PGLite posture |
|
|
107
|
-
|
|
108
|
-
Loading `oke.config.ts` with a `local:` env key or a `"sqlite"` pin fails immediately:
|
|
109
|
-
|
|
110
|
-
```text
|
|
111
|
-
Error: "local" is no longer a valid environment key in oke.config.ts.
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
```text
|
|
115
|
-
Error: "sqlite" is no longer a valid driver in oke.config.ts.
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
## Troubleshooting
|
|
119
|
-
|
|
120
|
-
<Accordions>
|
|
121
|
-
|
|
122
|
-
<Accordion title='CLI says "local" / "sqlite" is no longer valid'>
|
|
123
|
-
Edit `oke.config.ts` using the tables above. There is no automatic rewrite — fix the file, then
|
|
124
|
-
re-run the command.
|
|
125
|
-
</Accordion>
|
|
126
|
-
|
|
127
|
-
<Accordion title="defineConfig throws on sqlite, libsql, or non-pglite test SQL">
|
|
128
|
-
Those pins are hard errors. Fix the map, then restart `oke dev` / `oke test`. Exact messages are
|
|
129
|
-
documented under [Configuration · Safety](/docs/reference/configuration#safety-rules).
|
|
130
|
-
</Accordion>
|
|
131
|
-
|
|
132
|
-
</Accordions>
|
|
133
|
-
|
|
134
|
-
## Learn more
|
|
135
|
-
|
|
136
|
-
- [Configuration](/docs/reference/configuration) — full `oke.config.ts` reference
|
|
137
|
-
- [CLI Reference](/docs/reference/cli) — `oke dev` · `oke test`
|
|
138
|
-
- [Installation](/docs/get-started/installation) — Docker-first quick start
|
|
139
|
-
|
|
140
|
-
## Next
|
|
141
|
-
|
|
142
|
-
<Cards>
|
|
143
|
-
<Card
|
|
144
|
-
title="Configuration"
|
|
145
|
-
description="Drivers, images, db, ports."
|
|
146
|
-
href="/docs/reference/configuration"
|
|
147
|
-
/>
|
|
148
|
-
<Card
|
|
149
|
-
title="CLI Reference"
|
|
150
|
-
description="oke and create-oke commands."
|
|
151
|
-
href="/docs/reference/cli"
|
|
152
|
-
/>
|
|
153
|
-
<Card
|
|
154
|
-
title="Docker deployment"
|
|
155
|
-
description="Production compose shape."
|
|
156
|
-
href="/docs/deployment/docker"
|
|
157
|
-
/>
|
|
158
|
-
</Cards>
|