okengine 0.10.1 → 0.10.3

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.
Files changed (141) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/site/content/docs/ai/mcp.mdx +0 -1
  4. package/site/content/docs/elements/ai.mdx +0 -6
  5. package/site/content/docs/elements/channel.mdx +0 -6
  6. package/site/content/docs/elements/clock.mdx +2 -8
  7. package/site/content/docs/elements/flow.mdx +10 -17
  8. package/site/content/docs/elements/gate.mdx +4 -10
  9. package/site/content/docs/elements/signal.mdx +4 -13
  10. package/site/content/docs/elements/store.mdx +9 -16
  11. package/site/content/docs/elements/vault.mdx +1 -7
  12. package/site/content/docs/get-started/basic-usage.mdx +1 -9
  13. package/site/content/docs/get-started/introduction.mdx +1 -1
  14. package/site/content/docs/get-started/why.mdx +1 -2
  15. package/site/content/docs/index.mdx +0 -1
  16. package/site/content/docs/meta.json +0 -1
  17. package/site/content/docs/reference/cli.md +12 -12
  18. package/site/content/docs/reference/fx.mdx +6 -7
  19. package/src/auth/auth.test.ts +1 -2
  20. package/src/auth/bindings.ts +5 -15
  21. package/src/auth/gate-auth.test.ts +2 -2
  22. package/src/cli/ai-setup/ai-setup.test.ts +3 -1
  23. package/src/cli/ai-setup/apply.ts +13 -0
  24. package/src/cli/build.test.ts +67 -0
  25. package/src/cli/build.ts +33 -0
  26. package/src/cli/db-seed.ts +1 -1
  27. package/src/cli/dev-controls.test.ts +43 -48
  28. package/src/cli/dev-controls.ts +23 -172
  29. package/src/cli/dev.test.ts +90 -5
  30. package/src/cli/dev.ts +39 -16
  31. package/src/cli/doctor.ts +98 -5
  32. package/src/cli/load-config.images.test.ts +31 -1
  33. package/src/cli/load-config.ts +2 -2
  34. package/src/cli/safe-defaults.test.ts +1 -1
  35. package/src/client/notes-contract.test.ts +3 -4
  36. package/src/compiler/aot.test.ts +1 -2
  37. package/src/compiler/extract.test.ts +76 -21
  38. package/src/compiler/extract.ts +15 -3
  39. package/src/compiler/fixtures/raw/raw-unannotated.ts +2 -4
  40. package/src/compiler/fixtures/skyport/oke.config.ts +4 -2
  41. package/src/compiler/fixtures/skyport/src/flows/bookings/index.ts +4 -8
  42. package/src/compiler/fixtures/skyport/src/flows/payments/index.ts +1 -2
  43. package/src/compiler/fixtures/skyport/src/flows/support/index.ts +1 -2
  44. package/src/compiler/fixtures/skyport.expected.json +3 -3
  45. package/src/compiler/fixtures/triggers/five-triggers.ts +5 -10
  46. package/src/compiler/generate-adopt.test.ts +85 -0
  47. package/src/compiler/generate-adopt.ts +111 -0
  48. package/src/config/driver-defaults.test.ts +122 -0
  49. package/src/config/driver-defaults.ts +186 -0
  50. package/src/config/index.ts +97 -7
  51. package/src/console/server/dry-run.audit.test.ts +2 -2
  52. package/src/console/server/flows.ts +50 -150
  53. package/src/docker/compose.ts +13 -3
  54. package/src/docker/images-config.test.ts +168 -0
  55. package/src/docker/recipes/llama-cpp.ts +10 -1
  56. package/src/docker/stack-id.ts +1 -0
  57. package/src/elements/channel/declare.ts +27 -1
  58. package/src/elements/clock/chaos-child.ts +3 -6
  59. package/src/elements/clock/chaos.test.ts +1 -2
  60. package/src/elements/clock.test.ts +2 -4
  61. package/src/elements/signal/declare.ts +25 -1
  62. package/src/elements/store/declare.ts +27 -1
  63. package/src/elements/store/resource.ts +6 -11
  64. package/src/elements/store/upsert-app.test.ts +1 -2
  65. package/src/elements/vault/declare.ts +29 -1
  66. package/src/kernel/adopt-barrel-fresh.test.ts +103 -0
  67. package/src/kernel/app.ts +66 -9
  68. package/src/kernel/auto-registry.test.ts +198 -0
  69. package/src/kernel/boot-bind/channel.ts +12 -4
  70. package/src/kernel/boot-bind/clock.ts +3 -3
  71. package/src/kernel/boot-bind/gate.ts +7 -4
  72. package/src/kernel/boot-bind/honor-config.test.ts +5 -5
  73. package/src/kernel/boot-bind/journal.ts +3 -3
  74. package/src/kernel/boot-bind/signal.ts +3 -1
  75. package/src/kernel/boot-bind/store.test.ts +19 -0
  76. package/src/kernel/boot-bind/store.ts +24 -9
  77. package/src/kernel/boot-bind/vault.ts +3 -3
  78. package/src/kernel/boot.test.ts +19 -15
  79. package/src/kernel/boot.ts +81 -1
  80. package/src/kernel/call.test.ts +5 -10
  81. package/src/kernel/compensate.test.ts +3 -6
  82. package/src/kernel/concurrency.test.ts +3 -5
  83. package/src/kernel/correlation.test.ts +4 -8
  84. package/src/kernel/edge.test.ts +1 -1
  85. package/src/kernel/effects-stamping.test.ts +4 -7
  86. package/src/kernel/element-registries.ts +27 -0
  87. package/src/kernel/errors.ts +11 -0
  88. package/src/kernel/flow.test.ts +8 -15
  89. package/src/kernel/flow.ts +12 -14
  90. package/src/kernel/hook-timing.test.ts +2 -2
  91. package/src/kernel/hooks.test.ts +5 -10
  92. package/src/kernel/horizontal-child.ts +5 -10
  93. package/src/kernel/journal-boot.test.ts +2 -4
  94. package/src/kernel/pipeline.test.ts +6 -12
  95. package/src/kernel/plugin/capabilities.test.ts +1 -1
  96. package/src/kernel/plugin/decorate.test.ts +3 -8
  97. package/src/kernel/plugin/scoping.test.ts +6 -16
  98. package/src/kernel/plugin-elements.test.ts +1 -1
  99. package/src/kernel/plugin-needs.test.ts +1 -1
  100. package/src/kernel/ready.test.ts +1 -2
  101. package/src/kernel/registry-isolation.test.ts +5 -5
  102. package/src/kernel/triggers.ts +1 -1
  103. package/src/plugins/anonymous.ts +1 -3
  104. package/src/plugins/compression.test.ts +6 -8
  105. package/src/plugins/config-source.test.ts +1 -1
  106. package/src/plugins/config-source.ts +1 -2
  107. package/src/plugins/cors.test.ts +10 -10
  108. package/src/plugins/csrf.test.ts +2 -2
  109. package/src/plugins/headers.test.ts +14 -15
  110. package/src/plugins/ip-allowlist.test.ts +9 -9
  111. package/src/plugins/magic-link.ts +2 -6
  112. package/src/plugins/maintenance-mode.test.ts +6 -6
  113. package/src/plugins/otp.ts +5 -15
  114. package/src/plugins/passkey.ts +4 -12
  115. package/src/plugins/two-factor.ts +3 -9
  116. package/src/plugins/username.ts +2 -6
  117. package/src/release/measure.ts +1 -1
  118. package/src/runs/runs.test.ts +3 -5
  119. package/src/runtime/serve.test.ts +2 -4
  120. package/src/test/create-test-app.test.ts +3 -7
  121. package/src/test/provisions.integration.test.ts +4 -9
  122. package/src/test/reset-element-registries.ts +31 -0
  123. package/site/content/docs/console/access.mdx +0 -29
  124. package/site/content/docs/console/ai.mdx +0 -35
  125. package/site/content/docs/console/architecture.mdx +0 -35
  126. package/site/content/docs/console/channels.mdx +0 -37
  127. package/site/content/docs/console/clock.mdx +0 -51
  128. package/site/content/docs/console/flows.mdx +0 -31
  129. package/site/content/docs/console/gates.mdx +0 -73
  130. package/site/content/docs/console/index.mdx +0 -54
  131. package/site/content/docs/console/manifest-diff.mdx +0 -34
  132. package/site/content/docs/console/meta.json +0 -24
  133. package/site/content/docs/console/overview.mdx +0 -40
  134. package/site/content/docs/console/plugins.mdx +0 -41
  135. package/site/content/docs/console/privacy.mdx +0 -32
  136. package/site/content/docs/console/runs.mdx +0 -50
  137. package/site/content/docs/console/signals.mdx +0 -40
  138. package/site/content/docs/console/store.mdx +0 -32
  139. package/site/content/docs/console/tenancy.mdx +0 -32
  140. package/site/content/docs/console/traces.mdx +0 -38
  141. package/site/content/docs/console/vault.mdx +0 -41
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Real, already-established default driver ids per {@link ConfigEnv} —
3
+ * one source of truth for every driver map that has a single default table.
4
+ *
5
+ * These mirror the literal fallbacks that used to live inline in each
6
+ * `src/kernel/boot-bind/*.ts` resolver (`docker ? "postgres" : "memory"`,
7
+ * `env === "test" ? "frozen" : "memory"`, …). Kept here so
8
+ * {@link mergeEnvDriverMap} has one real map to merge a developer's partial
9
+ * override onto, instead of every resolver re-deriving its own default.
10
+ *
11
+ * `store.index`, `channel.whatsapp` / `push`, and `ai` are intentionally
12
+ * absent — they don't have one established default across all four envs
13
+ * (index/whatsapp/push default to nothing until configured; ai has no prod
14
+ * default at all and must be declared) and keep using
15
+ * {@link resolveDriverId}'s legacy cascade.
16
+ * @module
17
+ */
18
+
19
+ import {
20
+ mergeEnvDriverMap,
21
+ normalizeEnvDriverMap,
22
+ type DriversConfig,
23
+ type EnvDriverMap,
24
+ type RawEnvDriverMap,
25
+ } from "./index.ts";
26
+
27
+ /** `drivers.store.sql` — Postgres for docker/prod, in-memory otherwise. */
28
+ export const STORE_SQL_DEFAULTS: EnvDriverMap = {
29
+ local: "memory",
30
+ docker: "postgres",
31
+ test: "memory",
32
+ prod: "postgres",
33
+ };
34
+
35
+ /** `drivers.store.kv` — Redis for docker/prod, in-memory otherwise. */
36
+ export const STORE_KV_DEFAULTS: EnvDriverMap = {
37
+ local: "memory",
38
+ docker: "redis",
39
+ test: "memory",
40
+ prod: "redis",
41
+ };
42
+
43
+ /** `drivers.store.files` — S3 for docker/prod, in-memory otherwise. */
44
+ export const STORE_FILES_DEFAULTS: EnvDriverMap = {
45
+ local: "memory",
46
+ docker: "s3",
47
+ test: "memory",
48
+ prod: "s3",
49
+ };
50
+
51
+ /** `drivers.signal` — in-memory bus everywhere. */
52
+ export const SIGNAL_DEFAULTS: EnvDriverMap = {
53
+ local: "memory",
54
+ docker: "memory",
55
+ test: "memory",
56
+ prod: "memory",
57
+ };
58
+
59
+ /** `drivers.clock` — frozen test clock in `test`, in-memory cron elsewhere. */
60
+ export const CLOCK_DEFAULTS: EnvDriverMap = {
61
+ local: "memory",
62
+ docker: "memory",
63
+ test: "frozen",
64
+ prod: "memory",
65
+ };
66
+
67
+ /** `drivers.journal` — in-memory durable-run store everywhere. */
68
+ export const JOURNAL_DEFAULTS: EnvDriverMap = {
69
+ local: "memory",
70
+ docker: "memory",
71
+ test: "memory",
72
+ prod: "memory",
73
+ };
74
+
75
+ /** `drivers.vault` — OS env vars everywhere except `test` (in-memory). */
76
+ export const VAULT_DEFAULTS: EnvDriverMap = {
77
+ local: "env",
78
+ docker: "env",
79
+ test: "memory",
80
+ prod: "env",
81
+ };
82
+
83
+ /** `drivers.channel.email` — SMTP for docker/prod, console inbox otherwise. */
84
+ export const CHANNEL_EMAIL_DEFAULTS: EnvDriverMap = {
85
+ local: "console",
86
+ docker: "smtp",
87
+ test: "console",
88
+ prod: "smtp",
89
+ };
90
+
91
+ /**
92
+ * `drivers.channel.sms` — no default provider in any env; SMS is opt-in
93
+ * only (an unconfigured env simply gets no SMS channel).
94
+ */
95
+ export const CHANNEL_SMS_DEFAULTS: EnvDriverMap = {};
96
+
97
+ /**
98
+ * Effective default map for a driver whose real default also depends on the
99
+ * boot-time `docker` flag (real docker-compose infra available), not just
100
+ * the active {@link ConfigEnv} key — `store.sql` / `store.kv` /
101
+ * `store.files` / `channel.email` / the Gate KV facet. Real usage always
102
+ * pairs `docker: true` with `env: "docker"` / `"prod"`, so the static table
103
+ * (`docker`/`prod` → real infra id) applies as-is; with the flag `false`
104
+ * (`oke dev -l`, `test`, or a boot that deliberately decouples `env` from
105
+ * infra availability) every key falls back to the same safe, no-external-
106
+ * deps id the real table already uses for `test`.
107
+ *
108
+ * @param defaults - Real per-env default table (its `docker`/`prod` slots
109
+ * assume real infra is actually up)
110
+ * @param docker - Boot-time docker/compose-infra flag
111
+ */
112
+ export function dockerFlagDefaults(defaults: EnvDriverMap, docker: boolean): EnvDriverMap {
113
+ if (docker) return defaults;
114
+ const safe = defaults.test;
115
+ return { local: safe, docker: safe, test: safe, prod: safe };
116
+ }
117
+
118
+ /** Every driver map with one established default table, grouped by element. */
119
+ export const DRIVER_DEFAULTS = {
120
+ store: {
121
+ sql: STORE_SQL_DEFAULTS,
122
+ kv: STORE_KV_DEFAULTS,
123
+ files: STORE_FILES_DEFAULTS,
124
+ },
125
+ signal: SIGNAL_DEFAULTS,
126
+ clock: CLOCK_DEFAULTS,
127
+ journal: JOURNAL_DEFAULTS,
128
+ vault: VAULT_DEFAULTS,
129
+ channel: {
130
+ email: CHANNEL_EMAIL_DEFAULTS,
131
+ sms: CHANNEL_SMS_DEFAULTS,
132
+ },
133
+ } as const;
134
+
135
+ /**
136
+ * Every driver map from {@link DRIVER_DEFAULTS}, fully resolved — the
137
+ * developer's `oke.config.ts` override merged onto the real default,
138
+ * per-key, for all four {@link ConfigEnv} slots at once. This is the "full
139
+ * picture" `oke doctor` prints: what boot actually uses for every env, even
140
+ * when the config on disk only pins one key.
141
+ */
142
+ export interface EffectiveDriversConfig {
143
+ readonly store: {
144
+ readonly sql: EnvDriverMap;
145
+ readonly kv: EnvDriverMap;
146
+ readonly files: EnvDriverMap;
147
+ };
148
+ readonly signal: EnvDriverMap;
149
+ readonly clock: EnvDriverMap;
150
+ readonly journal: EnvDriverMap;
151
+ readonly vault: EnvDriverMap;
152
+ readonly channel: {
153
+ readonly email: EnvDriverMap;
154
+ readonly sms: EnvDriverMap;
155
+ };
156
+ }
157
+
158
+ /**
159
+ * Merge every driver map in {@link DRIVER_DEFAULTS} against the matching
160
+ * slot of a loaded `oke.config.ts` `drivers` block.
161
+ *
162
+ * @param drivers - `drivers` block from a loaded `oke.config.ts` (already
163
+ * normalized if it came through `defineConfig`; normalized again here so
164
+ * an un-normalized/raw block is still handled)
165
+ */
166
+ export function resolveEffectiveDrivers(
167
+ drivers: DriversConfig | undefined,
168
+ ): EffectiveDriversConfig {
169
+ const merge = (map: EnvDriverMap | undefined, defaults: EnvDriverMap) =>
170
+ mergeEnvDriverMap(normalizeEnvDriverMap(map as RawEnvDriverMap), defaults);
171
+ return {
172
+ store: {
173
+ sql: merge(drivers?.store?.sql, STORE_SQL_DEFAULTS),
174
+ kv: merge(drivers?.store?.kv, STORE_KV_DEFAULTS),
175
+ files: merge(drivers?.store?.files, STORE_FILES_DEFAULTS),
176
+ },
177
+ signal: merge(drivers?.signal, SIGNAL_DEFAULTS),
178
+ clock: merge(drivers?.clock, CLOCK_DEFAULTS),
179
+ journal: merge(drivers?.journal, JOURNAL_DEFAULTS),
180
+ vault: merge(drivers?.vault, VAULT_DEFAULTS),
181
+ channel: {
182
+ email: merge(drivers?.channel?.email, CHANNEL_EMAIL_DEFAULTS),
183
+ sms: merge(drivers?.channel?.sms, CHANNEL_SMS_DEFAULTS),
184
+ },
185
+ };
186
+ }
@@ -81,8 +81,55 @@ export interface DriversConfig {
81
81
  readonly runs?: EnvDriverMap;
82
82
  }
83
83
 
84
- /** Image lock entries keyed by element role (`store.sql`, …). */
85
- export type ImagesConfig = Readonly<Record<string, string>>;
84
+ /**
85
+ * Container image pins, nested the same way as {@link DriversConfig}:
86
+ * `store.*` / `channel.*` facets nest under their owning element; roles with
87
+ * no driver counterpart (`vault` picks a driver but pins its own image;
88
+ * `ai`, `pgdog`, `proxy` have no config-level element at all) stay flat.
89
+ *
90
+ * Always fully explicit — `images` has no hidden default merge. Omitted keys
91
+ * mean "no container for that role," never "inherit a default image."
92
+ */
93
+ export interface ImagesConfig {
94
+ readonly store?: {
95
+ readonly sql?: string;
96
+ readonly kv?: string;
97
+ readonly files?: string;
98
+ readonly index?: string;
99
+ };
100
+ readonly channel?: {
101
+ readonly email?: string;
102
+ };
103
+ readonly vault?: string;
104
+ readonly ai?: string;
105
+ readonly pgdog?: string;
106
+ readonly proxy?: string;
107
+ }
108
+
109
+ /**
110
+ * Flatten {@link ImagesConfig} to the dotted-role `Record<string, string>`
111
+ * every internal consumer (compose role matching, credentials, env prefixes)
112
+ * has always kept working with — the nesting is a config-surface / type-safety
113
+ * concern only, not an internal representation change.
114
+ *
115
+ * @param images - Nested config-surface images (or `undefined`)
116
+ */
117
+ export function flattenImagesConfig(
118
+ images: ImagesConfig | undefined,
119
+ ): Readonly<Record<string, string>> {
120
+ if (!images) return {};
121
+ const out: Record<string, string> = {};
122
+ if (images.store?.sql) out["store.sql"] = images.store.sql;
123
+ if (images.store?.kv) out["store.kv"] = images.store.kv;
124
+ if (images.store?.files) out["store.files"] = images.store.files;
125
+ if (images.store?.index) out["store.index"] = images.store.index;
126
+ if (images.channel?.email) out["channel.email"] = images.channel.email;
127
+ if (images.vault) out.vault = images.vault;
128
+ if (images.ai) out.ai = images.ai;
129
+ if (images.pgdog) out.pgdog = images.pgdog;
130
+ if (images.proxy) out.proxy = images.proxy;
131
+ return out;
132
+ }
86
133
 
87
134
  /** i18n config. */
88
135
  export interface I18nConfig {
@@ -293,6 +340,32 @@ export function normalizeDriversConfig(
293
340
  };
294
341
  }
295
342
 
343
+ /**
344
+ * Merge a developer's partial {@link EnvDriverMap} onto the real default map
345
+ * for one specific driver — per environment key, never a whole-object
346
+ * replace. An unset key keeps that driver's own real default; it never
347
+ * inherits a sibling key's value (the old `docker → prod → local → test`
348
+ * cascade in {@link resolveDriverId} did that, which is exactly the bug this
349
+ * fixes — `{ local: "pglite" }` no longer leaks `pglite` into `docker`).
350
+ *
351
+ * Scoped strictly to the `{ local?, docker?, test?, prod? }` shape — not a
352
+ * generic deep merge, and never applied to a whole config object.
353
+ *
354
+ * @param override - Developer-supplied partial map (may be `undefined`)
355
+ * @param defaults - Real, already-established default map for this driver
356
+ */
357
+ export function mergeEnvDriverMap(
358
+ override: EnvDriverMap | undefined,
359
+ defaults: EnvDriverMap,
360
+ ): EnvDriverMap {
361
+ return {
362
+ local: override?.local ?? defaults.local,
363
+ docker: override?.docker ?? defaults.docker,
364
+ test: override?.test ?? defaults.test,
365
+ prod: override?.prod ?? defaults.prod,
366
+ };
367
+ }
368
+
296
369
  /**
297
370
  * Fill missing `docker` pins from `prod` (compose infra ≈ production protocols).
298
371
  *
@@ -365,22 +438,39 @@ export function defineConfig(config: OkeConfig): OkeConfig {
365
438
  /**
366
439
  * Resolve a driver id for an env from an {@link EnvDriverMap}.
367
440
  *
368
- * `docker` falls back to `prod` then `local` so existing configs keep working
369
- * until an explicit `docker:` pin is added. Legacy keys are normalized first.
441
+ * With `defaults` given, the developer's map is merged onto it per-key via
442
+ * {@link mergeEnvDriverMap} and the active env's slot is read directly a
443
+ * key the developer never set keeps that driver's real default, full stop.
444
+ * This is the path every driver map with an established default should use.
445
+ *
446
+ * Without `defaults` (legacy path — `store.index`, `channel.whatsapp` /
447
+ * `push`, `ai`, which have no single established default table): `docker`
448
+ * falls back to `prod` then `local` then `test` so existing configs keep
449
+ * working until an explicit `docker:` pin is added. Legacy `dev`/`stack`
450
+ * keys are normalized first either way.
370
451
  *
371
452
  * @param map - Env → driver map
372
453
  * @param env - Active environment
454
+ * @param defaults - Real default map for this specific driver (per-key merge)
373
455
  */
374
456
  export function resolveDriverId(
375
457
  map: EnvDriverMap | RawEnvDriverMap | undefined,
376
458
  env: ConfigEnv,
459
+ defaults?: EnvDriverMap,
377
460
  ): string | undefined {
461
+ const normalized = normalizeEnvDriverMap(map as RawEnvDriverMap);
462
+ if (defaults) {
463
+ const merged = mergeEnvDriverMap(normalized, defaults);
464
+ const ref = merged[env];
465
+ if (ref === undefined) return undefined;
466
+ return typeof ref === "string" ? ref : ref.driver;
467
+ }
378
468
  if (!map) return undefined;
379
- const normalized = normalizeEnvDriverMap(map as RawEnvDriverMap) ?? map;
469
+ const resolved = normalized ?? map;
380
470
  const ref =
381
471
  env === "docker"
382
- ? (normalized.docker ?? normalized.prod ?? normalized.local ?? normalized.test)
383
- : (normalized[env] ?? normalized.local ?? normalized.test);
472
+ ? (resolved.docker ?? resolved.prod ?? resolved.local ?? resolved.test)
473
+ : (resolved[env] ?? resolved.local ?? resolved.test);
384
474
  if (ref === undefined) return undefined;
385
475
  return typeof ref === "string" ? ref : ref.driver;
386
476
  }
@@ -95,7 +95,7 @@ describe("console dry-run / preview audit", () => {
95
95
 
96
96
  test("Channels preview is locale template rendering, not dry-run mutation", async () => {
97
97
  const flows = await Bun.file(`${import.meta.dir}/flows.ts`).text();
98
- const previewIdx = flows.indexOf('name: "console.channel.preview"');
98
+ const previewIdx = flows.indexOf('flow("console.channel.preview"');
99
99
  expect(previewIdx).toBeGreaterThan(0);
100
100
  const slice = flows.slice(previewIdx, previewIdx + 800);
101
101
  expect(slice).not.toContain("withDryRun");
@@ -104,7 +104,7 @@ describe("console dry-run / preview audit", () => {
104
104
 
105
105
  test("Traces dryRun is metadata / logging, not withDryRun execution", async () => {
106
106
  const flows = await Bun.file(`${import.meta.dir}/flows.ts`).text();
107
- const idx = flows.indexOf('name: "console.traces.replay"');
107
+ const idx = flows.indexOf('flow("console.traces.replay"');
108
108
  expect(idx).toBeGreaterThan(0);
109
109
  const slice = flows.slice(idx, idx + 500);
110
110
  expect(slice).not.toContain("withDryRun");