@workflow/world-testing 4.0.1-beta.2 → 4.0.1-beta.21
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/LICENSE.md +201 -21
- package/dist/.well-known/workflow/v1/flow.d.ts +3 -0
- package/dist/.well-known/workflow/v1/flow.d.ts.map +1 -0
- package/dist/.well-known/workflow/v1/flow.js +52694 -0
- package/dist/.well-known/workflow/v1/flow.js.map +1 -0
- package/dist/.well-known/workflow/v1/manifest.debug.json +75 -0
- package/dist/.well-known/workflow/v1/step.d.ts +3 -0
- package/dist/.well-known/workflow/v1/step.d.ts.map +1 -0
- package/dist/.well-known/workflow/v1/step.js +50773 -0
- package/dist/.well-known/workflow/v1/step.js.map +1 -0
- package/dist/src/addition.d.mts +2 -0
- package/dist/src/addition.d.mts.map +1 -0
- package/dist/src/addition.mjs +24 -0
- package/dist/src/addition.mjs.map +1 -0
- package/dist/src/errors.d.mts +2 -0
- package/dist/src/errors.d.mts.map +1 -0
- package/dist/src/errors.mjs +31 -0
- package/dist/src/errors.mjs.map +1 -0
- package/dist/src/hooks.d.mts +2 -0
- package/dist/src/hooks.d.mts.map +1 -0
- package/dist/src/hooks.mjs +74 -0
- package/dist/src/hooks.mjs.map +1 -0
- package/dist/src/idempotency.d.mts +2 -0
- package/dist/src/idempotency.d.mts.map +1 -0
- package/dist/src/idempotency.mjs +25 -0
- package/dist/src/idempotency.mjs.map +1 -0
- package/dist/src/index.d.mts +2 -0
- package/dist/src/index.d.mts.map +1 -0
- package/dist/src/index.mjs +13 -0
- package/dist/src/index.mjs.map +1 -0
- package/dist/src/jsonlines.d.mts +2 -0
- package/dist/src/jsonlines.d.mts.map +1 -0
- package/dist/src/jsonlines.mjs +32 -0
- package/dist/src/jsonlines.mjs.map +1 -0
- package/dist/src/null-byte.d.mts +2 -0
- package/dist/src/null-byte.d.mts.map +1 -0
- package/dist/src/null-byte.mjs +20 -0
- package/dist/src/null-byte.mjs.map +1 -0
- package/dist/src/server.d.mts +2 -0
- package/dist/src/server.d.mts.map +1 -0
- package/dist/src/server.mjs +87 -0
- package/dist/src/server.mjs.map +1 -0
- package/dist/src/util.d.mts +86 -0
- package/dist/src/util.d.mts.map +1 -0
- package/dist/src/util.mjs +100 -0
- package/dist/src/util.mjs.map +1 -0
- package/dist/workflows/hooks.d.ts +17 -0
- package/dist/workflows/hooks.d.ts.map +1 -0
- package/dist/workflows/hooks.js +70 -0
- package/dist/workflows/hooks.js.map +1 -0
- package/package.json +15 -11
- package/CHANGELOG.md +0 -35
- package/src/addition.mts +0 -27
- package/src/idempotency.mts +0 -30
- package/src/index.mts +0 -7
- package/src/server.mts +0 -104
- package/src/util.mts +0 -99
- package/test/embedded.test.ts +0 -3
- package/tsconfig.json +0 -11
- package/turbo.json +0 -13
- package/workflows/addition.ts +0 -16
- package/workflows/noop.ts +0 -37
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../workflows/hooks.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,IAAI;;;;;;;;EAMf,CAAC;AAEH,wBAAsB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;;;;;;GActE"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.Hook = void 0;
|
|
37
|
+
exports.collectWithHook = collectWithHook;
|
|
38
|
+
const workflow_1 = require("workflow");
|
|
39
|
+
const z = __importStar(require("zod"));
|
|
40
|
+
exports.Hook = (0, workflow_1.defineHook)({
|
|
41
|
+
schema: z.object({
|
|
42
|
+
data: z.string(),
|
|
43
|
+
done: z.boolean().optional(),
|
|
44
|
+
metadata: z.unknown(),
|
|
45
|
+
}),
|
|
46
|
+
});
|
|
47
|
+
async function collectWithHook(token, customData) {
|
|
48
|
+
'use workflow';
|
|
49
|
+
const hook = exports.Hook.create({ token, metadata: { customData } });
|
|
50
|
+
const collected = [];
|
|
51
|
+
const wf = (0, workflow_1.getWritable)();
|
|
52
|
+
await writeEvent(wf, 'hookCreated');
|
|
53
|
+
for await (const event of hook) {
|
|
54
|
+
await writeEvent(wf, 'hookResumed', event);
|
|
55
|
+
collected.push(event);
|
|
56
|
+
if (event.done)
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
return { collected };
|
|
60
|
+
}
|
|
61
|
+
async function writeEvent(writable, event, payload) {
|
|
62
|
+
'use step';
|
|
63
|
+
console.log('writing event', event, payload);
|
|
64
|
+
const writer = writable.getWriter();
|
|
65
|
+
await writer.write(new TextEncoder().encode(`${JSON.stringify({
|
|
66
|
+
event,
|
|
67
|
+
payload,
|
|
68
|
+
})}\r\n`));
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../workflows/hooks.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWA,0CAcC;AAzBD,uCAAmD;AACnD,uCAAyB;AAEZ,QAAA,IAAI,GAAG,IAAA,qBAAU,EAAC;IAC7B,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;QAChB,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;QAC5B,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE;KACtB,CAAC;CACH,CAAC,CAAC;AAEI,KAAK,UAAU,eAAe,CAAC,KAAa,EAAE,UAAkB;IACrE,cAAc,CAAC;IAEf,MAAM,IAAI,GAAG,YAAI,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC;IAC9D,MAAM,SAAS,GAA6C,EAAE,CAAC;IAC/D,MAAM,EAAE,GAAG,IAAA,sBAAW,GAAE,CAAC;IACzB,MAAM,UAAU,CAAC,EAAE,EAAE,aAAa,CAAC,CAAC;IACpC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;QAC/B,MAAM,UAAU,CAAC,EAAE,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;QAC3C,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtB,IAAI,KAAK,CAAC,IAAI;YAAE,MAAM;IACxB,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,CAAC;AACvB,CAAC;AAED,KAAK,UAAU,UAAU,CACvB,QAAwB,EACxB,KAAa,EACb,OAAiB;IAEjB,UAAU,CAAC;IAEX,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,EAAE,CAAC;IACpC,MAAM,MAAM,CAAC,KAAK,CAChB,IAAI,WAAW,EAAE,CAAC,MAAM,CACtB,GAAG,IAAI,CAAC,SAAS,CAAC;QAChB,KAAK;QACL,OAAO;KACR,CAAC,MAAM,CACT,CACF,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,30 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@workflow/world-testing",
|
|
3
|
-
"version": "4.0.1-beta.
|
|
3
|
+
"version": "4.0.1-beta.21",
|
|
4
4
|
"description": "Testing utilities and World implementation for Workflow DevKit",
|
|
5
5
|
"main": "dist/src/index.mjs",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist"
|
|
8
|
+
],
|
|
6
9
|
"publishConfig": {
|
|
7
10
|
"access": "public"
|
|
8
11
|
},
|
|
9
|
-
"license": "
|
|
12
|
+
"license": "Apache-2.0",
|
|
10
13
|
"repository": {
|
|
11
14
|
"type": "git",
|
|
12
15
|
"url": "https://github.com/vercel/workflow.git",
|
|
13
16
|
"directory": "packages/world-testing"
|
|
14
17
|
},
|
|
15
18
|
"dependencies": {
|
|
16
|
-
"@hono/node-server": "
|
|
17
|
-
"chalk": "
|
|
18
|
-
"hono": "
|
|
19
|
-
"jsonlines": "
|
|
19
|
+
"@hono/node-server": "1.19.5",
|
|
20
|
+
"chalk": "5.6.2",
|
|
21
|
+
"hono": "4.9.10",
|
|
22
|
+
"jsonlines": "0.1.1",
|
|
20
23
|
"zod": "4.1.11",
|
|
21
|
-
"@workflow/
|
|
22
|
-
"workflow": "4.0.1-beta.
|
|
23
|
-
"
|
|
24
|
+
"@workflow/world": "4.0.1-beta.6",
|
|
25
|
+
"@workflow/cli": "4.0.1-beta.20",
|
|
26
|
+
"workflow": "4.0.1-beta.20"
|
|
24
27
|
},
|
|
25
28
|
"devDependencies": {
|
|
26
|
-
"@types/node": "
|
|
27
|
-
"@types/jsonlines": "
|
|
29
|
+
"@types/node": "22.19.0",
|
|
30
|
+
"@types/jsonlines": "0.1.5",
|
|
28
31
|
"vitest": "^3.2.4",
|
|
29
32
|
"@workflow/tsconfig": "4.0.1-beta.0"
|
|
30
33
|
},
|
|
@@ -35,6 +38,7 @@
|
|
|
35
38
|
"author": "",
|
|
36
39
|
"scripts": {
|
|
37
40
|
"build": "wf build && tsc",
|
|
41
|
+
"clean": "tsc --build --clean && rm -rf dist .well-known* .workflow-data",
|
|
38
42
|
"start": "node --watch src/server.mts",
|
|
39
43
|
"test": "vitest"
|
|
40
44
|
}
|
package/CHANGELOG.md
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# @workflow/world-testing
|
|
2
|
-
|
|
3
|
-
## 4.0.1-beta.2
|
|
4
|
-
|
|
5
|
-
### Patch Changes
|
|
6
|
-
|
|
7
|
-
- Updated dependencies [f5f171f]
|
|
8
|
-
- @workflow/cli@4.0.1-beta.2
|
|
9
|
-
- workflow@4.0.1-beta.2
|
|
10
|
-
|
|
11
|
-
## 4.0.1-beta.1
|
|
12
|
-
|
|
13
|
-
### Patch Changes
|
|
14
|
-
|
|
15
|
-
- 1408293: Add "description" field to `package.json` file
|
|
16
|
-
- e46294f: Add "license" and "repository" fields to `package.json` file
|
|
17
|
-
- Updated dependencies [57ebfcb]
|
|
18
|
-
- Updated dependencies [1408293]
|
|
19
|
-
- Updated dependencies [cea8530]
|
|
20
|
-
- Updated dependencies [8196cd9]
|
|
21
|
-
- Updated dependencies [8422a32]
|
|
22
|
-
- Updated dependencies [e46294f]
|
|
23
|
-
- @workflow/cli@4.0.1-beta.1
|
|
24
|
-
- workflow@4.0.1-beta.1
|
|
25
|
-
- @workflow/world@4.0.1-beta.1
|
|
26
|
-
|
|
27
|
-
## 4.0.1-beta.0
|
|
28
|
-
|
|
29
|
-
### Patch Changes
|
|
30
|
-
|
|
31
|
-
- fcf63d0: Initial publish
|
|
32
|
-
- Updated dependencies [fcf63d0]
|
|
33
|
-
- workflow@4.0.1-beta.0
|
|
34
|
-
- @workflow/world@4.0.1-beta.0
|
|
35
|
-
- @workflow/cli@4.0.1-beta.0
|
package/src/addition.mts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { expect, test, vi } from 'vitest';
|
|
2
|
-
import { createFetcher, startServer } from './util.mjs';
|
|
3
|
-
|
|
4
|
-
export function addition(world: string) {
|
|
5
|
-
test('runs an addition', { timeout: 12_000 }, async () => {
|
|
6
|
-
const server = await startServer({ world }).then(createFetcher);
|
|
7
|
-
const result = await server.invoke(
|
|
8
|
-
'workflows/addition.ts',
|
|
9
|
-
'addition',
|
|
10
|
-
[1, 2]
|
|
11
|
-
);
|
|
12
|
-
expect(result.runId).toMatch(/^wrun_.+/);
|
|
13
|
-
await vi.waitFor(
|
|
14
|
-
async () => {
|
|
15
|
-
const run = await server.getRun(result.runId);
|
|
16
|
-
expect(run).toMatchObject<Partial<typeof run>>({
|
|
17
|
-
status: 'completed',
|
|
18
|
-
output: [3],
|
|
19
|
-
});
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
interval: 200,
|
|
23
|
-
timeout: 10_000,
|
|
24
|
-
}
|
|
25
|
-
);
|
|
26
|
-
});
|
|
27
|
-
}
|
package/src/idempotency.mts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { expect, test, vi } from 'vitest';
|
|
2
|
-
import { hydrateWorkflowReturnValue } from 'workflow/internal/serialization';
|
|
3
|
-
import { createFetcher, startServer } from './util.mjs';
|
|
4
|
-
|
|
5
|
-
export function idempotency(world: string) {
|
|
6
|
-
test('idempotency', { timeout: 60_000 }, async () => {
|
|
7
|
-
const server = await startServer({ world }).then(createFetcher);
|
|
8
|
-
const result = await server.invoke('workflows/noop.ts', 'brokenWf', [1, 2]);
|
|
9
|
-
expect(result.runId).toMatch(/^wrun_.+/);
|
|
10
|
-
const run = await vi.waitFor(
|
|
11
|
-
async () => {
|
|
12
|
-
const run = await server.getRun(result.runId);
|
|
13
|
-
expect(run).toMatchObject<Partial<typeof run>>({
|
|
14
|
-
status: 'completed',
|
|
15
|
-
});
|
|
16
|
-
return run;
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
interval: 200,
|
|
20
|
-
timeout: 59_000,
|
|
21
|
-
}
|
|
22
|
-
);
|
|
23
|
-
|
|
24
|
-
const output = await hydrateWorkflowReturnValue(run.output, [], globalThis);
|
|
25
|
-
|
|
26
|
-
expect(output).toEqual({
|
|
27
|
-
numbers: Array.from({ length: 110 }, () => expect.any(Number)),
|
|
28
|
-
});
|
|
29
|
-
});
|
|
30
|
-
}
|
package/src/index.mts
DELETED
package/src/server.mts
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
|
-
import { serve } from '@hono/node-server';
|
|
3
|
-
import { Hono } from 'hono';
|
|
4
|
-
import { getRun, start } from 'workflow/api';
|
|
5
|
-
import { getWorld } from 'workflow/runtime';
|
|
6
|
-
import * as z from 'zod';
|
|
7
|
-
import flow from '../.well-known/workflow/v1/flow.js';
|
|
8
|
-
import manifest from '../.well-known/workflow/v1/manifest.debug.json' with {
|
|
9
|
-
type: 'json',
|
|
10
|
-
};
|
|
11
|
-
import step from '../.well-known/workflow/v1/step.js';
|
|
12
|
-
|
|
13
|
-
if (!process.env.WORKFLOW_TARGET_WORLD) {
|
|
14
|
-
console.error(
|
|
15
|
-
'Error: WORKFLOW_TARGET_WORLD environment variable is not set.'
|
|
16
|
-
);
|
|
17
|
-
process.exit(1);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
type Files = keyof typeof manifest.workflows;
|
|
21
|
-
type Workflows<F extends Files> = keyof (typeof manifest.workflows)[F];
|
|
22
|
-
|
|
23
|
-
const Invoke = z
|
|
24
|
-
.object({
|
|
25
|
-
file: z.literal(Object.keys(manifest.workflows) as Files[]),
|
|
26
|
-
workflow: z.string(),
|
|
27
|
-
args: z.unknown().array().default([]),
|
|
28
|
-
})
|
|
29
|
-
.transform((obj) => {
|
|
30
|
-
const file = obj.file as keyof typeof manifest.workflows;
|
|
31
|
-
const workflow = z
|
|
32
|
-
.literal(
|
|
33
|
-
Object.keys(manifest.workflows[file]) as Workflows<typeof file>[]
|
|
34
|
-
)
|
|
35
|
-
.parse(obj.workflow);
|
|
36
|
-
return {
|
|
37
|
-
args: obj.args,
|
|
38
|
-
workflow: manifest.workflows[file][workflow],
|
|
39
|
-
};
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
const app = new Hono()
|
|
43
|
-
.post('/.well-known/workflow/v1/flow', (ctx) => {
|
|
44
|
-
return flow.POST(ctx.req.raw);
|
|
45
|
-
})
|
|
46
|
-
.post('/.well-known/workflow/v1/step', (ctx) => {
|
|
47
|
-
return step.POST(ctx.req.raw);
|
|
48
|
-
})
|
|
49
|
-
.get('/_manifest', (ctx) => ctx.json(manifest))
|
|
50
|
-
.post('/invoke', async (ctx) => {
|
|
51
|
-
const json = await ctx.req.json().then(Invoke.parse);
|
|
52
|
-
const handler = await start(json.workflow, json.args);
|
|
53
|
-
|
|
54
|
-
return ctx.json({ runId: handler.runId });
|
|
55
|
-
})
|
|
56
|
-
.get('/runs/:runId', async (ctx) => {
|
|
57
|
-
return ctx.json(await getWorld().runs.get(ctx.req.param('runId')));
|
|
58
|
-
})
|
|
59
|
-
.get('/runs/:runId/readable', async (ctx) => {
|
|
60
|
-
const runId = ctx.req.param('runId');
|
|
61
|
-
const run = getRun(runId);
|
|
62
|
-
return new Response(run.getReadable());
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
serve(
|
|
66
|
-
{
|
|
67
|
-
fetch: app.fetch,
|
|
68
|
-
port: Number(process.env.PORT) || 0,
|
|
69
|
-
},
|
|
70
|
-
async (info) => {
|
|
71
|
-
console.log(`👂 listening on http://${info.address}:${info.port}`);
|
|
72
|
-
console.log('');
|
|
73
|
-
|
|
74
|
-
process.env.PORT = info.port.toString();
|
|
75
|
-
|
|
76
|
-
for (const [filename, workflows] of Object.entries(manifest.workflows)) {
|
|
77
|
-
for (const workflowName of Object.keys(workflows)) {
|
|
78
|
-
console.log(
|
|
79
|
-
`$ curl -X POST http://localhost:${info.port}/invoke -d '${JSON.stringify(
|
|
80
|
-
{
|
|
81
|
-
file: filename,
|
|
82
|
-
workflow: workflowName,
|
|
83
|
-
}
|
|
84
|
-
)}'`
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const world = getWorld();
|
|
90
|
-
if (world.start) {
|
|
91
|
-
console.log(`starting background tasks...`);
|
|
92
|
-
await world.start().then(
|
|
93
|
-
() => console.log('background tasks started.'),
|
|
94
|
-
(err) => console.error('❗ error starting background tasks:', err)
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
if (process.env.CONTROL_FD === '3') {
|
|
99
|
-
const control = fs.createWriteStream('', { fd: 3 });
|
|
100
|
-
control.write(`${JSON.stringify({ state: 'listening', info })}\n`);
|
|
101
|
-
control.end();
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
);
|
package/src/util.mts
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import cp from 'node:child_process';
|
|
2
|
-
import { existsSync } from 'node:fs';
|
|
3
|
-
import { WorkflowRunSchema } from '@workflow/world';
|
|
4
|
-
import chalk, { type ChalkInstance } from 'chalk';
|
|
5
|
-
import jsonlines from 'jsonlines';
|
|
6
|
-
import { assert, onTestFailed, onTestFinished } from 'vitest';
|
|
7
|
-
import * as z from 'zod';
|
|
8
|
-
import type manifest from '../.well-known/workflow/v1/manifest.debug.json';
|
|
9
|
-
|
|
10
|
-
export const Control = z.object({
|
|
11
|
-
state: z.literal('listening'),
|
|
12
|
-
info: z.object({
|
|
13
|
-
port: z.number(),
|
|
14
|
-
}),
|
|
15
|
-
});
|
|
16
|
-
type Control = z.infer<typeof Control>;
|
|
17
|
-
|
|
18
|
-
type Files = keyof typeof manifest.workflows;
|
|
19
|
-
type Workflows<F extends Files> = keyof (typeof manifest.workflows)[F];
|
|
20
|
-
|
|
21
|
-
export const Worlds = {
|
|
22
|
-
embedded: 'embedded',
|
|
23
|
-
postgres: '@workflow/world-postgres',
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export async function startServer(opts: { world: string }) {
|
|
27
|
-
let serverPath = new URL('./server.mts', import.meta.url).pathname;
|
|
28
|
-
|
|
29
|
-
if (!existsSync(serverPath)) {
|
|
30
|
-
serverPath = new URL('./server.mjs', import.meta.url).pathname;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const proc = cp.spawn('node', [serverPath], {
|
|
34
|
-
stdio: ['ignore', 'pipe', 'pipe', 'pipe'],
|
|
35
|
-
env: {
|
|
36
|
-
...process.env,
|
|
37
|
-
WORKFLOW_TARGET_WORLD: opts.world,
|
|
38
|
-
CONTROL_FD: '3',
|
|
39
|
-
},
|
|
40
|
-
});
|
|
41
|
-
onTestFinished(() => {
|
|
42
|
-
proc.kill();
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
const stdio = [] as { stream: ChalkInstance; chunk: string }[];
|
|
46
|
-
proc.stdout?.on('data', (chunk) => {
|
|
47
|
-
stdio.push({ stream: chalk.white, chunk: chunk.toString() });
|
|
48
|
-
});
|
|
49
|
-
proc.stderr?.on('data', (chunk) => {
|
|
50
|
-
stdio.push({ stream: chalk.red, chunk: chunk.toString() });
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
onTestFailed(() => {
|
|
54
|
-
console.log('=== SERVER STDIO ===');
|
|
55
|
-
let buffer = '';
|
|
56
|
-
for (const { stream, chunk } of stdio) {
|
|
57
|
-
buffer += stream.inverse(chunk);
|
|
58
|
-
}
|
|
59
|
-
console.log(buffer);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
const fd3 = proc.stdio[3];
|
|
63
|
-
assert(fd3, 'fd3 should be defined');
|
|
64
|
-
|
|
65
|
-
for await (const chunk of fd3.pipe(jsonlines.parse())) {
|
|
66
|
-
return Control.parse(chunk);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
throw new Error('Server did not start correctly');
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const Invoke = z.object({ runId: z.coerce.string() });
|
|
73
|
-
|
|
74
|
-
export function createFetcher(control: Control) {
|
|
75
|
-
return {
|
|
76
|
-
async invoke<F extends Files, W extends Workflows<F>>(
|
|
77
|
-
file: F,
|
|
78
|
-
workflow: W,
|
|
79
|
-
args: unknown[]
|
|
80
|
-
) {
|
|
81
|
-
const x = await fetch(`http://localhost:${control.info.port}/invoke`, {
|
|
82
|
-
method: 'POST',
|
|
83
|
-
headers: {
|
|
84
|
-
'content-type': 'application/json',
|
|
85
|
-
},
|
|
86
|
-
body: JSON.stringify({ file, workflow, args }),
|
|
87
|
-
});
|
|
88
|
-
const data = await x.json().then(Invoke.parse);
|
|
89
|
-
return data;
|
|
90
|
-
},
|
|
91
|
-
async getRun(id: string) {
|
|
92
|
-
const x = await fetch(
|
|
93
|
-
`http://localhost:${control.info.port}/runs/${encodeURIComponent(id)}`
|
|
94
|
-
);
|
|
95
|
-
const data = await x.json();
|
|
96
|
-
return WorkflowRunSchema.parseAsync(data);
|
|
97
|
-
},
|
|
98
|
-
};
|
|
99
|
-
}
|
package/test/embedded.test.ts
DELETED
package/tsconfig.json
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "@workflow/tsconfig/base.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"moduleResolution": "NodeNext",
|
|
5
|
-
"allowJs": true,
|
|
6
|
-
"module": "NodeNext",
|
|
7
|
-
"outDir": "dist"
|
|
8
|
-
},
|
|
9
|
-
"include": ["src", ".well-known"],
|
|
10
|
-
"exclude": ["node_modules", "**/*.test.ts"]
|
|
11
|
-
}
|
package/turbo.json
DELETED
package/workflows/addition.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { RetryableError } from 'workflow';
|
|
2
|
-
|
|
3
|
-
async function add(num: number, num2: number): Promise<number> {
|
|
4
|
-
'use step';
|
|
5
|
-
if (Math.random() < 0.2) {
|
|
6
|
-
throw new RetryableError('Random failure, please retry');
|
|
7
|
-
}
|
|
8
|
-
return num + num2;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export async function addition(num: number, num2: number): Promise<number> {
|
|
12
|
-
'use workflow';
|
|
13
|
-
const result = await add(num, num2);
|
|
14
|
-
console.log({ result });
|
|
15
|
-
return result;
|
|
16
|
-
}
|
package/workflows/noop.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
let count = 0;
|
|
2
|
-
export async function noop(_i: number) {
|
|
3
|
-
'use step';
|
|
4
|
-
|
|
5
|
-
count++;
|
|
6
|
-
return count;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export async function brokenWf() {
|
|
10
|
-
'use workflow';
|
|
11
|
-
|
|
12
|
-
const numbers = [] as number[];
|
|
13
|
-
|
|
14
|
-
{
|
|
15
|
-
const promises: Promise<number>[] = [];
|
|
16
|
-
for (let i = 0; i < 10; i++) {
|
|
17
|
-
promises.push(noop(i));
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
console.log('await 10');
|
|
21
|
-
numbers.push(...(await Promise.all(promises)));
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
{
|
|
25
|
-
const promises: Promise<number>[] = [];
|
|
26
|
-
for (let i = 0; i < 100; i++) {
|
|
27
|
-
promises.push(noop(1000 + i));
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
console.log('await 100');
|
|
31
|
-
numbers.push(...(await Promise.all(promises)));
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
console.log('done.');
|
|
35
|
-
|
|
36
|
-
return { numbers };
|
|
37
|
-
}
|