devflare 1.0.0-next.1 → 1.0.0-next.10
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/LLM.md +775 -637
- package/R2.md +200 -0
- package/README.md +285 -514
- package/bin/devflare.js +8 -8
- package/dist/{account-rvrj687w.js → account-8psavtg6.js} +27 -4
- package/dist/bridge/miniflare.d.ts +6 -0
- package/dist/bridge/miniflare.d.ts.map +1 -1
- package/dist/bridge/proxy.d.ts +5 -6
- package/dist/bridge/proxy.d.ts.map +1 -1
- package/dist/bridge/server.d.ts.map +1 -1
- package/dist/browser.d.ts +50 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/{build-mnf6v8gd.js → build-k36xrzvy.js} +26 -7
- package/dist/bundler/do-bundler.d.ts +7 -0
- package/dist/bundler/do-bundler.d.ts.map +1 -1
- package/dist/cli/commands/account.d.ts.map +1 -1
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/deploy.d.ts.map +1 -1
- package/dist/cli/commands/dev.d.ts.map +1 -1
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/types.d.ts.map +1 -1
- package/dist/cli/config-path.d.ts +5 -0
- package/dist/cli/config-path.d.ts.map +1 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/package-metadata.d.ts +16 -0
- package/dist/cli/package-metadata.d.ts.map +1 -0
- package/dist/config/compiler.d.ts +7 -0
- package/dist/config/compiler.d.ts.map +1 -1
- package/dist/config/index.d.ts +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/schema.d.ts +2575 -1221
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/{deploy-nhceck39.js → deploy-dbvfq8vq.js} +33 -15
- package/dist/{dev-qnxet3j9.js → dev-rk8p6pse.js} +900 -234
- package/dist/dev-server/miniflare-log.d.ts +12 -0
- package/dist/dev-server/miniflare-log.d.ts.map +1 -0
- package/dist/dev-server/runtime-stdio.d.ts +8 -0
- package/dist/dev-server/runtime-stdio.d.ts.map +1 -0
- package/dist/dev-server/server.d.ts +2 -0
- package/dist/dev-server/server.d.ts.map +1 -1
- package/dist/dev-server/vite-utils.d.ts +37 -0
- package/dist/dev-server/vite-utils.d.ts.map +1 -0
- package/dist/{doctor-e8fy6fj5.js → doctor-06y8nxd4.js} +73 -50
- package/dist/{durable-object-t4kbb0yt.js → durable-object-yt8v1dyn.js} +1 -1
- package/dist/index-05fyzwne.js +195 -0
- package/dist/index-1p814k7s.js +227 -0
- package/dist/{index-hcex3rgh.js → index-1phx14av.js} +84 -7
- package/dist/{index-tk6ej9dj.js → index-2q3pmzrx.js} +12 -16
- package/dist/{index-pf5s73n9.js → index-59df49vn.js} +11 -281
- package/dist/index-5yxg30va.js +304 -0
- package/dist/index-62b3gt2g.js +12 -0
- package/dist/index-6h8xbs75.js +44 -0
- package/dist/{index-67qcae0f.js → index-6v3wjg1r.js} +16 -1
- package/dist/index-8gtqgb3q.js +529 -0
- package/dist/{index-gz1gndna.js → index-9wt9x09k.js} +42 -62
- package/dist/index-fef08w43.js +231 -0
- package/dist/{index-ep3445yc.js → index-jht2j546.js} +393 -170
- package/dist/index-k7r18na8.js +0 -0
- package/dist/{index-m2q41jwa.js → index-n932ytmq.js} +9 -1
- package/dist/index-pwgyy2q9.js +39 -0
- package/dist/{index-07q6yxyc.js → index-v8vvsn9x.js} +1 -0
- package/dist/index-vky23txa.js +70 -0
- package/dist/index-vs49yxn4.js +322 -0
- package/dist/{index-z14anrqp.js → index-wfbfz02q.js} +14 -15
- package/dist/index-ws68xvq2.js +311 -0
- package/dist/index-y1d8za14.js +196 -0
- package/dist/{init-f9mgmew3.js → init-na2atvz2.js} +42 -55
- package/dist/router/types.d.ts +24 -0
- package/dist/router/types.d.ts.map +1 -0
- package/dist/runtime/context.d.ts +249 -8
- package/dist/runtime/context.d.ts.map +1 -1
- package/dist/runtime/exports.d.ts +50 -55
- package/dist/runtime/exports.d.ts.map +1 -1
- package/dist/runtime/index.d.ts +8 -1
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/middleware.d.ts +77 -60
- package/dist/runtime/middleware.d.ts.map +1 -1
- package/dist/runtime/router.d.ts +7 -0
- package/dist/runtime/router.d.ts.map +1 -0
- package/dist/runtime/validation.d.ts +1 -1
- package/dist/runtime/validation.d.ts.map +1 -1
- package/dist/src/browser.js +150 -0
- package/dist/src/cli/index.js +10 -0
- package/dist/{cloudflare → src/cloudflare}/index.js +3 -3
- package/dist/{decorators → src/decorators}/index.js +2 -2
- package/dist/src/index.js +132 -0
- package/dist/src/runtime/index.js +111 -0
- package/dist/{sveltekit → src/sveltekit}/index.js +14 -6
- package/dist/{test → src/test}/index.js +22 -13
- package/dist/{vite → src/vite}/index.js +128 -59
- package/dist/sveltekit/platform.d.ts.map +1 -1
- package/dist/test/bridge-context.d.ts +5 -2
- package/dist/test/bridge-context.d.ts.map +1 -1
- package/dist/test/cf.d.ts +25 -11
- package/dist/test/cf.d.ts.map +1 -1
- package/dist/test/email.d.ts +16 -7
- package/dist/test/email.d.ts.map +1 -1
- package/dist/test/queue.d.ts.map +1 -1
- package/dist/test/resolve-service-bindings.d.ts.map +1 -1
- package/dist/test/scheduled.d.ts.map +1 -1
- package/dist/test/simple-context.d.ts +1 -1
- package/dist/test/simple-context.d.ts.map +1 -1
- package/dist/test/tail.d.ts +2 -1
- package/dist/test/tail.d.ts.map +1 -1
- package/dist/test/worker.d.ts +6 -0
- package/dist/test/worker.d.ts.map +1 -1
- package/dist/transform/durable-object.d.ts.map +1 -1
- package/dist/transform/worker-entrypoint.d.ts.map +1 -1
- package/dist/{types-5nyrz1sz.js → types-x9q7t491.js} +30 -16
- package/dist/utils/entrypoint-discovery.d.ts +6 -3
- package/dist/utils/entrypoint-discovery.d.ts.map +1 -1
- package/dist/utils/send-email.d.ts +15 -0
- package/dist/utils/send-email.d.ts.map +1 -0
- package/dist/vite/plugin.d.ts.map +1 -1
- package/dist/worker-entry/composed-worker.d.ts +13 -0
- package/dist/worker-entry/composed-worker.d.ts.map +1 -0
- package/dist/worker-entry/routes.d.ts +22 -0
- package/dist/worker-entry/routes.d.ts.map +1 -0
- package/dist/{worker-entrypoint-m9th0rg0.js → worker-entrypoint-c259fmfs.js} +1 -1
- package/package.json +21 -19
- package/dist/index.js +0 -298
- package/dist/runtime/index.js +0 -111
|
File without changes
|
|
@@ -9,7 +9,10 @@ import {
|
|
|
9
9
|
parseJsonMsg,
|
|
10
10
|
serializeValue,
|
|
11
11
|
stringifyJsonMsg
|
|
12
|
-
} from "./index-
|
|
12
|
+
} from "./index-59df49vn.js";
|
|
13
|
+
import {
|
|
14
|
+
normalizeSendEmailMessage
|
|
15
|
+
} from "./index-fef08w43.js";
|
|
13
16
|
|
|
14
17
|
// src/bridge/server.ts
|
|
15
18
|
var server_default = {
|
|
@@ -176,6 +179,8 @@ async function executeRpcMethod(method, params, env, ctx) {
|
|
|
176
179
|
return executeDoFetch(env, params[0], params[1], params[2]);
|
|
177
180
|
case "stub.rpc":
|
|
178
181
|
return executeDoRpc(env, params[0], params[1], params[2], params[3]);
|
|
182
|
+
case "email.send":
|
|
183
|
+
return executeSendEmail(binding, params[0]);
|
|
179
184
|
case "send":
|
|
180
185
|
return binding.send(params[0], params[1]);
|
|
181
186
|
case "sendBatch":
|
|
@@ -189,6 +194,9 @@ async function executeRpcMethod(method, params, env, ctx) {
|
|
|
189
194
|
throw new Error(`Unknown operation: ${method}`);
|
|
190
195
|
}
|
|
191
196
|
}
|
|
197
|
+
async function executeSendEmail(binding, message) {
|
|
198
|
+
return binding.send(normalizeSendEmailMessage(message));
|
|
199
|
+
}
|
|
192
200
|
function serializeR2Object(obj) {
|
|
193
201
|
if (!obj)
|
|
194
202
|
return null;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {
|
|
2
|
+
resolveConfigPath
|
|
3
|
+
} from "./index-1phx14av.js";
|
|
4
|
+
|
|
5
|
+
// src/cli/config-path.ts
|
|
6
|
+
import { stat } from "node:fs/promises";
|
|
7
|
+
var CONFIG_FILE_EXTENSIONS = [".ts", ".mts", ".js", ".mjs"];
|
|
8
|
+
var SUPPORTED_CONFIG_FILENAMES = CONFIG_FILE_EXTENSIONS.map((extension) => `devflare.config${extension}`);
|
|
9
|
+
function hasKnownConfigExtension(filePath) {
|
|
10
|
+
return CONFIG_FILE_EXTENSIONS.some((extension) => filePath.endsWith(extension));
|
|
11
|
+
}
|
|
12
|
+
async function getExistingFilePath(filePath) {
|
|
13
|
+
try {
|
|
14
|
+
const fileStat = await stat(filePath);
|
|
15
|
+
return fileStat.isFile() ? filePath : null;
|
|
16
|
+
} catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
async function resolveConfigCandidatePath(candidatePath) {
|
|
21
|
+
const candidates = [candidatePath];
|
|
22
|
+
if (!hasKnownConfigExtension(candidatePath)) {
|
|
23
|
+
for (const extension of CONFIG_FILE_EXTENSIONS) {
|
|
24
|
+
candidates.push(`${candidatePath}${extension}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
for (const candidate of candidates) {
|
|
28
|
+
const existingFilePath = await getExistingFilePath(candidate);
|
|
29
|
+
if (existingFilePath) {
|
|
30
|
+
return existingFilePath;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return await resolveConfigPath(candidatePath) ?? null;
|
|
34
|
+
}
|
|
35
|
+
function formatSupportedConfigFilenames() {
|
|
36
|
+
return SUPPORTED_CONFIG_FILENAMES.join(", ");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export { resolveConfigCandidatePath, formatSupportedConfigFilenames };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getContextOrNull
|
|
3
|
+
} from "./index-5yxg30va.js";
|
|
4
|
+
import {
|
|
5
|
+
bridgeEnv
|
|
6
|
+
} from "./index-59df49vn.js";
|
|
7
|
+
|
|
8
|
+
// src/env.ts
|
|
9
|
+
var testContextEnv = null;
|
|
10
|
+
var testContextDispose = null;
|
|
11
|
+
function __setTestContext(envBindings, dispose) {
|
|
12
|
+
testContextEnv = envBindings;
|
|
13
|
+
testContextDispose = dispose;
|
|
14
|
+
}
|
|
15
|
+
function __clearTestContext() {
|
|
16
|
+
testContextEnv = null;
|
|
17
|
+
testContextDispose = null;
|
|
18
|
+
}
|
|
19
|
+
var env = new Proxy({}, {
|
|
20
|
+
get(_target, prop) {
|
|
21
|
+
if (prop === "dispose") {
|
|
22
|
+
return async () => {
|
|
23
|
+
if (testContextDispose) {
|
|
24
|
+
await testContextDispose();
|
|
25
|
+
__clearTestContext();
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
const ctx = getContextOrNull();
|
|
30
|
+
if (ctx?.env) {
|
|
31
|
+
return ctx.env[prop];
|
|
32
|
+
}
|
|
33
|
+
if (testContextEnv) {
|
|
34
|
+
return testContextEnv[prop];
|
|
35
|
+
}
|
|
36
|
+
return bridgeEnv[prop];
|
|
37
|
+
},
|
|
38
|
+
has(_target, prop) {
|
|
39
|
+
if (prop === "dispose")
|
|
40
|
+
return true;
|
|
41
|
+
const ctx = getContextOrNull();
|
|
42
|
+
if (ctx?.env) {
|
|
43
|
+
return prop in ctx.env;
|
|
44
|
+
}
|
|
45
|
+
if (testContextEnv) {
|
|
46
|
+
return prop in testContextEnv;
|
|
47
|
+
}
|
|
48
|
+
return prop in bridgeEnv;
|
|
49
|
+
},
|
|
50
|
+
ownKeys(_target) {
|
|
51
|
+
const ctx = getContextOrNull();
|
|
52
|
+
if (ctx?.env) {
|
|
53
|
+
return Reflect.ownKeys(ctx.env);
|
|
54
|
+
}
|
|
55
|
+
if (testContextEnv) {
|
|
56
|
+
return Reflect.ownKeys(testContextEnv);
|
|
57
|
+
}
|
|
58
|
+
return Reflect.ownKeys(bridgeEnv);
|
|
59
|
+
},
|
|
60
|
+
getOwnPropertyDescriptor(_target, prop) {
|
|
61
|
+
if (prop === "dispose") {
|
|
62
|
+
return { configurable: true, enumerable: false, writable: false };
|
|
63
|
+
}
|
|
64
|
+
const ctx = getContextOrNull();
|
|
65
|
+
const source = ctx?.env ?? testContextEnv ?? bridgeEnv;
|
|
66
|
+
return Reflect.getOwnPropertyDescriptor(source, prop);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
export { __setTestContext, __clearTestContext, env };
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
import {
|
|
2
|
+
normalizeDOBinding
|
|
3
|
+
} from "./index-1phx14av.js";
|
|
4
|
+
import {
|
|
5
|
+
__require
|
|
6
|
+
} from "./index-37x76zdn.js";
|
|
7
|
+
|
|
8
|
+
// src/bridge/miniflare.ts
|
|
9
|
+
function generateGatewayScript() {
|
|
10
|
+
return `
|
|
11
|
+
// Gateway Worker — Provides RPC access to all bindings
|
|
12
|
+
export default {
|
|
13
|
+
async fetch(request, env, ctx) {
|
|
14
|
+
const url = new URL(request.url)
|
|
15
|
+
|
|
16
|
+
// Health check
|
|
17
|
+
if (url.pathname === '/_devflare/health') {
|
|
18
|
+
return new Response(JSON.stringify({ status: 'ok', bindings: Object.keys(env) }), {
|
|
19
|
+
headers: { 'Content-Type': 'application/json' }
|
|
20
|
+
})
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// RPC endpoint
|
|
24
|
+
if (url.pathname === '/_devflare/rpc' && request.method === 'POST') {
|
|
25
|
+
try {
|
|
26
|
+
const { method, params } = await request.json()
|
|
27
|
+
const result = await executeRpc(env, method, params)
|
|
28
|
+
return new Response(JSON.stringify({ ok: true, result }), {
|
|
29
|
+
headers: { 'Content-Type': 'application/json' }
|
|
30
|
+
})
|
|
31
|
+
} catch (error) {
|
|
32
|
+
return new Response(JSON.stringify({
|
|
33
|
+
ok: false,
|
|
34
|
+
error: { code: 'RPC_ERROR', message: error.message }
|
|
35
|
+
}), {
|
|
36
|
+
status: 500,
|
|
37
|
+
headers: { 'Content-Type': 'application/json' }
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return new Response('Devflare Gateway', { status: 200 })
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function executeRpc(env, method, params) {
|
|
47
|
+
const [bindingName, ...methodPath] = method.split('.')
|
|
48
|
+
const binding = env[bindingName]
|
|
49
|
+
const RAW_EMAIL = 'EmailMessage::raw'
|
|
50
|
+
|
|
51
|
+
if (!binding) {
|
|
52
|
+
throw new Error(\`Binding "\${bindingName}" not found\`)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const methodName = methodPath.join('.')
|
|
56
|
+
|
|
57
|
+
// KV operations
|
|
58
|
+
if (methodName === 'get') return binding.get(params[0], params[1])
|
|
59
|
+
if (methodName === 'put') return binding.put(params[0], params[1], params[2])
|
|
60
|
+
if (methodName === 'delete') return binding.delete(params[0])
|
|
61
|
+
if (methodName === 'list') return binding.list(params[0])
|
|
62
|
+
if (methodName === 'getWithMetadata') return binding.getWithMetadata(params[0], params[1])
|
|
63
|
+
|
|
64
|
+
// R2 operations
|
|
65
|
+
if (methodName === 'head') return binding.head(params[0])
|
|
66
|
+
if (methodName === 'r2.get') return serializeR2Object(await binding.get(params[0], params[1]))
|
|
67
|
+
if (methodName === 'r2.put') return serializeR2Object(await binding.put(params[0], params[1], params[2]))
|
|
68
|
+
if (methodName === 'r2.delete') return binding.delete(params[0])
|
|
69
|
+
if (methodName === 'r2.list') return serializeR2Objects(await binding.list(params[0]))
|
|
70
|
+
|
|
71
|
+
// D1 operations
|
|
72
|
+
if (methodName === 'exec') return binding.exec(params[0])
|
|
73
|
+
if (methodName === 'batch') {
|
|
74
|
+
const statements = params[0].map(s => binding.prepare(s.sql).bind(...(s.bindings || [])))
|
|
75
|
+
return binding.batch(statements)
|
|
76
|
+
}
|
|
77
|
+
if (methodName.startsWith('stmt.')) {
|
|
78
|
+
const [, stmtMethod] = methodName.split('.')
|
|
79
|
+
const [sql, ...bindings] = params
|
|
80
|
+
const stmt = binding.prepare(sql).bind(...bindings.slice(0, -1))
|
|
81
|
+
|
|
82
|
+
if (stmtMethod === 'first') return stmt.first(bindings[bindings.length - 1])
|
|
83
|
+
if (stmtMethod === 'all') return stmt.all()
|
|
84
|
+
if (stmtMethod === 'run') return stmt.run()
|
|
85
|
+
if (stmtMethod === 'raw') return stmt.raw(bindings[bindings.length - 1])
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// DO operations
|
|
89
|
+
if (methodName === 'idFromName') {
|
|
90
|
+
const id = binding.idFromName(params[0])
|
|
91
|
+
return { __type: 'DOId', hex: id.toString() }
|
|
92
|
+
}
|
|
93
|
+
if (methodName === 'idFromString') {
|
|
94
|
+
const id = binding.idFromString(params[0])
|
|
95
|
+
return { __type: 'DOId', hex: id.toString() }
|
|
96
|
+
}
|
|
97
|
+
if (methodName === 'newUniqueId') {
|
|
98
|
+
const id = binding.newUniqueId(params[0])
|
|
99
|
+
return { __type: 'DOId', hex: id.toString() }
|
|
100
|
+
}
|
|
101
|
+
if (methodName === 'stub.fetch') {
|
|
102
|
+
const [, doId, serializedReq] = params
|
|
103
|
+
const id = binding.idFromString(doId.hex)
|
|
104
|
+
const stub = binding.get(id)
|
|
105
|
+
const response = await stub.fetch(new Request(serializedReq.url, {
|
|
106
|
+
method: serializedReq.method,
|
|
107
|
+
headers: serializedReq.headers,
|
|
108
|
+
body: serializedReq.body?.type === 'bytes' ? atob(serializedReq.body.data) : undefined
|
|
109
|
+
}))
|
|
110
|
+
return serializeResponse(response)
|
|
111
|
+
}
|
|
112
|
+
if (methodName === 'stub.rpc') {
|
|
113
|
+
// DO RPC: Call a method on the DO instance
|
|
114
|
+
const [, doId, rpcMethod, rpcParams] = params
|
|
115
|
+
const id = binding.idFromString(doId.hex)
|
|
116
|
+
const stub = binding.get(id)
|
|
117
|
+
|
|
118
|
+
// Use fetch to call the RPC endpoint
|
|
119
|
+
const response = await stub.fetch(new Request('http://do/_rpc', {
|
|
120
|
+
method: 'POST',
|
|
121
|
+
headers: { 'Content-Type': 'application/json' },
|
|
122
|
+
body: JSON.stringify({ method: rpcMethod, params: rpcParams })
|
|
123
|
+
}))
|
|
124
|
+
|
|
125
|
+
const result = await response.json()
|
|
126
|
+
if (!result.ok) throw new Error(result.error?.message || 'RPC failed')
|
|
127
|
+
return result.result
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Queue operations
|
|
131
|
+
if (methodName === 'send') return binding.send(params[0], params[1])
|
|
132
|
+
if (methodName === 'sendBatch') return binding.sendBatch(params[0], params[1])
|
|
133
|
+
|
|
134
|
+
// Send Email operations
|
|
135
|
+
if (methodName === 'email.send') {
|
|
136
|
+
const message = params[0]
|
|
137
|
+
if (message && typeof message === 'object' && 'from' in message && 'to' in message && 'raw' in message) {
|
|
138
|
+
return binding.send({
|
|
139
|
+
from: message.from,
|
|
140
|
+
to: message.to,
|
|
141
|
+
[RAW_EMAIL]: createEmailMessageRaw(message.raw)
|
|
142
|
+
})
|
|
143
|
+
}
|
|
144
|
+
return binding.send(message)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Generic fallback
|
|
148
|
+
if (typeof binding[methodName] === 'function') {
|
|
149
|
+
return binding[methodName](...params)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
throw new Error(\`Unknown method: \${method}\`)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function createEmailMessageRaw(raw) {
|
|
156
|
+
if (typeof raw === 'string' || raw instanceof ReadableStream) {
|
|
157
|
+
return raw
|
|
158
|
+
}
|
|
159
|
+
if (raw instanceof ArrayBuffer || raw instanceof Uint8Array) {
|
|
160
|
+
return new Response(raw).body
|
|
161
|
+
}
|
|
162
|
+
throw new Error('Unsupported EmailMessage raw payload')
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function serializeResponse(response) {
|
|
166
|
+
return {
|
|
167
|
+
status: response.status,
|
|
168
|
+
statusText: response.statusText,
|
|
169
|
+
headers: [...response.headers.entries()],
|
|
170
|
+
body: null // Will be streamed separately for large bodies
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function serializeR2Object(obj) {
|
|
175
|
+
if (!obj) return null
|
|
176
|
+
return {
|
|
177
|
+
key: obj.key,
|
|
178
|
+
version: obj.version,
|
|
179
|
+
size: obj.size,
|
|
180
|
+
etag: obj.etag,
|
|
181
|
+
httpEtag: obj.httpEtag,
|
|
182
|
+
uploaded: obj.uploaded?.toISOString(),
|
|
183
|
+
httpMetadata: obj.httpMetadata,
|
|
184
|
+
customMetadata: obj.customMetadata
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function serializeR2Objects(result) {
|
|
189
|
+
if (!result) return null
|
|
190
|
+
return {
|
|
191
|
+
objects: result.objects.map(serializeR2Object),
|
|
192
|
+
truncated: result.truncated,
|
|
193
|
+
cursor: result.cursor,
|
|
194
|
+
delimitedPrefixes: result.delimitedPrefixes
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
`;
|
|
198
|
+
}
|
|
199
|
+
async function startMiniflare(options = {}) {
|
|
200
|
+
const { Miniflare, Log, LogLevel } = await import("miniflare");
|
|
201
|
+
const port = options.port ?? 8787;
|
|
202
|
+
const persistPath = options.persistPath ?? ".devflare/data";
|
|
203
|
+
const mfConfig = {
|
|
204
|
+
modules: true,
|
|
205
|
+
script: generateGatewayScript(),
|
|
206
|
+
port,
|
|
207
|
+
host: "127.0.0.1",
|
|
208
|
+
log: options.verbose ? new Log(LogLevel.DEBUG) : new Log(LogLevel.WARN),
|
|
209
|
+
compatibilityDate: options.compatibilityDate ?? "2024-01-01",
|
|
210
|
+
compatibilityFlags: options.compatibilityFlags ?? []
|
|
211
|
+
};
|
|
212
|
+
const hasBindings = (val) => {
|
|
213
|
+
if (!val)
|
|
214
|
+
return false;
|
|
215
|
+
if (Array.isArray(val))
|
|
216
|
+
return val.length > 0;
|
|
217
|
+
return Object.keys(val).length > 0;
|
|
218
|
+
};
|
|
219
|
+
if (hasBindings(options.kvNamespaces)) {
|
|
220
|
+
mfConfig.kvNamespaces = options.kvNamespaces;
|
|
221
|
+
if (options.persist) {
|
|
222
|
+
mfConfig.kvPersist = `${persistPath}/kv`;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
if (hasBindings(options.r2Buckets)) {
|
|
226
|
+
mfConfig.r2Buckets = options.r2Buckets;
|
|
227
|
+
if (options.persist) {
|
|
228
|
+
mfConfig.r2Persist = `${persistPath}/r2`;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (hasBindings(options.d1Databases)) {
|
|
232
|
+
mfConfig.d1Databases = options.d1Databases;
|
|
233
|
+
if (options.persist) {
|
|
234
|
+
mfConfig.d1Persist = `${persistPath}/d1`;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (options.durableObjects) {
|
|
238
|
+
mfConfig.durableObjects = options.durableObjects;
|
|
239
|
+
if (options.persist) {
|
|
240
|
+
mfConfig.durableObjectsPersist = `${persistPath}/do`;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
if (options.sendEmail) {
|
|
244
|
+
mfConfig.email = {
|
|
245
|
+
send_email: Object.entries(options.sendEmail).map(([name, config]) => ({
|
|
246
|
+
name,
|
|
247
|
+
...config.destinationAddress && {
|
|
248
|
+
destination_address: config.destinationAddress
|
|
249
|
+
},
|
|
250
|
+
...config.allowedDestinationAddresses && {
|
|
251
|
+
allowed_destination_addresses: config.allowedDestinationAddresses
|
|
252
|
+
},
|
|
253
|
+
...config.allowedSenderAddresses && {
|
|
254
|
+
allowed_sender_addresses: config.allowedSenderAddresses
|
|
255
|
+
}
|
|
256
|
+
}))
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
if (options.bindings && Object.keys(options.bindings).length > 0) {
|
|
260
|
+
mfConfig.bindings = options.bindings;
|
|
261
|
+
}
|
|
262
|
+
if (options.queues?.length) {
|
|
263
|
+
mfConfig.queueProducers = Object.fromEntries(options.queues.map((q) => [q, { queueName: q }]));
|
|
264
|
+
}
|
|
265
|
+
const mf = new Miniflare(mfConfig);
|
|
266
|
+
await mf.ready;
|
|
267
|
+
return {
|
|
268
|
+
ready: Promise.resolve(),
|
|
269
|
+
async dispose() {
|
|
270
|
+
await mf.dispose();
|
|
271
|
+
},
|
|
272
|
+
async getBindings() {
|
|
273
|
+
return mf.getBindings();
|
|
274
|
+
},
|
|
275
|
+
getKVNamespace: mf.getKVNamespace.bind(mf),
|
|
276
|
+
getR2Bucket: mf.getR2Bucket.bind(mf),
|
|
277
|
+
getD1Database: mf.getD1Database.bind(mf),
|
|
278
|
+
getDurableObjectNamespace: mf.getDurableObjectNamespace.bind(mf),
|
|
279
|
+
dispatchFetch: mf.dispatchFetch.bind(mf),
|
|
280
|
+
_mf: mf
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
async function startMiniflareFromConfig(config, options = {}) {
|
|
284
|
+
const bindings = config.bindings ?? {};
|
|
285
|
+
const mfOptions = {
|
|
286
|
+
...options,
|
|
287
|
+
compatibilityDate: config.compatibilityDate,
|
|
288
|
+
compatibilityFlags: config.compatibilityFlags,
|
|
289
|
+
kvNamespaces: bindings.kv ? bindings.kv : undefined,
|
|
290
|
+
r2Buckets: bindings.r2 ? bindings.r2 : undefined,
|
|
291
|
+
d1Databases: bindings.d1 ? bindings.d1 : undefined,
|
|
292
|
+
queues: bindings.queues?.consumers?.map((c) => c.queue),
|
|
293
|
+
sendEmail: bindings.sendEmail ? bindings.sendEmail : undefined,
|
|
294
|
+
bindings: config.vars,
|
|
295
|
+
durableObjects: bindings.durableObjects ? Object.fromEntries(Object.entries(bindings.durableObjects).map(([bindingName, doConfig]) => {
|
|
296
|
+
const normalized = normalizeDOBinding(doConfig);
|
|
297
|
+
return [
|
|
298
|
+
bindingName,
|
|
299
|
+
{
|
|
300
|
+
className: normalized.className,
|
|
301
|
+
scriptPath: normalized.scriptName
|
|
302
|
+
}
|
|
303
|
+
];
|
|
304
|
+
})) : undefined
|
|
305
|
+
};
|
|
306
|
+
return startMiniflare(mfOptions);
|
|
307
|
+
}
|
|
308
|
+
var globalMiniflare = null;
|
|
309
|
+
async function getMiniflare(options) {
|
|
310
|
+
if (!globalMiniflare) {
|
|
311
|
+
globalMiniflare = await startMiniflare(options);
|
|
312
|
+
}
|
|
313
|
+
return globalMiniflare;
|
|
314
|
+
}
|
|
315
|
+
async function stopMiniflare() {
|
|
316
|
+
if (globalMiniflare) {
|
|
317
|
+
await globalMiniflare.dispose();
|
|
318
|
+
globalMiniflare = null;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
export { startMiniflare, startMiniflareFromConfig, getMiniflare, stopMiniflare };
|
|
@@ -95,11 +95,16 @@ function transformWorkerEntrypoint(code, id, options = {}) {
|
|
|
95
95
|
}
|
|
96
96
|
const fetchFn = functions.find((f) => f.name === "fetch");
|
|
97
97
|
const rpcMethods = functions.filter((f) => f.name !== "fetch");
|
|
98
|
+
const needsFetchHelpers = Boolean(fetchFn);
|
|
98
99
|
const s = new MagicString(code);
|
|
99
100
|
const importStatement = `import { WorkerEntrypoint } from 'cloudflare:workers'
|
|
100
101
|
`;
|
|
101
|
-
if (
|
|
102
|
-
|
|
102
|
+
if (needsFetchHelpers) {
|
|
103
|
+
const runtimeImports = ["createFetchEvent", "invokeFetchHandler"];
|
|
104
|
+
if (injectContext) {
|
|
105
|
+
runtimeImports.push("runWithEventContext");
|
|
106
|
+
}
|
|
107
|
+
s.prepend(`import { ${runtimeImports.join(", ")} } from 'devflare/runtime'
|
|
103
108
|
`);
|
|
104
109
|
}
|
|
105
110
|
s.prepend(importStatement);
|
|
@@ -123,29 +128,23 @@ function transformWorkerEntrypoint(code, id, options = {}) {
|
|
|
123
128
|
class ${className} extends WorkerEntrypoint {
|
|
124
129
|
`;
|
|
125
130
|
if (fetchFn) {
|
|
126
|
-
|
|
127
|
-
classBody += ` async fetch(request: Request): Promise<Response> {
|
|
128
|
-
`;
|
|
129
|
-
classBody += ` return runWithContext(
|
|
131
|
+
classBody += ` async fetch(request: Request): Promise<Response> {
|
|
130
132
|
`;
|
|
131
|
-
|
|
133
|
+
classBody += ` const __devflareEvent = createFetchEvent(request, this.env, this.ctx)
|
|
132
134
|
`;
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
classBody += ` request,
|
|
135
|
+
if (injectContext) {
|
|
136
|
+
classBody += ` return runWithEventContext(
|
|
136
137
|
`;
|
|
137
|
-
classBody += `
|
|
138
|
+
classBody += ` __devflareEvent,
|
|
138
139
|
`;
|
|
139
|
-
classBody += `
|
|
140
|
+
classBody += ` () => invokeFetchHandler(__originalFetch, __devflareEvent)
|
|
140
141
|
`;
|
|
141
142
|
classBody += ` )
|
|
142
143
|
`;
|
|
143
144
|
classBody += ` }
|
|
144
145
|
`;
|
|
145
146
|
} else {
|
|
146
|
-
classBody += `
|
|
147
|
-
`;
|
|
148
|
-
classBody += ` return __originalFetch(request, this.env, this.ctx)
|
|
147
|
+
classBody += ` return invokeFetchHandler(__originalFetch, __devflareEvent)
|
|
149
148
|
`;
|
|
150
149
|
classBody += ` }
|
|
151
150
|
`;
|