okengine 0.1.6 → 0.2.2
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 +1 -1
- package/README.md +36 -29
- package/docs/spec/example.md +1187 -0
- package/docs/spec/unified-theory.md +1 -1
- package/package.json +20 -6
- package/src/cli/dev-app-runner.ts +6 -2
- package/src/cli/dev.ts +19 -10
- package/src/cli/doc-drift.ts +54 -21
- package/src/console/index.ts +25 -13
- package/src/console/server/app.ts +44 -7
- package/src/console/server/claim.test.ts +7 -4
- package/src/console/server/claim.ts +2 -7
- package/src/console/server/flows.ts +2 -6
- package/src/console/server/index.ts +2 -1
- package/src/console/server/lazy-panels.test.ts +27 -0
- package/src/console/server/panel-load.ts +28 -0
- package/src/console/server/plugin.ts +1 -1
- package/src/console/server/plugins.ts +7 -6
- package/src/console/server/public-flows.ts +12 -0
- package/src/console/server/state.ts +159 -122
- package/src/console/server/store.ts +13 -10
- package/src/console/ui/dist/assets/index-B71Yl_SS.js +10 -0
- package/src/console/ui/dist/assets/panel-access-Dd37LU2c.js +64 -0
- package/src/console/ui/dist/assets/panel-ai-CC7LR6-J.js +1 -0
- package/src/console/ui/dist/assets/panel-architecture-B5b3iKCz.js +1 -0
- package/src/console/ui/dist/assets/panel-channels-CeNjTKXp.js +1 -0
- package/src/console/ui/dist/assets/panel-clock-DgFTLoHV.js +1 -0
- package/src/console/ui/dist/assets/panel-diff-DxehccqB.js +1 -0
- package/src/console/ui/dist/assets/panel-flows-BtrVn-Eg.js +45 -0
- package/src/console/ui/dist/assets/panel-gates-Z9MKRGdH.js +1 -0
- package/src/console/ui/dist/assets/panel-overview-Bd48d9km.js +1 -0
- package/src/console/ui/dist/assets/panel-plugins-DWd0TowH.js +1 -0
- package/src/console/ui/dist/assets/panel-runs-BwsWqKeB.js +1 -0
- package/src/console/ui/dist/assets/panel-signals-9najbZY2.js +1 -0
- package/src/console/ui/dist/assets/panel-store-OHkP2pDp.js +1 -0
- package/src/console/ui/dist/assets/panel-traces-tn2JoY8U.js +1 -0
- package/src/console/ui/dist/assets/panel-vault-BbfWdox0.js +1 -0
- package/src/console/ui/dist/assets/rolldown-runtime-CNC7AqOf.js +1 -0
- package/src/console/ui/dist/assets/style-Cnl7WLya.css +3 -0
- package/src/console/ui/dist/index.html +14 -0
- package/src/docs-origin.ts +19 -0
- package/src/drivers/index.ts +1 -6
- package/src/drivers/vault-sops.ts +20 -1
- package/src/kernel/app.ts +1 -1
- package/src/kernel/boot-bind/ai.ts +31 -0
- package/src/kernel/boot-bind/channel.ts +27 -0
- package/src/kernel/boot-bind/clock.ts +74 -0
- package/src/kernel/boot-bind/gate.ts +28 -0
- package/src/kernel/boot-bind/runs.ts +28 -0
- package/src/kernel/boot-bind/signal.ts +68 -0
- package/src/kernel/boot-bind/store.ts +47 -0
- package/src/kernel/boot-bind/vault.ts +36 -0
- package/src/kernel/boot.test.ts +85 -1
- package/src/kernel/boot.ts +250 -212
- package/src/kernel/errors.registry.test.ts +4 -2
- package/src/kernel/errors.ts +3 -1
- package/src/kernel/fx.test.ts +2 -2
- package/src/kernel/index.ts +2 -0
- package/src/mcp/data.ts +1 -0
- package/src/mcp/docs-index.ts +252 -0
- package/src/mcp/docs-mcp.test.ts +176 -0
- package/src/mcp/docs-server.ts +233 -0
- package/src/mcp/docs-tools.ts +143 -0
- package/src/mcp/index.ts +29 -5
- package/src/mcp/protocol.ts +2 -1
- package/src/release/exports.test.ts +71 -0
- package/src/release/exports.ts +156 -0
- package/src/release/index.ts +21 -0
- package/src/release/limits.ts +9 -0
- package/src/release/measure.exports.test.ts +82 -0
- package/src/release/measure.ts +297 -14
- package/src/release/publish.ts +14 -3
- package/src/release/readme.test.ts +61 -0
- package/src/release/readme.ts +13 -0
- package/src/runtime/index.ts +1 -0
- package/src/runtime/security.test.ts +6 -1
- package/src/runtime/types.ts +6 -0
- package/src/term.test.ts +51 -0
- package/src/term.ts +158 -0
- package/src/test/create-test-app.ts +2 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy channel binder — loaded only when Channel is declared.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { openConsoleChannel } from "../../drivers/channel-console.ts";
|
|
6
|
+
import {
|
|
7
|
+
createChannelRuntime,
|
|
8
|
+
type ChannelRuntime,
|
|
9
|
+
} from "../../elements/channel.ts";
|
|
10
|
+
import type { BootOptions } from "../boot.ts";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Construct a Channel runtime (console inbox default).
|
|
14
|
+
*
|
|
15
|
+
* @param options - Boot options
|
|
16
|
+
* @param now - Clock
|
|
17
|
+
*/
|
|
18
|
+
export function bindChannel(
|
|
19
|
+
options: BootOptions,
|
|
20
|
+
now: () => number,
|
|
21
|
+
): ChannelRuntime {
|
|
22
|
+
return createChannelRuntime({
|
|
23
|
+
...(options.channel ?? {}),
|
|
24
|
+
drivers: options.channel?.drivers ?? [openConsoleChannel()],
|
|
25
|
+
now,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy clock binder — loaded only when Clock is declared.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
clock as declareClock,
|
|
7
|
+
createClockRuntime,
|
|
8
|
+
createTestClockRuntime,
|
|
9
|
+
type ClockDecl,
|
|
10
|
+
type ClockRuntime,
|
|
11
|
+
} from "../../elements/clock.ts";
|
|
12
|
+
import {
|
|
13
|
+
resolveDriverId,
|
|
14
|
+
type ConfigEnv,
|
|
15
|
+
} from "../../config/index.ts";
|
|
16
|
+
import type { BootOptions } from "../boot.ts";
|
|
17
|
+
|
|
18
|
+
/** Result of binding a clock runtime. */
|
|
19
|
+
export interface BindClockResult {
|
|
20
|
+
readonly clock: ClockRuntime;
|
|
21
|
+
readonly clockDecls: ReadonlyMap<string, ClockDecl>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Construct / adopt a Clock runtime, register decls, reconcile.
|
|
26
|
+
*
|
|
27
|
+
* @param options - Boot options
|
|
28
|
+
* @param env - Active environment
|
|
29
|
+
* @param now - Clock
|
|
30
|
+
* @param prebuilt - Optional injected runtime
|
|
31
|
+
*/
|
|
32
|
+
export async function bindClock(
|
|
33
|
+
options: BootOptions,
|
|
34
|
+
env: ConfigEnv,
|
|
35
|
+
now: () => number,
|
|
36
|
+
prebuilt?: ClockRuntime,
|
|
37
|
+
): Promise<BindClockResult> {
|
|
38
|
+
const clockDriver =
|
|
39
|
+
resolveDriverId(options.config?.drivers?.clock, env) ??
|
|
40
|
+
(env === "test" ? "frozen" : "memory");
|
|
41
|
+
const clock =
|
|
42
|
+
prebuilt ??
|
|
43
|
+
(clockDriver === "frozen" || env === "test"
|
|
44
|
+
? createTestClockRuntime(now(), { instanceId: options.instanceId })
|
|
45
|
+
: createClockRuntime({ instanceId: options.instanceId, now }));
|
|
46
|
+
|
|
47
|
+
const clockDecls = new Map<string, ClockDecl>();
|
|
48
|
+
for (const c of options.clocks ?? []) {
|
|
49
|
+
clockDecls.set(c.name, c);
|
|
50
|
+
}
|
|
51
|
+
for (const b of options.bindings ?? []) {
|
|
52
|
+
if (b.trigger.kind === "every" && !clockDecls.has(b.trigger.interval)) {
|
|
53
|
+
clockDecls.set(
|
|
54
|
+
b.trigger.interval,
|
|
55
|
+
declareClock(b.trigger.interval, { every: b.trigger.interval }),
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
for (const decl of clockDecls.values()) {
|
|
60
|
+
clock.register(decl);
|
|
61
|
+
}
|
|
62
|
+
await clock.reconcile();
|
|
63
|
+
|
|
64
|
+
if (options.onCronFire) {
|
|
65
|
+
const fire = options.onCronFire;
|
|
66
|
+
for (const name of clockDecls.keys()) {
|
|
67
|
+
clock.onCron(name, async () => {
|
|
68
|
+
await fire(name);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return { clock, clockDecls };
|
|
74
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy gate binder — loaded only when Gate is declared (or required by AI).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { memoryDrivers } from "../../drivers/memory.ts";
|
|
6
|
+
import {
|
|
7
|
+
createGateRuntime,
|
|
8
|
+
type GateRuntime,
|
|
9
|
+
} from "../../elements/gate.ts";
|
|
10
|
+
import type { BootOptions } from "../boot.ts";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Construct a Gate runtime backed by a memory kv namespace.
|
|
14
|
+
*
|
|
15
|
+
* @param options - Boot options
|
|
16
|
+
* @param now - Clock
|
|
17
|
+
*/
|
|
18
|
+
export async function bindGate(
|
|
19
|
+
options: BootOptions,
|
|
20
|
+
now: () => number,
|
|
21
|
+
): Promise<GateRuntime> {
|
|
22
|
+
const kvNs = await memoryDrivers.kv.open({ name: "oke:gates" });
|
|
23
|
+
return createGateRuntime({
|
|
24
|
+
gates: options.gates ?? [],
|
|
25
|
+
kv: kvNs,
|
|
26
|
+
now,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy runs binder — loaded only when runs are requested.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
createRunsRuntime,
|
|
7
|
+
memoryRunsDriver,
|
|
8
|
+
type CreateRunsRuntimeOptions,
|
|
9
|
+
type RunsRuntime,
|
|
10
|
+
} from "../../runs/index.ts";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Construct and open a runs runtime.
|
|
14
|
+
*
|
|
15
|
+
* @param options - Create options (when not already a runtime)
|
|
16
|
+
*/
|
|
17
|
+
export async function bindRuns(
|
|
18
|
+
options?: CreateRunsRuntimeOptions,
|
|
19
|
+
): Promise<RunsRuntime> {
|
|
20
|
+
const runs = createRunsRuntime({
|
|
21
|
+
driver: options?.driver ?? memoryRunsDriver,
|
|
22
|
+
...(options ?? {}),
|
|
23
|
+
});
|
|
24
|
+
if (!runs.store) {
|
|
25
|
+
await runs.open();
|
|
26
|
+
}
|
|
27
|
+
return runs;
|
|
28
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy signal binder — loaded only when Signal is declared.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { memorySignalDriver } from "../../drivers/signal-memory.ts";
|
|
6
|
+
import {
|
|
7
|
+
createSignalRuntime,
|
|
8
|
+
type SignalRuntime,
|
|
9
|
+
} from "../../elements/signal.ts";
|
|
10
|
+
import {
|
|
11
|
+
resolveDriverId,
|
|
12
|
+
type ConfigEnv,
|
|
13
|
+
} from "../../config/index.ts";
|
|
14
|
+
import type { BootOptions } from "../boot.ts";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Construct a Signal runtime, register decls / binding names, start the bus.
|
|
18
|
+
*
|
|
19
|
+
* @param options - Boot options
|
|
20
|
+
* @param env - Active environment
|
|
21
|
+
* @param now - Clock
|
|
22
|
+
*/
|
|
23
|
+
export async function bindSignal(
|
|
24
|
+
options: BootOptions,
|
|
25
|
+
env: ConfigEnv,
|
|
26
|
+
now: () => number,
|
|
27
|
+
): Promise<SignalRuntime> {
|
|
28
|
+
const signalId =
|
|
29
|
+
resolveDriverId(options.config?.drivers?.signal, env) ?? "memory";
|
|
30
|
+
void signalId;
|
|
31
|
+
const signal = createSignalRuntime({
|
|
32
|
+
driver: memorySignalDriver,
|
|
33
|
+
now,
|
|
34
|
+
});
|
|
35
|
+
for (const decl of options.signals ?? []) {
|
|
36
|
+
signal.register(decl);
|
|
37
|
+
}
|
|
38
|
+
for (const b of options.bindings ?? []) {
|
|
39
|
+
if (b.trigger.kind === "signal") {
|
|
40
|
+
if (!signal.declarations.has(b.trigger.name)) {
|
|
41
|
+
signal.register({
|
|
42
|
+
name: b.trigger.name,
|
|
43
|
+
delivery: "once",
|
|
44
|
+
retries: 3,
|
|
45
|
+
deadLetter: true,
|
|
46
|
+
optional: true,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const bus = await signal.start();
|
|
52
|
+
|
|
53
|
+
if (options.onSignal) {
|
|
54
|
+
const handler = options.onSignal;
|
|
55
|
+
const seen = new Set<string>();
|
|
56
|
+
for (const b of options.bindings ?? []) {
|
|
57
|
+
if (b.trigger.kind !== "signal") continue;
|
|
58
|
+
const name = b.trigger.name;
|
|
59
|
+
if (seen.has(name)) continue;
|
|
60
|
+
seen.add(name);
|
|
61
|
+
await bus.subscribe(name, `oke:${name}`, async (msg) => {
|
|
62
|
+
await handler(name, msg.payload);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return signal;
|
|
68
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy store binder — loaded only when Store is declared.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { memoryDrivers } from "../../drivers/memory.ts";
|
|
6
|
+
import {
|
|
7
|
+
createStoreRuntime,
|
|
8
|
+
type StoreRuntime,
|
|
9
|
+
} from "../../elements/store.ts";
|
|
10
|
+
import {
|
|
11
|
+
resolveDriverId,
|
|
12
|
+
type ConfigEnv,
|
|
13
|
+
} from "../../config/index.ts";
|
|
14
|
+
import type { BootOptions } from "../boot.ts"; // type-only — no cycle at runtime
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Construct a Store runtime and register facet declarations.
|
|
18
|
+
*
|
|
19
|
+
* @param options - Boot options
|
|
20
|
+
* @param env - Active environment
|
|
21
|
+
* @param now - Clock
|
|
22
|
+
*/
|
|
23
|
+
export function bindStore(
|
|
24
|
+
options: BootOptions,
|
|
25
|
+
env: ConfigEnv,
|
|
26
|
+
now: () => number,
|
|
27
|
+
): StoreRuntime {
|
|
28
|
+
const sqlId =
|
|
29
|
+
resolveDriverId(options.config?.drivers?.store?.sql, env) ?? "memory";
|
|
30
|
+
const kvId =
|
|
31
|
+
resolveDriverId(options.config?.drivers?.store?.kv, env) ?? "memory";
|
|
32
|
+
void sqlId;
|
|
33
|
+
void kvId;
|
|
34
|
+
const store = createStoreRuntime({
|
|
35
|
+
drivers: {
|
|
36
|
+
sql: memoryDrivers.sql,
|
|
37
|
+
kv: memoryDrivers.kv,
|
|
38
|
+
files: memoryDrivers.files,
|
|
39
|
+
index: memoryDrivers.index,
|
|
40
|
+
},
|
|
41
|
+
now,
|
|
42
|
+
});
|
|
43
|
+
for (const decl of options.stores ?? []) {
|
|
44
|
+
store.register?.(decl);
|
|
45
|
+
}
|
|
46
|
+
return store;
|
|
47
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy vault binder — loaded only when secrets are declared.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { memoryVaultDriver } from "../../drivers/vault-memory.ts";
|
|
6
|
+
import {
|
|
7
|
+
createVaultRuntime,
|
|
8
|
+
type VaultRuntime,
|
|
9
|
+
} from "../../elements/vault.ts";
|
|
10
|
+
import type { ConfigEnv } from "../../config/index.ts";
|
|
11
|
+
import type { BootOptions } from "../boot.ts";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Construct and boot a Vault runtime from BootOptions.
|
|
15
|
+
*
|
|
16
|
+
* @param options - Boot options
|
|
17
|
+
* @param env - Active environment
|
|
18
|
+
*/
|
|
19
|
+
export async function bindVault(
|
|
20
|
+
options: BootOptions,
|
|
21
|
+
env: ConfigEnv,
|
|
22
|
+
): Promise<VaultRuntime> {
|
|
23
|
+
const vaultSecrets = options.vault?.secrets ?? options.secrets ?? [];
|
|
24
|
+
const vault = createVaultRuntime({
|
|
25
|
+
secrets: vaultSecrets,
|
|
26
|
+
chain: options.vault?.chain ?? [
|
|
27
|
+
{
|
|
28
|
+
driver: memoryVaultDriver,
|
|
29
|
+
options: { secrets: {} },
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
allowDevFallbacks: options.vault?.allowDevFallbacks ?? env !== "prod",
|
|
33
|
+
});
|
|
34
|
+
await vault.boot();
|
|
35
|
+
return vault;
|
|
36
|
+
}
|
package/src/kernel/boot.test.ts
CHANGED
|
@@ -7,10 +7,14 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { afterEach, describe, expect, jest, test } from "bun:test";
|
|
10
|
+
import { mkdtemp, rm } from "node:fs/promises";
|
|
11
|
+
import { tmpdir } from "node:os";
|
|
12
|
+
import { join } from "node:path";
|
|
10
13
|
import { memoryVaultDriver } from "../drivers/index.ts";
|
|
11
14
|
import { clock } from "../elements/clock.ts";
|
|
15
|
+
import { store } from "../elements/store.ts";
|
|
12
16
|
import { vault, VaultBootError } from "../elements/vault.ts";
|
|
13
|
-
import { bootApplication } from "./boot.ts";
|
|
17
|
+
import { bootApplication, resolveElementNeeds } from "./boot.ts";
|
|
14
18
|
import { flow, resetFlowSeq } from "./flow.ts";
|
|
15
19
|
import { every, http } from "./triggers.ts";
|
|
16
20
|
import { oke } from "./app.ts";
|
|
@@ -42,6 +46,86 @@ describe("boot — vault gaps", () => {
|
|
|
42
46
|
expect(boot.message).toContain("DATABASE_URL");
|
|
43
47
|
}
|
|
44
48
|
});
|
|
49
|
+
|
|
50
|
+
test("three missing secrets still list every gap at once", async () => {
|
|
51
|
+
try {
|
|
52
|
+
await bootApplication({
|
|
53
|
+
env: "prod",
|
|
54
|
+
secrets: [
|
|
55
|
+
vault("A", { description: "one" }),
|
|
56
|
+
vault("B", { description: "two" }),
|
|
57
|
+
vault("C", { description: "three" }),
|
|
58
|
+
],
|
|
59
|
+
vault: {
|
|
60
|
+
allowDevFallbacks: false,
|
|
61
|
+
chain: [{ driver: memoryVaultDriver, options: { secrets: {} } }],
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
expect.unreachable("boot should fail");
|
|
65
|
+
} catch (err) {
|
|
66
|
+
expect(err).toBeInstanceOf(VaultBootError);
|
|
67
|
+
const boot = err as VaultBootError;
|
|
68
|
+
expect(boot.gaps.map((g) => g.name).sort()).toEqual(["A", "B", "C"]);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe("boot — lazy element needs", () => {
|
|
74
|
+
test("Store-only declarations do not require AI/channel/vault", () => {
|
|
75
|
+
const needs = resolveElementNeeds({
|
|
76
|
+
stores: [store.sql("notes", { schema: {} as never })],
|
|
77
|
+
});
|
|
78
|
+
expect(needs.store).toBe(true);
|
|
79
|
+
expect(needs.ai).toBe(false);
|
|
80
|
+
expect(needs.channel).toBe(false);
|
|
81
|
+
expect(needs.vault).toBe(false);
|
|
82
|
+
expect(needs.signal).toBe(false);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test("oke() Store-only graph stays under the prior 41.4 kB baseline", async () => {
|
|
86
|
+
const dir = await mkdtemp(join(tmpdir(), "oke-store-only-"));
|
|
87
|
+
const entry = join(dir, "entry.ts");
|
|
88
|
+
const appPath = join(import.meta.dir, "app.ts");
|
|
89
|
+
const storePath = join(import.meta.dir, "../elements/store.ts");
|
|
90
|
+
await Bun.write(
|
|
91
|
+
entry,
|
|
92
|
+
`import { oke } from ${JSON.stringify(appPath)};\n` +
|
|
93
|
+
`import { store } from ${JSON.stringify(storePath)};\n` +
|
|
94
|
+
`export const app = oke({ name: "notes" });\n` +
|
|
95
|
+
`export { store };\n`,
|
|
96
|
+
);
|
|
97
|
+
try {
|
|
98
|
+
const result = await Bun.build({
|
|
99
|
+
entrypoints: [entry],
|
|
100
|
+
minify: true,
|
|
101
|
+
target: "bun",
|
|
102
|
+
format: "esm",
|
|
103
|
+
external: [
|
|
104
|
+
"@duckdb/node-api",
|
|
105
|
+
"@duckdb/*",
|
|
106
|
+
"age-encryption",
|
|
107
|
+
"sently",
|
|
108
|
+
"sently/*",
|
|
109
|
+
"ajv",
|
|
110
|
+
"ajv/*",
|
|
111
|
+
"ajv-formats",
|
|
112
|
+
"oxc-parser",
|
|
113
|
+
"zod",
|
|
114
|
+
],
|
|
115
|
+
});
|
|
116
|
+
expect(result.success).toBe(true);
|
|
117
|
+
let total = 0;
|
|
118
|
+
for (const o of result.outputs) {
|
|
119
|
+
const raw = await o.arrayBuffer();
|
|
120
|
+
if (raw.byteLength === 0) continue;
|
|
121
|
+
total += Bun.gzipSync(new Uint8Array(raw)).byteLength;
|
|
122
|
+
}
|
|
123
|
+
// Prior eager-bind baseline: ~41.4 kB for oke() alone.
|
|
124
|
+
expect(total).toBeLessThan(41_400);
|
|
125
|
+
} finally {
|
|
126
|
+
await rm(dir, { recursive: true, force: true });
|
|
127
|
+
}
|
|
128
|
+
});
|
|
45
129
|
});
|
|
46
130
|
|
|
47
131
|
describe("boot — capabilities from Manifest effects", () => {
|