@workflow/world-testing 5.0.0-beta.4 → 5.0.0-beta.5
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/dist/.well-known/workflow/v1/flow.mjs +73481 -43011
- package/dist/.well-known/workflow/v1/manifest.json +292 -43
- package/dist/.well-known/workflow/v1/step.mjs +8635 -46348
- package/dist/src/index.d.mts.map +1 -1
- package/dist/src/index.mjs +2 -0
- package/dist/src/index.mjs.map +1 -1
- package/dist/src/inline-batches-debug.d.mts +15 -0
- package/dist/src/inline-batches-debug.d.mts.map +1 -0
- package/dist/src/inline-batches-debug.mjs +208 -0
- package/dist/src/inline-batches-debug.mjs.map +1 -0
- package/dist/src/inline-execution.d.mts +13 -0
- package/dist/src/inline-execution.d.mts.map +1 -0
- package/dist/src/inline-execution.mjs +80 -0
- package/dist/src/inline-execution.mjs.map +1 -0
- package/dist/src/server.mjs +50 -5
- package/dist/src/server.mjs.map +1 -1
- package/dist/src/util.d.mts +15 -12
- package/dist/src/util.d.mts.map +1 -1
- package/dist/src/util.mjs +20 -3
- package/dist/src/util.mjs.map +1 -1
- package/package.json +5 -5
package/dist/src/util.d.mts
CHANGED
|
@@ -12,7 +12,9 @@ type Files = keyof typeof manifest.workflows;
|
|
|
12
12
|
type Workflows<F extends Files> = keyof (typeof manifest.workflows)[F];
|
|
13
13
|
export declare function startServer(opts: {
|
|
14
14
|
world: string;
|
|
15
|
+
env?: Record<string, string | undefined>;
|
|
15
16
|
}): Promise<{
|
|
17
|
+
getOutput: () => string;
|
|
16
18
|
state: "listening";
|
|
17
19
|
info: {
|
|
18
20
|
port: number;
|
|
@@ -22,6 +24,7 @@ export declare function createFetcher(control: Control): {
|
|
|
22
24
|
invoke<F extends Files, W extends Workflows<F>>(file: F, workflow: W, args: unknown[]): Promise<{
|
|
23
25
|
runId: string;
|
|
24
26
|
}>;
|
|
27
|
+
getFlowInvocationCount(runId: string): Promise<number>;
|
|
25
28
|
getRun(id: string): Promise<{
|
|
26
29
|
runId: string;
|
|
27
30
|
deploymentId: string;
|
|
@@ -30,13 +33,14 @@ export declare function createFetcher(control: Control): {
|
|
|
30
33
|
createdAt: Date;
|
|
31
34
|
updatedAt: Date;
|
|
32
35
|
status: "pending" | "running";
|
|
33
|
-
output: undefined;
|
|
34
|
-
error: undefined;
|
|
35
|
-
completedAt: undefined;
|
|
36
36
|
specVersion?: number | undefined;
|
|
37
37
|
executionContext?: Record<string, any> | undefined;
|
|
38
|
+
errorCode?: string | undefined;
|
|
38
39
|
expiredAt?: Date | undefined;
|
|
39
40
|
startedAt?: Date | undefined;
|
|
41
|
+
output?: undefined;
|
|
42
|
+
error?: undefined;
|
|
43
|
+
completedAt?: undefined;
|
|
40
44
|
} | {
|
|
41
45
|
runId: string;
|
|
42
46
|
deploymentId: string;
|
|
@@ -45,13 +49,14 @@ export declare function createFetcher(control: Control): {
|
|
|
45
49
|
createdAt: Date;
|
|
46
50
|
updatedAt: Date;
|
|
47
51
|
status: "cancelled";
|
|
48
|
-
output: undefined;
|
|
49
|
-
error: undefined;
|
|
50
52
|
completedAt: Date;
|
|
51
53
|
specVersion?: number | undefined;
|
|
52
54
|
executionContext?: Record<string, any> | undefined;
|
|
55
|
+
errorCode?: string | undefined;
|
|
53
56
|
expiredAt?: Date | undefined;
|
|
54
57
|
startedAt?: Date | undefined;
|
|
58
|
+
output?: undefined;
|
|
59
|
+
error?: undefined;
|
|
55
60
|
} | {
|
|
56
61
|
runId: string;
|
|
57
62
|
deploymentId: string;
|
|
@@ -61,12 +66,13 @@ export declare function createFetcher(control: Control): {
|
|
|
61
66
|
updatedAt: Date;
|
|
62
67
|
status: "completed";
|
|
63
68
|
output: unknown;
|
|
64
|
-
error: undefined;
|
|
65
69
|
completedAt: Date;
|
|
66
70
|
specVersion?: number | undefined;
|
|
67
71
|
executionContext?: Record<string, any> | undefined;
|
|
72
|
+
errorCode?: string | undefined;
|
|
68
73
|
expiredAt?: Date | undefined;
|
|
69
74
|
startedAt?: Date | undefined;
|
|
75
|
+
error?: undefined;
|
|
70
76
|
} | {
|
|
71
77
|
runId: string;
|
|
72
78
|
deploymentId: string;
|
|
@@ -75,17 +81,14 @@ export declare function createFetcher(control: Control): {
|
|
|
75
81
|
createdAt: Date;
|
|
76
82
|
updatedAt: Date;
|
|
77
83
|
status: "failed";
|
|
78
|
-
|
|
79
|
-
error: {
|
|
80
|
-
message: string;
|
|
81
|
-
stack?: string | undefined;
|
|
82
|
-
code?: string | undefined;
|
|
83
|
-
};
|
|
84
|
+
error: unknown;
|
|
84
85
|
completedAt: Date;
|
|
85
86
|
specVersion?: number | undefined;
|
|
86
87
|
executionContext?: Record<string, any> | undefined;
|
|
88
|
+
errorCode?: string | undefined;
|
|
87
89
|
expiredAt?: Date | undefined;
|
|
88
90
|
startedAt?: Date | undefined;
|
|
91
|
+
output?: undefined;
|
|
89
92
|
}>;
|
|
90
93
|
getReadable(id: string): Promise<ReadableStream<Uint8Array>>;
|
|
91
94
|
resumeHook<T extends TypedHook<any, any>>(token: string, payload: Omit<NoInfer<TypedHook.Input<T>>, "metadata">): Promise<void>;
|
package/dist/src/util.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.d.mts","sourceRoot":"","sources":["../../src/util.mts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,KAAK,QAAQ,MAAM,0CAA0C,CAAC;AAErE,eAAO,MAAM,OAAO;;;;;iBAKlB,CAAC;AACH,KAAK,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,OAAO,CAAC,CAAC;AAEvC,KAAK,KAAK,GAAG,MAAM,OAAO,QAAQ,CAAC,SAAS,CAAC;AAC7C,KAAK,SAAS,CAAC,CAAC,SAAS,KAAK,IAAI,MAAM,CAAC,OAAO,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAEvE,wBAAsB,WAAW,CAAC,IAAI,EAAE;
|
|
1
|
+
{"version":3,"file":"util.d.mts","sourceRoot":"","sources":["../../src/util.mts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,KAAK,QAAQ,MAAM,0CAA0C,CAAC;AAErE,eAAO,MAAM,OAAO;;;;;iBAKlB,CAAC;AACH,KAAK,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,OAAO,CAAC,CAAC;AAEvC,KAAK,KAAK,GAAG,MAAM,OAAO,QAAQ,CAAC,SAAS,CAAC;AAC7C,KAAK,SAAS,CAAC,CAAC,SAAS,KAAK,IAAI,MAAM,CAAC,OAAO,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAEvE,wBAAsB,WAAW,CAAC,IAAI,EAAE;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;CAC1C;;;;;;GAwDA;AAID,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO;WAE7B,CAAC,SAAS,KAAK,EAAE,CAAC,SAAS,SAAS,CAAC,CAAC,CAAC,QAC5C,CAAC,YACG,CAAC,QACL,OAAO,EAAE;;;kCAemB,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;eAO3C,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBAmBD,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;eAcjD,CAAC,SAAS,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,SACrC,MAAM,WACJ,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC;EAoB3D"}
|
package/dist/src/util.mjs
CHANGED
|
@@ -23,17 +23,25 @@ export async function startServer(opts) {
|
|
|
23
23
|
...process.env,
|
|
24
24
|
WORKFLOW_TARGET_WORLD: opts.world,
|
|
25
25
|
CONTROL_FD: '3',
|
|
26
|
+
...(opts.env ?? {}),
|
|
26
27
|
},
|
|
27
28
|
});
|
|
28
29
|
onTestFinished(() => {
|
|
29
30
|
proc.kill();
|
|
30
31
|
});
|
|
31
32
|
const stdio = [];
|
|
33
|
+
// Accumulated raw server output — used by tests that want to inspect
|
|
34
|
+
// debug logs (e.g., count runtime iterations, event loads, etc.).
|
|
35
|
+
const outputBuffer = [];
|
|
32
36
|
proc.stdout?.on('data', (chunk) => {
|
|
33
|
-
|
|
37
|
+
const str = chunk.toString();
|
|
38
|
+
stdio.push({ stream: chalk.white, chunk: str });
|
|
39
|
+
outputBuffer.push(str);
|
|
34
40
|
});
|
|
35
41
|
proc.stderr?.on('data', (chunk) => {
|
|
36
|
-
|
|
42
|
+
const str = chunk.toString();
|
|
43
|
+
stdio.push({ stream: chalk.red, chunk: str });
|
|
44
|
+
outputBuffer.push(str);
|
|
37
45
|
});
|
|
38
46
|
onTestFailed(() => {
|
|
39
47
|
console.log('=== SERVER STDIO ===');
|
|
@@ -46,7 +54,11 @@ export async function startServer(opts) {
|
|
|
46
54
|
const fd3 = proc.stdio[3];
|
|
47
55
|
assert(fd3, 'fd3 should be defined');
|
|
48
56
|
for await (const chunk of fd3.pipe(jsonlines.parse())) {
|
|
49
|
-
|
|
57
|
+
const control = Control.parse(chunk);
|
|
58
|
+
return {
|
|
59
|
+
...control,
|
|
60
|
+
getOutput: () => outputBuffer.join(''),
|
|
61
|
+
};
|
|
50
62
|
}
|
|
51
63
|
throw new Error('Server did not start correctly');
|
|
52
64
|
}
|
|
@@ -67,6 +79,11 @@ export function createFetcher(control) {
|
|
|
67
79
|
});
|
|
68
80
|
return data;
|
|
69
81
|
},
|
|
82
|
+
async getFlowInvocationCount(runId) {
|
|
83
|
+
const x = await fetch(`http://localhost:${control.info.port}/_flow-invocations/${encodeURIComponent(runId)}`);
|
|
84
|
+
const data = (await x.json());
|
|
85
|
+
return data.count;
|
|
86
|
+
},
|
|
70
87
|
async getRun(id) {
|
|
71
88
|
const x = await fetch(`http://localhost:${control.info.port}/runs/${encodeURIComponent(id)}`);
|
|
72
89
|
const text = await x.text();
|
package/dist/src/util.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.mjs","sourceRoot":"","sources":["../../src/util.mts"],"names":[],"mappings":"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","sourcesContent":["import cp from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport { WorkflowRunSchema } from '@workflow/world';\nimport chalk, { type ChalkInstance } from 'chalk';\nimport jsonlines from 'jsonlines';\nimport { assert, onTestFailed, onTestFinished } from 'vitest';\nimport type { TypedHook } from 'workflow';\nimport * as z from 'zod';\nimport type manifest from '../.well-known/workflow/v1/manifest.json';\n\nexport const Control = z.object({\n state: z.literal('listening'),\n info: z.object({\n port: z.number(),\n }),\n});\ntype Control = z.infer<typeof Control>;\n\ntype Files = keyof typeof manifest.workflows;\ntype Workflows<F extends Files> = keyof (typeof manifest.workflows)[F];\n\nexport async function startServer(opts: { world: string }) {\n let serverPath = new URL('./server.mts', import.meta.url);\n\n if (!existsSync(serverPath)) {\n serverPath = new URL('./server.mjs', import.meta.url);\n }\n\n const proc = cp.spawn('node', [fileURLToPath(serverPath)], {\n stdio: ['ignore', 'pipe', 'pipe', 'pipe'],\n env: {\n ...process.env,\n WORKFLOW_TARGET_WORLD: opts.world,\n CONTROL_FD: '3',\n },\n });\n onTestFinished(() => {\n proc.kill();\n });\n\n const stdio = [] as { stream: ChalkInstance; chunk: string }[];\n proc.stdout?.on('data', (chunk) => {\n stdio.push({ stream: chalk.white, chunk: chunk.toString() });\n });\n proc.stderr?.on('data', (chunk) => {\n stdio.push({ stream: chalk.red, chunk: chunk.toString() });\n });\n\n onTestFailed(() => {\n console.log('=== SERVER STDIO ===');\n let buffer = '';\n for (const { stream, chunk } of stdio) {\n buffer += stream.inverse(chunk);\n }\n console.log(buffer);\n });\n\n const fd3 = proc.stdio[3];\n assert(fd3, 'fd3 should be defined');\n\n for await (const chunk of fd3.pipe(jsonlines.parse())) {\n return Control.parse(chunk);\n }\n\n throw new Error('Server did not start correctly');\n}\n\nconst Invoke = z.object({ runId: z.coerce.string() });\n\nexport function createFetcher(control: Control) {\n return {\n async invoke<F extends Files, W extends Workflows<F>>(\n file: F,\n workflow: W,\n args: unknown[]\n ) {\n const x = await fetch(`http://localhost:${control.info.port}/invoke`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n },\n body: JSON.stringify({ file, workflow, args }),\n });\n const data = await x.json().then(Invoke.parse);\n onTestFailed(() => {\n console.error('Workflow run:', data.runId);\n });\n return data;\n },\n async getRun(id: string) {\n const x = await fetch(\n `http://localhost:${control.info.port}/runs/${encodeURIComponent(id)}`\n );\n const text = await x.text();\n // Custom JSON reviver to decode base64 back to Uint8Array\n const data = JSON.parse(text, (_key, value) => {\n if (\n value !== null &&\n typeof value === 'object' &&\n (value as any).__type === 'Uint8Array' &&\n typeof (value as any).data === 'string'\n ) {\n return new Uint8Array(Buffer.from((value as any).data, 'base64'));\n }\n return value;\n });\n return WorkflowRunSchema.parseAsync(data);\n },\n async getReadable(id: string): Promise<ReadableStream<Uint8Array>> {\n const x = await fetch(\n `http://localhost:${control.info.port}/runs/${encodeURIComponent(id)}/readable`\n );\n if (!x.ok) {\n throw new Error(\n `Failed to get readable stream: ${x.status} ${x.statusText}`\n );\n }\n if (!x.body) {\n throw new Error('No body in response');\n }\n return x.body;\n },\n async resumeHook<T extends TypedHook<any, any>>(\n token: string,\n payload: Omit<NoInfer<TypedHook.Input<T>>, 'metadata'>\n ) {\n const res = await fetch(\n `http://localhost:${control.info.port}/hooks/${token}`,\n {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n },\n body: JSON.stringify(payload),\n }\n );\n res.arrayBuffer().catch(() => {}); // Drain the body to avoid resource leaks\n if (!res.ok) {\n throw new Error(\n `Failed to resume hook: ${res.status} ${res.statusText}`\n );\n }\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"util.mjs","sourceRoot":"","sources":["../../src/util.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,KAA6B,MAAM,OAAO,CAAC;AAClD,OAAO,SAAS,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAE9D,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAGzB,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9B,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;IAC7B,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;QACb,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;KACjB,CAAC;CACH,CAAC,CAAC;AAMH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAGjC;IACC,IAAI,UAAU,GAAG,IAAI,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAE1D,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,UAAU,GAAG,IAAI,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,IAAI,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,EAAE;QACzD,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;QACzC,GAAG,EAAE;YACH,GAAG,OAAO,CAAC,GAAG;YACd,qBAAqB,EAAE,IAAI,CAAC,KAAK;YACjC,UAAU,EAAE,GAAG;YACf,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC;SACpB;KACF,CAAC,CAAC;IACH,cAAc,CAAC,GAAG,EAAE;QAClB,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,EAAgD,CAAC;IAC/D,qEAAqE;IACrE,kEAAkE;IAClE,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;QAChC,MAAM,GAAG,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QAChD,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;IACH,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;QAChC,MAAM,GAAG,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QAC9C,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,YAAY,CAAC,GAAG,EAAE;QAChB,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;QACpC,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,KAAK,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,KAAK,EAAE,CAAC;YACtC,MAAM,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAClC,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC,CAAC,CAAC;IAEH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC1B,MAAM,CAAC,GAAG,EAAE,uBAAuB,CAAC,CAAC;IAErC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC;QACtD,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACrC,OAAO;YACL,GAAG,OAAO;YACV,SAAS,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;SACvC,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAEtD,MAAM,UAAU,aAAa,CAAC,OAAgB;IAC5C,OAAO;QACL,KAAK,CAAC,MAAM,CACV,IAAO,EACP,QAAW,EACX,IAAe;YAEf,MAAM,CAAC,GAAG,MAAM,KAAK,CAAC,oBAAoB,OAAO,CAAC,IAAI,CAAC,IAAI,SAAS,EAAE;gBACpE,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;iBACnC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;aAC/C,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC/C,YAAY,CAAC,GAAG,EAAE;gBAChB,OAAO,CAAC,KAAK,CAAC,eAAe,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;YAC7C,CAAC,CAAC,CAAC;YACH,OAAO,IAAI,CAAC;QACd,CAAC;QACD,KAAK,CAAC,sBAAsB,CAAC,KAAa;YACxC,MAAM,CAAC,GAAG,MAAM,KAAK,CACnB,oBAAoB,OAAO,CAAC,IAAI,CAAC,IAAI,sBAAsB,kBAAkB,CAAC,KAAK,CAAC,EAAE,CACvF,CAAC;YACF,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAsB,CAAC;YACnD,OAAO,IAAI,CAAC,KAAK,CAAC;QACpB,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,EAAU;YACrB,MAAM,CAAC,GAAG,MAAM,KAAK,CACnB,oBAAoB,OAAO,CAAC,IAAI,CAAC,IAAI,SAAS,kBAAkB,CAAC,EAAE,CAAC,EAAE,CACvE,CAAC;YACF,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;YAC5B,0DAA0D;YAC1D,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;gBAC5C,IACE,KAAK,KAAK,IAAI;oBACd,OAAO,KAAK,KAAK,QAAQ;oBACxB,KAAa,CAAC,MAAM,KAAK,YAAY;oBACtC,OAAQ,KAAa,CAAC,IAAI,KAAK,QAAQ,EACvC,CAAC;oBACD,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,CAAE,KAAa,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;gBACpE,CAAC;gBACD,OAAO,KAAK,CAAC;YACf,CAAC,CAAC,CAAC;YACH,OAAO,iBAAiB,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAC5C,CAAC;QACD,KAAK,CAAC,WAAW,CAAC,EAAU;YAC1B,MAAM,CAAC,GAAG,MAAM,KAAK,CACnB,oBAAoB,OAAO,CAAC,IAAI,CAAC,IAAI,SAAS,kBAAkB,CAAC,EAAE,CAAC,WAAW,CAChF,CAAC;YACF,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;gBACV,MAAM,IAAI,KAAK,CACb,kCAAkC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,UAAU,EAAE,CAC7D,CAAC;YACJ,CAAC;YACD,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBACZ,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;YACzC,CAAC;YACD,OAAO,CAAC,CAAC,IAAI,CAAC;QAChB,CAAC;QACD,KAAK,CAAC,UAAU,CACd,KAAa,EACb,OAAsD;YAEtD,MAAM,GAAG,GAAG,MAAM,KAAK,CACrB,oBAAoB,OAAO,CAAC,IAAI,CAAC,IAAI,UAAU,KAAK,EAAE,EACtD;gBACE,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;iBACnC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;aAC9B,CACF,CAAC;YACF,GAAG,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC,CAAC,yCAAyC;YAC5E,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,MAAM,IAAI,KAAK,CACb,0BAA0B,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,CACzD,CAAC;YACJ,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import cp from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport { WorkflowRunSchema } from '@workflow/world';\nimport chalk, { type ChalkInstance } from 'chalk';\nimport jsonlines from 'jsonlines';\nimport { assert, onTestFailed, onTestFinished } from 'vitest';\nimport type { TypedHook } from 'workflow';\nimport * as z from 'zod';\nimport type manifest from '../.well-known/workflow/v1/manifest.json';\n\nexport const Control = z.object({\n state: z.literal('listening'),\n info: z.object({\n port: z.number(),\n }),\n});\ntype Control = z.infer<typeof Control>;\n\ntype Files = keyof typeof manifest.workflows;\ntype Workflows<F extends Files> = keyof (typeof manifest.workflows)[F];\n\nexport async function startServer(opts: {\n world: string;\n env?: Record<string, string | undefined>;\n}) {\n let serverPath = new URL('./server.mts', import.meta.url);\n\n if (!existsSync(serverPath)) {\n serverPath = new URL('./server.mjs', import.meta.url);\n }\n\n const proc = cp.spawn('node', [fileURLToPath(serverPath)], {\n stdio: ['ignore', 'pipe', 'pipe', 'pipe'],\n env: {\n ...process.env,\n WORKFLOW_TARGET_WORLD: opts.world,\n CONTROL_FD: '3',\n ...(opts.env ?? {}),\n },\n });\n onTestFinished(() => {\n proc.kill();\n });\n\n const stdio = [] as { stream: ChalkInstance; chunk: string }[];\n // Accumulated raw server output — used by tests that want to inspect\n // debug logs (e.g., count runtime iterations, event loads, etc.).\n const outputBuffer: string[] = [];\n proc.stdout?.on('data', (chunk) => {\n const str = chunk.toString();\n stdio.push({ stream: chalk.white, chunk: str });\n outputBuffer.push(str);\n });\n proc.stderr?.on('data', (chunk) => {\n const str = chunk.toString();\n stdio.push({ stream: chalk.red, chunk: str });\n outputBuffer.push(str);\n });\n\n onTestFailed(() => {\n console.log('=== SERVER STDIO ===');\n let buffer = '';\n for (const { stream, chunk } of stdio) {\n buffer += stream.inverse(chunk);\n }\n console.log(buffer);\n });\n\n const fd3 = proc.stdio[3];\n assert(fd3, 'fd3 should be defined');\n\n for await (const chunk of fd3.pipe(jsonlines.parse())) {\n const control = Control.parse(chunk);\n return {\n ...control,\n getOutput: () => outputBuffer.join(''),\n };\n }\n\n throw new Error('Server did not start correctly');\n}\n\nconst Invoke = z.object({ runId: z.coerce.string() });\n\nexport function createFetcher(control: Control) {\n return {\n async invoke<F extends Files, W extends Workflows<F>>(\n file: F,\n workflow: W,\n args: unknown[]\n ) {\n const x = await fetch(`http://localhost:${control.info.port}/invoke`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n },\n body: JSON.stringify({ file, workflow, args }),\n });\n const data = await x.json().then(Invoke.parse);\n onTestFailed(() => {\n console.error('Workflow run:', data.runId);\n });\n return data;\n },\n async getFlowInvocationCount(runId: string): Promise<number> {\n const x = await fetch(\n `http://localhost:${control.info.port}/_flow-invocations/${encodeURIComponent(runId)}`\n );\n const data = (await x.json()) as { count: number };\n return data.count;\n },\n async getRun(id: string) {\n const x = await fetch(\n `http://localhost:${control.info.port}/runs/${encodeURIComponent(id)}`\n );\n const text = await x.text();\n // Custom JSON reviver to decode base64 back to Uint8Array\n const data = JSON.parse(text, (_key, value) => {\n if (\n value !== null &&\n typeof value === 'object' &&\n (value as any).__type === 'Uint8Array' &&\n typeof (value as any).data === 'string'\n ) {\n return new Uint8Array(Buffer.from((value as any).data, 'base64'));\n }\n return value;\n });\n return WorkflowRunSchema.parseAsync(data);\n },\n async getReadable(id: string): Promise<ReadableStream<Uint8Array>> {\n const x = await fetch(\n `http://localhost:${control.info.port}/runs/${encodeURIComponent(id)}/readable`\n );\n if (!x.ok) {\n throw new Error(\n `Failed to get readable stream: ${x.status} ${x.statusText}`\n );\n }\n if (!x.body) {\n throw new Error('No body in response');\n }\n return x.body;\n },\n async resumeHook<T extends TypedHook<any, any>>(\n token: string,\n payload: Omit<NoInfer<TypedHook.Input<T>>, 'metadata'>\n ) {\n const res = await fetch(\n `http://localhost:${control.info.port}/hooks/${token}`,\n {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n },\n body: JSON.stringify(payload),\n }\n );\n res.arrayBuffer().catch(() => {}); // Drain the body to avoid resource leaks\n if (!res.ok) {\n throw new Error(\n `Failed to resume hook: ${res.status} ${res.statusText}`\n );\n }\n },\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@workflow/world-testing",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
3
|
+
"version": "5.0.0-beta.5",
|
|
4
4
|
"description": "Testing utilities and World implementation for Workflow SDK",
|
|
5
5
|
"main": "dist/src/index.mjs",
|
|
6
6
|
"files": [
|
|
@@ -21,10 +21,10 @@
|
|
|
21
21
|
"hono": "4.12.3",
|
|
22
22
|
"jsonlines": "0.1.1",
|
|
23
23
|
"zod": "4.3.6",
|
|
24
|
-
"@workflow/
|
|
25
|
-
"@workflow/
|
|
26
|
-
"workflow": "5.0.0-beta.
|
|
27
|
-
"@workflow/world": "5.0.0-beta.
|
|
24
|
+
"@workflow/core": "5.0.0-beta.5",
|
|
25
|
+
"@workflow/cli": "5.0.0-beta.5",
|
|
26
|
+
"workflow": "5.0.0-beta.5",
|
|
27
|
+
"@workflow/world": "5.0.0-beta.2"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@types/node": "22.19.0",
|