Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 4 additions & 11 deletions packages/bootstrap/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,17 @@
"homepage": "https://workglow.dev",
"scripts": {
"watch": "concurrently -c 'auto' 'bun:watch-*'",
"watch-js": "concurrently -c 'auto' -n 'browser,node,bun' 'bun run watch-browser' 'bun run watch-node' 'bun run watch-bun'",
"watch-js": "concurrently -c 'auto' -n 'browser,node' 'bun run watch-browser' 'bun run watch-node'",
"watch-browser": "bun build --watch --no-clear-screen --target=browser --sourcemap=external --packages=external --outdir ./dist ./src/browser.ts",
"watch-node": "bun build --watch --no-clear-screen --target=node --sourcemap=external --packages=external --outdir ./dist ./src/node.ts",
"watch-bun": "bun build --watch --no-clear-screen --target=bun --sourcemap=external --packages=external --outdir ./dist ./src/bun.ts",
"watch-types": "tsc --watch --preserveWatchOutput",
"build-package": "concurrently -c 'auto' -n 'browser,node,bun,types' 'bun run build-browser' 'bun run build-node' 'bun run build-bun' 'bun run build-types'",
"build-js": "concurrently -m 12 --timings -c 'auto' -n 'browser,node,bun' 'bun run build-browser' 'bun run build-node' 'bun run build-bun'",
"build-package": "concurrently -c 'auto' -n 'browser,node,types' 'bun run build-browser' 'bun run build-node' 'bun run build-types'",
"build-js": "concurrently -m 12 --timings -c 'auto' -n 'browser,node' 'bun run build-browser' 'bun run build-node'",
"build-clean": "rm -fr dist/* tsconfig.tsbuildinfo",
"build-browser": "bun build --target=browser --sourcemap=external --packages=external --outdir ./dist ./src/browser.ts",
"build-node": "bun build --target=node --sourcemap=external --packages=external --outdir ./dist ./src/node.ts",
"build-bun": "bun build --target=bun --sourcemap=external --packages=external --outdir ./dist ./src/bun.ts",
"build-types": "rm -f tsconfig.tsbuildinfo && tsgo",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"test": "bun test"
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0"
},
"peerDependencies": {
"@workglow/ai": "workspace:*",
Expand Down Expand Up @@ -76,10 +73,6 @@
"types": "./dist/browser.d.ts",
"import": "./dist/browser.js"
},
"bun": {
"types": "./dist/bun.d.ts",
"import": "./dist/bun.js"
},
"types": "./dist/node.d.ts",
"import": "./dist/node.js"
}
Expand Down
9 changes: 0 additions & 9 deletions packages/bootstrap/src/bun.ts

This file was deleted.

2 changes: 1 addition & 1 deletion packages/bootstrap/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"extends": "../../tsconfig.json",
"include": ["src/common.ts", "src/*/**/*"],
"files": ["./src/browser.ts", "./src/node.ts", "./src/bun.ts"],
"files": ["./src/browser.ts", "./src/node.ts"],
"exclude": ["dist", "node_modules"],
"compilerOptions": {
"composite": true,
Expand Down
64 changes: 63 additions & 1 deletion packages/test/src/test/util/BootstrapReadme.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@
* `TaskGraphRunConfig` has a `context` key — so with a loosely typed `Input`
* that object is an input override named `context`, the run keeps the global
* registry, and `ctx.dispose()` tears down a registry the task never touched.
* Both halves are pinned below so the snippet cannot silently rot back.
*
* Two halves are pinned below. The first `describe` exercises both shapes at
* runtime, proving the documented one works and the old one does not. The
* second reads the two documents themselves, so a snippet that rots back is a
* test failure rather than prose nobody re-checks. The document cases scan
* every fenced block for the wrong shape, so a deliberate counter-example in
* the README would trip them — write the counter-example as prose instead.
*/

import { createOrchestrationContext } from "@workglow/bootstrap";
Expand All @@ -23,8 +29,30 @@ import { Task } from "@workglow/task-graph";
import type { ServiceRegistry } from "@workglow/util";
import { globalServiceRegistry } from "@workglow/util";
import type { DataPortSchema } from "@workglow/util/schema";
import { readFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { describe, expect, it } from "vitest";

const REPO_ROOT = join(dirname(fileURLToPath(import.meta.url)), "../../../../..");
const README_PATH = join(REPO_ROOT, "packages/bootstrap/README.md");
const SOURCE_PATH = join(REPO_ROOT, "packages/bootstrap/src/bootstrap/bootstrapWorkglow.ts");

/** The registry travelling in the run config — `run()`'s second argument. */
const REGISTRY_IN_RUN_CONFIG =
/\.run\(\s*\{\s*\}\s*,\s*\{\s*registry:\s*\w+\.registry[\s,]*\}\s*\)/;
/** The shape that silently becomes an input override named `context`. */
const CONTEXT_AS_INPUT = /\.run\(\s*\{\s*context\s*:/;

/**
* Every fenced code block's body, whatever its info string. Selecting blocks by
* content rather than by the heading above them keeps a heading rename from
* making these cases pass vacuously.
*/
function fencedBlocks(markdown: string): string[] {
return [...markdown.matchAll(/^```[^\n]*\n([\s\S]*?)^```/gm)].map((match) => match[1]!);
}

interface RegistryProbeOutput extends TaskOutput {
isGlobal: boolean;
}
Expand Down Expand Up @@ -93,3 +121,37 @@ describe("the @workglow/bootstrap README isolated-context example", () => {
}
});
});

describe("the documents the example is transcribed from", () => {
it("README documents the registry in the run config", () => {
const blocks = fencedBlocks(readFileSync(README_PATH, "utf8")).filter((block) =>
block.includes("createOrchestrationContext(")
);

expect(blocks.length).toBeGreaterThan(0);
expect(blocks.some((block) => REGISTRY_IN_RUN_CONFIG.test(block))).toBe(true);
});

it("no README code block passes the context as an input override", () => {
// Code only: the surrounding prose deliberately discusses "an input named
// `context`" and has to stay legal.
const offenders = fencedBlocks(readFileSync(README_PATH, "utf8")).filter((block) =>
CONTEXT_AS_INPUT.test(block)
);

expect(offenders).toEqual([]);
});

it("the createOrchestrationContext JSDoc shows the same shape", () => {
const source = readFileSync(SOURCE_PATH, "utf8");
const jsdoc = source.match(
/\/\*\*([\s\S]*?)\*\/\s*export function createOrchestrationContext\b/
);

expect(jsdoc).not.toBeNull();

const comment = jsdoc![1]!.replace(/^\s*\*/gm, "");
expect(REGISTRY_IN_RUN_CONFIG.test(comment)).toBe(true);
expect(CONTEXT_AS_INPUT.test(comment)).toBe(false);
});
});
Loading