@dxos/functions-simulator-cloudflare 0.8.4-main.21d9917
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 +8 -0
- package/README.md +21 -0
- package/dist/lib/browser/index.mjs +81 -0
- package/dist/lib/browser/index.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -0
- package/dist/lib/browser/testing/index.mjs +1 -0
- package/dist/lib/browser/testing/index.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +83 -0
- package/dist/lib/node-esm/index.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -0
- package/dist/lib/node-esm/testing/index.mjs +2 -0
- package/dist/lib/node-esm/testing/index.mjs.map +7 -0
- package/dist/types/src/function-worker.d.ts +32 -0
- package/dist/types/src/function-worker.d.ts.map +1 -0
- package/dist/types/src/function-worker.test.d.ts +2 -0
- package/dist/types/src/function-worker.test.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +2 -0
- package/dist/types/src/index.d.ts.map +1 -0
- package/dist/types/src/testing/index.d.ts +2 -0
- package/dist/types/src/testing/index.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -0
- package/package.json +48 -0
- package/src/function-worker.test.ts +47 -0
- package/src/function-worker.ts +113 -0
- package/src/index.ts +5 -0
- package/src/testing/index.ts +5 -0
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dxos/functions-simulator-cloudflare",
|
|
3
|
+
"version": "0.8.4-main.21d9917",
|
|
4
|
+
"description": "Simulate functions running in Cloudflare runtime",
|
|
5
|
+
"homepage": "https://dxos.org",
|
|
6
|
+
"bugs": "https://github.com/dxos/dxos/issues",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/dxos/dxos"
|
|
10
|
+
},
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"author": "info@dxos.org",
|
|
13
|
+
"sideEffects": true,
|
|
14
|
+
"type": "module",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/types/src/index.d.ts",
|
|
18
|
+
"browser": "./dist/lib/browser/index.mjs",
|
|
19
|
+
"node": "./dist/lib/node-esm/index.mjs"
|
|
20
|
+
},
|
|
21
|
+
"./testing": {
|
|
22
|
+
"types": "./dist/types/src/testing/index.d.ts",
|
|
23
|
+
"browser": "./dist/lib/browser/testing/index.mjs",
|
|
24
|
+
"node": "./dist/lib/node-esm/testing/index.mjs"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"types": "dist/types/src/index.d.ts",
|
|
28
|
+
"typesVersions": {
|
|
29
|
+
"*": {
|
|
30
|
+
"testing": [
|
|
31
|
+
"dist/types/src/testing/index.d.ts"
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"files": [
|
|
36
|
+
"dist",
|
|
37
|
+
"src"
|
|
38
|
+
],
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"miniflare": "^4.20251128.0",
|
|
41
|
+
"@dxos/context": "0.8.4-main.21d9917",
|
|
42
|
+
"@dxos/protocols": "0.8.4-main.21d9917"
|
|
43
|
+
},
|
|
44
|
+
"publishConfig": {
|
|
45
|
+
"access": "public"
|
|
46
|
+
},
|
|
47
|
+
"beast": {}
|
|
48
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { describe, expect, test } from 'vitest';
|
|
6
|
+
|
|
7
|
+
import { FunctionWorker, makeJsModule } from './function-worker';
|
|
8
|
+
|
|
9
|
+
describe('FunctionWorker', async () => {
|
|
10
|
+
test('hello world', async () => {
|
|
11
|
+
await using worker = new FunctionWorker({
|
|
12
|
+
mainModule: 'index.js',
|
|
13
|
+
modules: {
|
|
14
|
+
'index.js': makeJsModule(`
|
|
15
|
+
export default {
|
|
16
|
+
async fetch(request, env, ctx) {
|
|
17
|
+
return new Response(JSON.stringify({ success: true, data: 'Hello Miniflare!' }));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
`),
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
const result = await worker.invoke({});
|
|
24
|
+
expect(result).toEqual({ _kind: 'success', result: 'Hello Miniflare!' });
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test('multiple modules', async () => {
|
|
28
|
+
await using worker = new FunctionWorker({
|
|
29
|
+
mainModule: 'index.js',
|
|
30
|
+
modules: {
|
|
31
|
+
'const.js': makeJsModule(`
|
|
32
|
+
export const constValue = 'Hello Miniflare!';
|
|
33
|
+
`),
|
|
34
|
+
'index.js': makeJsModule(`
|
|
35
|
+
import { constValue } from './const.js';
|
|
36
|
+
export default {
|
|
37
|
+
async fetch(request, env, ctx) {
|
|
38
|
+
return new Response(JSON.stringify({ success: true, data: constValue }));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
`),
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
const result = await worker.invoke({});
|
|
45
|
+
expect(result).toEqual({ _kind: 'success', result: 'Hello Miniflare!' });
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { Miniflare, Request } from 'miniflare';
|
|
6
|
+
|
|
7
|
+
import { type Context, Resource } from '@dxos/context';
|
|
8
|
+
import { type EdgeEnvelope, type SerializedError } from '@dxos/protocols';
|
|
9
|
+
|
|
10
|
+
export type InvokeResult =
|
|
11
|
+
| {
|
|
12
|
+
_kind: 'success';
|
|
13
|
+
/**
|
|
14
|
+
* The output of the function.
|
|
15
|
+
*/
|
|
16
|
+
result: unknown;
|
|
17
|
+
}
|
|
18
|
+
| {
|
|
19
|
+
_kind: 'error';
|
|
20
|
+
error: SerializedError;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type FunctionWorkerOptions = {
|
|
24
|
+
mainModule: string;
|
|
25
|
+
modules: {
|
|
26
|
+
[filename: string]: {
|
|
27
|
+
contents: Uint8Array<ArrayBuffer>;
|
|
28
|
+
contentType: string;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const makeJsModule = (source: string) => ({
|
|
34
|
+
contentType: 'application/javascript',
|
|
35
|
+
contents: new TextEncoder().encode(source),
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
export class FunctionWorker extends Resource {
|
|
39
|
+
#miniflare: Miniflare;
|
|
40
|
+
|
|
41
|
+
constructor(opts: FunctionWorkerOptions) {
|
|
42
|
+
super();
|
|
43
|
+
if (!opts.modules[opts.mainModule]) {
|
|
44
|
+
throw new Error(`Main module not found: ${opts.mainModule}`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const modules: MiniflareModule[] = Object.entries(opts.modules).map(([filename, mod]) => {
|
|
48
|
+
switch (mod.contentType) {
|
|
49
|
+
case 'application/javascript':
|
|
50
|
+
return {
|
|
51
|
+
type: 'ESModule' as const,
|
|
52
|
+
path: filename,
|
|
53
|
+
contents: mod.contents,
|
|
54
|
+
};
|
|
55
|
+
case 'application/wasm':
|
|
56
|
+
return {
|
|
57
|
+
type: 'CompiledWasm' as const,
|
|
58
|
+
path: filename,
|
|
59
|
+
contents: mod.contents,
|
|
60
|
+
};
|
|
61
|
+
default:
|
|
62
|
+
throw new Error(`Unsupported content type: ${mod.contentType}`);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
modules.sort((a, b) => (a.path === opts.mainModule ? -1 : 1));
|
|
67
|
+
|
|
68
|
+
this.#miniflare = new Miniflare({
|
|
69
|
+
modules,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
protected override async _close(_ctx: Context): Promise<void> {
|
|
74
|
+
await this.#miniflare.dispose();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async invoke(input: unknown): Promise<InvokeResult> {
|
|
78
|
+
const request = new Request('http://functions.dxos.internal/', {
|
|
79
|
+
method: 'POST',
|
|
80
|
+
headers: {
|
|
81
|
+
'Content-Type': 'application/json',
|
|
82
|
+
'X-Edge-Env': 'test',
|
|
83
|
+
},
|
|
84
|
+
body: JSON.stringify({ data: input }),
|
|
85
|
+
});
|
|
86
|
+
const response = await this.#miniflare.dispatchFetch(request);
|
|
87
|
+
try {
|
|
88
|
+
const envelope = (await response.clone().json()) as EdgeEnvelope<unknown>;
|
|
89
|
+
if (envelope.success) {
|
|
90
|
+
return { _kind: 'success', result: envelope.data };
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
_kind: 'error',
|
|
94
|
+
error: envelope.error ?? {
|
|
95
|
+
message: envelope.message,
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
} catch (err) {
|
|
99
|
+
return {
|
|
100
|
+
_kind: 'error',
|
|
101
|
+
error: {
|
|
102
|
+
message: (await response.text()).slice(0, 1024),
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
type MiniflareModule = {
|
|
110
|
+
type: 'ESModule' | 'CommonJS' | 'Text' | 'Data' | 'CompiledWasm' | 'PythonModule' | 'PythonRequirement';
|
|
111
|
+
path: string;
|
|
112
|
+
contents?: string | Uint8Array<ArrayBuffer> | undefined;
|
|
113
|
+
};
|
package/src/index.ts
ADDED