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/cli/dev.test.ts
CHANGED
|
@@ -7,15 +7,19 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { afterEach, describe, expect, test } from "bun:test";
|
|
10
|
-
import { mkdtemp } from "node:fs/promises";
|
|
10
|
+
import { mkdir, mkdtemp, readdir } from "node:fs/promises";
|
|
11
11
|
import { tmpdir } from "node:os";
|
|
12
12
|
import { join, resolve } from "node:path";
|
|
13
|
+
import {
|
|
14
|
+
ADOPT_BARREL_FILE,
|
|
15
|
+
generateAdoptBarrel,
|
|
16
|
+
writeAdoptBarrel,
|
|
17
|
+
} from "../compiler/generate-adopt.ts";
|
|
13
18
|
import type { Manifest } from "../manifest/types.ts";
|
|
14
19
|
import type { WideEvent } from "../runs/types.ts";
|
|
15
20
|
import { isDataEnvelope, MCP_DATA_KIND } from "../mcp/data.ts";
|
|
16
21
|
import { mintMcpSession } from "../mcp/session.ts";
|
|
17
22
|
import { runDev, type DevOptions, type DevSession } from "./dev.ts";
|
|
18
|
-
import { readDevMode, writeDevMode } from "./dev-mode.ts";
|
|
19
23
|
import { mcpContextFromConsole } from "./mcp-from-console.ts";
|
|
20
24
|
|
|
21
25
|
/** Repo public entry — absolute import so temp apps need no install. */
|
|
@@ -23,6 +27,45 @@ const OKE_INDEX = resolve(import.meta.dir, "../index.ts");
|
|
|
23
27
|
|
|
24
28
|
const SECRET = "oke-dev-mcp-integration-secret";
|
|
25
29
|
|
|
30
|
+
/** Minimal compose injectables — unit tests never shell out to Docker. */
|
|
31
|
+
const STUB_IMAGES = {
|
|
32
|
+
"store.sql": "postgres:16-alpine",
|
|
33
|
+
"store.kv": "redis:7-alpine",
|
|
34
|
+
} as const;
|
|
35
|
+
const STUB_CREDENTIALS = {
|
|
36
|
+
"store.sql": {
|
|
37
|
+
user: "oke",
|
|
38
|
+
password: "test-password-not-in-yaml",
|
|
39
|
+
database: "oke",
|
|
40
|
+
},
|
|
41
|
+
} as const;
|
|
42
|
+
|
|
43
|
+
function stubCompose(
|
|
44
|
+
overrides: Partial<
|
|
45
|
+
Pick<
|
|
46
|
+
DevOptions,
|
|
47
|
+
"images" | "credentials" | "composeUp" | "composeHealth" | "composeStop" | "noDbPush"
|
|
48
|
+
>
|
|
49
|
+
> = {},
|
|
50
|
+
): Pick<
|
|
51
|
+
DevOptions,
|
|
52
|
+
"images" | "credentials" | "composeUp" | "composeHealth" | "composeStop" | "noDbPush"
|
|
53
|
+
> {
|
|
54
|
+
return {
|
|
55
|
+
images: STUB_IMAGES,
|
|
56
|
+
credentials: STUB_CREDENTIALS,
|
|
57
|
+
composeUp: async () => {},
|
|
58
|
+
composeHealth: async () =>
|
|
59
|
+
new Map([
|
|
60
|
+
["store-sql", "ready"],
|
|
61
|
+
["store-kv", "ready"],
|
|
62
|
+
]),
|
|
63
|
+
composeStop: () => {},
|
|
64
|
+
noDbPush: true,
|
|
65
|
+
...overrides,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
26
69
|
const LIVE_MANIFEST: Manifest = {
|
|
27
70
|
oke: "1.0",
|
|
28
71
|
app: "dev-live",
|
|
@@ -72,6 +115,52 @@ describe("mcpContextFromConsole", () => {
|
|
|
72
115
|
});
|
|
73
116
|
});
|
|
74
117
|
|
|
118
|
+
/**
|
|
119
|
+
* Console for MCP tests — boot with `docker: false` so host `OKE_DOCKER=1`
|
|
120
|
+
* from compose stubs does not force redis/smtp docker URLs.
|
|
121
|
+
*/
|
|
122
|
+
async function serveTestConsole(
|
|
123
|
+
port: number,
|
|
124
|
+
cwd: string,
|
|
125
|
+
manifest: Manifest = LIVE_MANIFEST,
|
|
126
|
+
): Promise<{
|
|
127
|
+
readonly console: import("../console/server/app.ts").ConsoleAppHandle;
|
|
128
|
+
readonly port: number;
|
|
129
|
+
readonly stop: () => void;
|
|
130
|
+
}> {
|
|
131
|
+
const { createConsoleApp } = await import("../console/server/app.ts");
|
|
132
|
+
const handle = createConsoleApp({
|
|
133
|
+
cwd,
|
|
134
|
+
secret: SECRET,
|
|
135
|
+
silentClaim: true,
|
|
136
|
+
manifest,
|
|
137
|
+
});
|
|
138
|
+
await handle.app.boot({ env: "test", docker: false });
|
|
139
|
+
handle.state.listRuns = async () => {
|
|
140
|
+
const runs = handle.app.bootResult?.runs;
|
|
141
|
+
if (!runs) return [];
|
|
142
|
+
return runs.all();
|
|
143
|
+
};
|
|
144
|
+
const server = Bun.serve({
|
|
145
|
+
port,
|
|
146
|
+
hostname: "127.0.0.1",
|
|
147
|
+
fetch: (req) => handle.app.fetch(req),
|
|
148
|
+
});
|
|
149
|
+
const boundPort = server.port;
|
|
150
|
+
if (boundPort === undefined) {
|
|
151
|
+
server.stop(true);
|
|
152
|
+
throw new Error("test console: Bun.serve did not bind a port");
|
|
153
|
+
}
|
|
154
|
+
return {
|
|
155
|
+
console: handle,
|
|
156
|
+
port: boundPort,
|
|
157
|
+
stop() {
|
|
158
|
+
server.stop(true);
|
|
159
|
+
void handle.app.stop();
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
75
164
|
describe("oke dev MCP live wiring", () => {
|
|
76
165
|
let session: DevSession | undefined;
|
|
77
166
|
|
|
@@ -94,9 +183,11 @@ describe("oke dev MCP live wiring", () => {
|
|
|
94
183
|
consolePort: 0,
|
|
95
184
|
mcpPort: 0,
|
|
96
185
|
appPort: 0,
|
|
186
|
+
...stubCompose(),
|
|
97
187
|
startApp: async () => ({ stop() {} }),
|
|
98
188
|
regenClient: async () => {},
|
|
99
189
|
write: () => {},
|
|
190
|
+
serveConsole: async (port) => serveTestConsole(port, dir),
|
|
100
191
|
});
|
|
101
192
|
|
|
102
193
|
expect(result.code).toBe(0);
|
|
@@ -223,26 +314,18 @@ describe("oke dev MCP live wiring", () => {
|
|
|
223
314
|
mcpPort: 0,
|
|
224
315
|
appPort: 0,
|
|
225
316
|
manifest: LIVE_MANIFEST,
|
|
317
|
+
...stubCompose(),
|
|
226
318
|
startApp: async () => ({ stop() {} }),
|
|
227
319
|
regenClient: async () => {},
|
|
228
320
|
write: () => {},
|
|
229
321
|
serveConsole: async (port) => {
|
|
230
|
-
const
|
|
231
|
-
const server = await serveConsole({
|
|
232
|
-
port,
|
|
233
|
-
hostname: "127.0.0.1",
|
|
234
|
-
cwd: dir,
|
|
235
|
-
secret: SECRET,
|
|
236
|
-
silentClaim: true,
|
|
237
|
-
env: "dev",
|
|
238
|
-
manifest: LIVE_MANIFEST,
|
|
239
|
-
});
|
|
322
|
+
const server = await serveTestConsole(port, dir);
|
|
240
323
|
return {
|
|
241
324
|
console: server.console,
|
|
242
325
|
port: server.port,
|
|
243
326
|
stop() {
|
|
244
327
|
consoleStopped = true;
|
|
245
|
-
server.stop(
|
|
328
|
+
server.stop();
|
|
246
329
|
},
|
|
247
330
|
};
|
|
248
331
|
},
|
|
@@ -293,6 +376,7 @@ describe("oke dev docs MCP", () => {
|
|
|
293
376
|
consolePort: 0,
|
|
294
377
|
mcpPort: 0,
|
|
295
378
|
docsMcpPort: 0,
|
|
379
|
+
...stubCompose(),
|
|
296
380
|
startApp: async () => ({ stop() {} }),
|
|
297
381
|
regenClient: async () => {},
|
|
298
382
|
write: () => {},
|
|
@@ -366,6 +450,7 @@ describe("oke dev docs MCP", () => {
|
|
|
366
450
|
consolePort: 0,
|
|
367
451
|
mcpPort: 0,
|
|
368
452
|
docsMcpPort: 0,
|
|
453
|
+
...stubCompose(),
|
|
369
454
|
startApp: async () => ({ stop() {} }),
|
|
370
455
|
regenClient: async () => {},
|
|
371
456
|
write: (t) => {
|
|
@@ -421,7 +506,7 @@ export const app = oke({ name: "dev-hot", env: "test" }).adopt({ ping });
|
|
|
421
506
|
);
|
|
422
507
|
}
|
|
423
508
|
|
|
424
|
-
/** Stub Console + MCP so boot/hot tests isolate the app child. */
|
|
509
|
+
/** Stub Console + MCP + compose so boot/hot tests isolate the app child. */
|
|
425
510
|
function stubSurfaces(): Pick<
|
|
426
511
|
DevOptions,
|
|
427
512
|
| "serveConsole"
|
|
@@ -431,6 +516,12 @@ function stubSurfaces(): Pick<
|
|
|
431
516
|
| "write"
|
|
432
517
|
| "silentClaim"
|
|
433
518
|
| "keepAlive"
|
|
519
|
+
| "images"
|
|
520
|
+
| "credentials"
|
|
521
|
+
| "composeUp"
|
|
522
|
+
| "composeHealth"
|
|
523
|
+
| "composeStop"
|
|
524
|
+
| "noDbPush"
|
|
434
525
|
> {
|
|
435
526
|
return {
|
|
436
527
|
silentClaim: true,
|
|
@@ -440,6 +531,7 @@ function stubSurfaces(): Pick<
|
|
|
440
531
|
serveConsole: async () => ({ stop() {} }),
|
|
441
532
|
serveMcp: async () => ({ stop() {} }),
|
|
442
533
|
serveDocsMcp: async () => ({ stop() {} }),
|
|
534
|
+
...stubCompose(),
|
|
443
535
|
};
|
|
444
536
|
}
|
|
445
537
|
|
|
@@ -544,109 +636,133 @@ describe("oke dev hot reload", () => {
|
|
|
544
636
|
}, 60_000);
|
|
545
637
|
});
|
|
546
638
|
|
|
547
|
-
describe("oke dev
|
|
548
|
-
test("
|
|
549
|
-
const dir = await mkdtemp(join(tmpdir(), "oke-dev-
|
|
550
|
-
await
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
639
|
+
describe("oke dev syncAdoptBarrel atomic write", () => {
|
|
640
|
+
test("default path regenerates generated.ts and leaves no .tmp behind", async () => {
|
|
641
|
+
const dir = await mkdtemp(join(tmpdir(), "oke-dev-adopt-atomic-"));
|
|
642
|
+
await mkdir(join(dir, "src/flows/notes"), { recursive: true });
|
|
643
|
+
await Bun.write(join(dir, "src/flows/notes/index.ts"), "export {};\n");
|
|
644
|
+
await Bun.write(join(dir, "src/app.ts"), "export {};\n");
|
|
645
|
+
await Bun.write(join(dir, "src/flows", ADOPT_BARREL_FILE), "// stale stub\n");
|
|
646
|
+
|
|
647
|
+
const { code } = await runDev({
|
|
554
648
|
cwd: dir,
|
|
555
649
|
dryRun: true,
|
|
556
650
|
stdinIsTTY: false,
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
return "docker";
|
|
560
|
-
},
|
|
561
|
-
composeUp: async () => {
|
|
562
|
-
composeCalls++;
|
|
563
|
-
},
|
|
651
|
+
images: STUB_IMAGES,
|
|
652
|
+
credentials: STUB_CREDENTIALS,
|
|
564
653
|
write: () => {},
|
|
565
654
|
});
|
|
566
655
|
expect(code).toBe(0);
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
expect(
|
|
656
|
+
|
|
657
|
+
const barrelPath = join(dir, "src/flows", ADOPT_BARREL_FILE);
|
|
658
|
+
const text = await Bun.file(barrelPath).text();
|
|
659
|
+
expect(text).toContain('export * as notes from "./notes/index.ts";');
|
|
660
|
+
expect(text).not.toContain("stale stub");
|
|
661
|
+
expect(await Bun.file(`${barrelPath}.tmp`).exists()).toBe(false);
|
|
662
|
+
const leftovers = (await readdir(join(dir, "src/flows"))).filter((f) => f.includes(".tmp"));
|
|
663
|
+
expect(leftovers).toEqual([]);
|
|
571
664
|
});
|
|
572
665
|
|
|
573
|
-
test("
|
|
574
|
-
const dir = await mkdtemp(join(tmpdir(), "oke-dev-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
const
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
expect(
|
|
588
|
-
|
|
589
|
-
|
|
666
|
+
test("writeAdoptBarrel uses temp then rename — concurrent readers never see a torn file", async () => {
|
|
667
|
+
const dir = await mkdtemp(join(tmpdir(), "oke-dev-adopt-race-"));
|
|
668
|
+
const flowsDir = join(dir, "src/flows");
|
|
669
|
+
await mkdir(flowsDir, { recursive: true });
|
|
670
|
+
const target = join(flowsDir, ADOPT_BARREL_FILE);
|
|
671
|
+
|
|
672
|
+
// Two complete, same-length payloads so a mid-write truncate would yield
|
|
673
|
+
// mixed or short content that fails both equality checks.
|
|
674
|
+
const markerA = "A";
|
|
675
|
+
const markerB = "B";
|
|
676
|
+
const body = (marker: string) => `// ${marker}\n` + `${marker.repeat(64)}\n`.repeat(2_000);
|
|
677
|
+
const payloadA = body(markerA);
|
|
678
|
+
const payloadB = body(markerB);
|
|
679
|
+
expect(payloadA.length).toBe(payloadB.length);
|
|
680
|
+
expect(payloadA).not.toBe(payloadB);
|
|
681
|
+
|
|
682
|
+
await writeAdoptBarrel(dir, payloadA);
|
|
683
|
+
expect(await Bun.file(target).text()).toBe(payloadA);
|
|
684
|
+
|
|
685
|
+
const reads: string[] = [];
|
|
686
|
+
let stop = false;
|
|
687
|
+
const reader = (async () => {
|
|
688
|
+
while (!stop) {
|
|
689
|
+
try {
|
|
690
|
+
reads.push(await Bun.file(target).text());
|
|
691
|
+
} catch {
|
|
692
|
+
// Target briefly missing only if rename races a delete — ignore.
|
|
693
|
+
}
|
|
694
|
+
// Yield so writers interleave; Bun.sleep(0) is enough on this loop.
|
|
695
|
+
await Bun.sleep(0);
|
|
696
|
+
}
|
|
697
|
+
})();
|
|
698
|
+
|
|
699
|
+
for (let i = 0; i < 80; i++) {
|
|
700
|
+
await writeAdoptBarrel(dir, i % 2 === 0 ? payloadB : payloadA);
|
|
701
|
+
}
|
|
702
|
+
stop = true;
|
|
703
|
+
await reader;
|
|
704
|
+
|
|
705
|
+
expect(reads.length).toBeGreaterThan(10);
|
|
706
|
+
for (const sample of reads) {
|
|
707
|
+
// Every observation is a complete prior or complete next payload —
|
|
708
|
+
// never a truncated prefix, never a mix of A/B markers.
|
|
709
|
+
const ok = sample === payloadA || sample === payloadB;
|
|
710
|
+
expect(ok).toBe(true);
|
|
711
|
+
expect(sample.length).toBe(payloadA.length);
|
|
712
|
+
expect(sample.includes(markerA) && sample.includes(markerB)).toBe(false);
|
|
713
|
+
}
|
|
714
|
+
expect(await Bun.file(`${target}.tmp`).exists()).toBe(false);
|
|
715
|
+
|
|
716
|
+
// Same helper the default `oke dev` path uses end-to-end.
|
|
717
|
+
const { source } = await generateAdoptBarrel({ rootDir: dir });
|
|
718
|
+
await writeAdoptBarrel(dir, source);
|
|
719
|
+
expect(await Bun.file(target).text()).toBe(source);
|
|
590
720
|
});
|
|
721
|
+
});
|
|
591
722
|
|
|
592
|
-
|
|
593
|
-
|
|
723
|
+
describe("oke dev Docker-first", () => {
|
|
724
|
+
test("dryRun always plans compose (no mode ask)", async () => {
|
|
725
|
+
const dir = await mkdtemp(join(tmpdir(), "oke-dev-always-compose-"));
|
|
594
726
|
await Bun.write(join(dir, "src/app.ts"), "export {}\n");
|
|
595
|
-
let askCalls = 0;
|
|
596
727
|
let composeCalls = 0;
|
|
597
728
|
const { code, plan } = await runDev({
|
|
598
729
|
cwd: dir,
|
|
599
730
|
dryRun: true,
|
|
600
|
-
stdinIsTTY:
|
|
601
|
-
images:
|
|
602
|
-
credentials:
|
|
603
|
-
"store.sql": {
|
|
604
|
-
user: "oke",
|
|
605
|
-
password: "test-password-not-in-yaml",
|
|
606
|
-
database: "oke",
|
|
607
|
-
},
|
|
608
|
-
},
|
|
609
|
-
ask: async () => {
|
|
610
|
-
askCalls++;
|
|
611
|
-
return "docker";
|
|
612
|
-
},
|
|
731
|
+
stdinIsTTY: false,
|
|
732
|
+
images: STUB_IMAGES,
|
|
733
|
+
credentials: STUB_CREDENTIALS,
|
|
613
734
|
composeUp: async () => {
|
|
614
735
|
composeCalls++;
|
|
615
736
|
},
|
|
616
737
|
write: () => {},
|
|
617
738
|
});
|
|
618
739
|
expect(code).toBe(0);
|
|
619
|
-
expect(askCalls).toBe(1);
|
|
620
740
|
expect(composeCalls).toBe(0);
|
|
621
|
-
expect(
|
|
622
|
-
expect(plan?.stackRoles).toEqual(["store.sql"]);
|
|
741
|
+
expect(plan?.stackRoles).toEqual(["store.sql", "store.kv"]);
|
|
623
742
|
});
|
|
624
743
|
|
|
625
|
-
test("
|
|
626
|
-
const dir = await mkdtemp(join(tmpdir(), "oke-dev-
|
|
744
|
+
test("role filter -d store.sql plans only that role", async () => {
|
|
745
|
+
const dir = await mkdtemp(join(tmpdir(), "oke-dev-roles-"));
|
|
627
746
|
await Bun.write(join(dir, "src/app.ts"), "export {}\n");
|
|
628
|
-
let askCalls = 0;
|
|
629
747
|
const { code, plan } = await runDev({
|
|
630
748
|
cwd: dir,
|
|
631
749
|
dryRun: true,
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
750
|
+
stdinIsTTY: false,
|
|
751
|
+
docker: ["store.sql"],
|
|
752
|
+
images: {
|
|
753
|
+
"store.sql": "postgres:16-alpine",
|
|
754
|
+
"store.kv": "redis:7-alpine",
|
|
637
755
|
},
|
|
756
|
+
credentials: STUB_CREDENTIALS,
|
|
638
757
|
write: () => {},
|
|
639
758
|
});
|
|
640
759
|
expect(code).toBe(0);
|
|
641
|
-
expect(
|
|
642
|
-
expect(plan?.stackRoles).toBeNull();
|
|
643
|
-
expect(await readDevMode(dir)).toBeNull();
|
|
760
|
+
expect(plan?.stackRoles).toEqual(["store.sql"]);
|
|
644
761
|
});
|
|
645
762
|
|
|
646
|
-
test("session stop calls composeStop after a successful
|
|
763
|
+
test("session stop calls composeStop after a successful compose up", async () => {
|
|
647
764
|
const dir = await mkdtemp(join(tmpdir(), "oke-dev-compose-stop-"));
|
|
648
765
|
await Bun.write(join(dir, "src/app.ts"), "export {}\n");
|
|
649
|
-
await writeDevMode(dir, "docker");
|
|
650
766
|
let upCalls = 0;
|
|
651
767
|
let stopCalls = 0;
|
|
652
768
|
let stoppedFiles: readonly string[] | undefined;
|
|
@@ -659,26 +775,20 @@ describe("oke dev mode resolution", () => {
|
|
|
659
775
|
const result = await runDev({
|
|
660
776
|
cwd: dir,
|
|
661
777
|
stdinIsTTY: false,
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
password: "test-password-not-in-yaml",
|
|
667
|
-
database: "oke",
|
|
778
|
+
...stubCompose({
|
|
779
|
+
composeUp: async (files) => {
|
|
780
|
+
upCalls++;
|
|
781
|
+
expect(files.length).toBeGreaterThan(0);
|
|
668
782
|
},
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
},
|
|
678
|
-
composeStop: (files) => {
|
|
679
|
-
stopCalls++;
|
|
680
|
-
stoppedFiles = files;
|
|
681
|
-
},
|
|
783
|
+
composeHealth: async ({ onUpdate }) => {
|
|
784
|
+
onUpdate?.("store-sql", "ready");
|
|
785
|
+
return new Map([["store-sql", "ready"]]);
|
|
786
|
+
},
|
|
787
|
+
composeStop: (files) => {
|
|
788
|
+
stopCalls++;
|
|
789
|
+
stoppedFiles = files;
|
|
790
|
+
},
|
|
791
|
+
}),
|
|
682
792
|
startApp: async () => ({ stop() {} }),
|
|
683
793
|
serveConsole: async () => ({ stop() {} }),
|
|
684
794
|
regenClient: async () => {},
|
|
@@ -703,10 +813,9 @@ describe("oke dev mode resolution", () => {
|
|
|
703
813
|
}
|
|
704
814
|
});
|
|
705
815
|
|
|
706
|
-
test("
|
|
707
|
-
const dir = await mkdtemp(join(tmpdir(), "oke-dev-
|
|
816
|
+
test("compose failure exits loudly (no silent downgrade)", async () => {
|
|
817
|
+
const dir = await mkdtemp(join(tmpdir(), "oke-dev-compose-fail-"));
|
|
708
818
|
await Bun.write(join(dir, "src/app.ts"), "export {}\n");
|
|
709
|
-
await writeDevMode(dir, "docker");
|
|
710
819
|
const lines: string[] = [];
|
|
711
820
|
const origErr = console.error;
|
|
712
821
|
console.error = (...args: unknown[]) => {
|
|
@@ -716,17 +825,11 @@ describe("oke dev mode resolution", () => {
|
|
|
716
825
|
const { code } = await runDev({
|
|
717
826
|
cwd: dir,
|
|
718
827
|
stdinIsTTY: false,
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
user: "oke",
|
|
723
|
-
password: "test-password-not-in-yaml",
|
|
724
|
-
database: "oke",
|
|
828
|
+
...stubCompose({
|
|
829
|
+
composeUp: async () => {
|
|
830
|
+
throw new Error("compose boom");
|
|
725
831
|
},
|
|
726
|
-
},
|
|
727
|
-
composeUp: async () => {
|
|
728
|
-
throw new Error("compose boom");
|
|
729
|
-
},
|
|
832
|
+
}),
|
|
730
833
|
startApp: async () => ({ stop() {} }),
|
|
731
834
|
serveConsole: async () => ({ stop() {} }),
|
|
732
835
|
regenClient: async () => {},
|
|
@@ -734,7 +837,36 @@ describe("oke dev mode resolution", () => {
|
|
|
734
837
|
keepAlive: false,
|
|
735
838
|
});
|
|
736
839
|
expect(code).toBe(1);
|
|
737
|
-
expect(lines.some((l) => l.includes("
|
|
840
|
+
expect(lines.some((l) => l.includes("Docker Compose failed"))).toBe(true);
|
|
841
|
+
} finally {
|
|
842
|
+
console.error = origErr;
|
|
843
|
+
}
|
|
844
|
+
});
|
|
845
|
+
|
|
846
|
+
test("missing Docker daemon fails fast with a clear error", async () => {
|
|
847
|
+
const dir = await mkdtemp(join(tmpdir(), "oke-dev-no-daemon-"));
|
|
848
|
+
await Bun.write(join(dir, "src/app.ts"), "export {}\n");
|
|
849
|
+
const lines: string[] = [];
|
|
850
|
+
const origErr = console.error;
|
|
851
|
+
console.error = (...args: unknown[]) => {
|
|
852
|
+
lines.push(args.map(String).join(" "));
|
|
853
|
+
};
|
|
854
|
+
try {
|
|
855
|
+
const { code } = await runDev({
|
|
856
|
+
cwd: dir,
|
|
857
|
+
stdinIsTTY: false,
|
|
858
|
+
images: STUB_IMAGES,
|
|
859
|
+
credentials: STUB_CREDENTIALS,
|
|
860
|
+
assertDocker: async () => {
|
|
861
|
+
throw new Error(
|
|
862
|
+
"oke dev: Docker daemon unavailable — start Docker Desktop (or the Docker daemon) and retry",
|
|
863
|
+
);
|
|
864
|
+
},
|
|
865
|
+
write: () => {},
|
|
866
|
+
keepAlive: false,
|
|
867
|
+
});
|
|
868
|
+
expect(code).toBe(1);
|
|
869
|
+
expect(lines.some((l) => l.includes("Docker daemon unavailable"))).toBe(true);
|
|
738
870
|
} finally {
|
|
739
871
|
console.error = origErr;
|
|
740
872
|
}
|