devflare 1.0.0-next.5 → 1.0.0-next.7
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 +7 -2
- package/README.md +4 -2
- package/dist/browser.d.ts +50 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +149 -0
- package/dist/{build-mnf6v8gd.js → build-9myaxf07.js} +22 -5
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/deploy.d.ts.map +1 -1
- package/dist/cli/commands/types.d.ts.map +1 -1
- package/dist/{deploy-nhceck39.js → deploy-h1wz5p7m.js} +29 -13
- package/dist/{dev-b9dmrj7b.js → dev-rsdssknb.js} +381 -91
- package/dist/dev-server/server.d.ts.map +1 -1
- package/dist/index-62b3gt2g.js +12 -0
- package/dist/index-9ats0s83.js +70 -0
- package/dist/index-a0fjkq68.js +198 -0
- package/dist/{index-pf5s73n9.js → index-ccrh4w3t.js} +1 -281
- package/dist/{index-ep3445yc.js → index-f8qh2tyh.js} +34 -107
- package/dist/index-k7r18na8.js +0 -0
- package/dist/{index-m2q41jwa.js → index-n3np2d6t.js} +1 -1
- package/dist/index-npc1c8jx.js +44 -0
- package/dist/index-p7g30wd2.js +281 -0
- package/dist/{index-07q6yxyc.js → index-v8vvsn9x.js} +1 -0
- package/dist/index.js +25 -26
- package/dist/runtime/index.d.ts +2 -0
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +73 -0
- package/dist/sveltekit/index.js +5 -3
- package/dist/test/index.js +10 -5
- package/dist/test/simple-context.d.ts +1 -1
- package/dist/test/simple-context.d.ts.map +1 -1
- package/dist/{types-5nyrz1sz.js → types-wdcpnfvy.js} +44 -11
- package/dist/vite/index.js +118 -50
- package/dist/vite/plugin.d.ts.map +1 -1
- package/dist/worker-entry/composed-worker.d.ts +10 -0
- package/dist/worker-entry/composed-worker.d.ts.map +1 -0
- package/package.json +3 -2
- package/dist/{doctor-fmgb3d28.js → doctor-v7jy4s3r.js} +3 -3
|
@@ -10,7 +10,8 @@ import {
|
|
|
10
10
|
findDurableObjectClasses
|
|
11
11
|
} from "./index-gz1gndna.js";
|
|
12
12
|
import {
|
|
13
|
-
loadConfig
|
|
13
|
+
loadConfig,
|
|
14
|
+
resolveConfigPath
|
|
14
15
|
} from "./index-hcex3rgh.js";
|
|
15
16
|
import {
|
|
16
17
|
__require
|
|
@@ -21,7 +22,7 @@ import { createConsola } from "consola";
|
|
|
21
22
|
import { resolve as resolve3 } from "pathe";
|
|
22
23
|
|
|
23
24
|
// src/dev-server/server.ts
|
|
24
|
-
import { dirname as dirname2, resolve as resolve2 } from "pathe";
|
|
25
|
+
import { dirname as dirname2, relative as relative2, resolve as resolve2 } from "pathe";
|
|
25
26
|
|
|
26
27
|
// src/bundler/do-bundler.ts
|
|
27
28
|
import { resolve, dirname, relative } from "pathe";
|
|
@@ -1099,17 +1100,35 @@ var DEFAULT_FETCH_ENTRY_FILES = [
|
|
|
1099
1100
|
"src/fetch.mts",
|
|
1100
1101
|
"src/fetch.mjs"
|
|
1101
1102
|
];
|
|
1103
|
+
var DEFAULT_QUEUE_ENTRY_FILES = [
|
|
1104
|
+
"src/queue.ts",
|
|
1105
|
+
"src/queue.js",
|
|
1106
|
+
"src/queue.mts",
|
|
1107
|
+
"src/queue.mjs"
|
|
1108
|
+
];
|
|
1109
|
+
var DEFAULT_SCHEDULED_ENTRY_FILES = [
|
|
1110
|
+
"src/scheduled.ts",
|
|
1111
|
+
"src/scheduled.js",
|
|
1112
|
+
"src/scheduled.mts",
|
|
1113
|
+
"src/scheduled.mjs"
|
|
1114
|
+
];
|
|
1115
|
+
var DEFAULT_EMAIL_ENTRY_FILES = [
|
|
1116
|
+
"src/email.ts",
|
|
1117
|
+
"src/email.js",
|
|
1118
|
+
"src/email.mts",
|
|
1119
|
+
"src/email.mjs"
|
|
1120
|
+
];
|
|
1102
1121
|
var INTERNAL_APP_SERVICE_BINDING = "__DEVFLARE_APP";
|
|
1103
|
-
async function
|
|
1104
|
-
if (
|
|
1122
|
+
async function resolveWorkerHandlerPath(cwd, configuredPath, defaultEntries) {
|
|
1123
|
+
if (configuredPath === false) {
|
|
1105
1124
|
return null;
|
|
1106
1125
|
}
|
|
1107
1126
|
const fs = await import("node:fs/promises");
|
|
1108
1127
|
const candidates = new Set;
|
|
1109
|
-
if (typeof
|
|
1110
|
-
candidates.add(
|
|
1128
|
+
if (typeof configuredPath === "string" && configuredPath) {
|
|
1129
|
+
candidates.add(configuredPath);
|
|
1111
1130
|
}
|
|
1112
|
-
for (const defaultEntry of
|
|
1131
|
+
for (const defaultEntry of defaultEntries) {
|
|
1113
1132
|
candidates.add(defaultEntry);
|
|
1114
1133
|
}
|
|
1115
1134
|
for (const candidate of candidates) {
|
|
@@ -1123,7 +1142,214 @@ async function resolveMainWorkerScriptPath(cwd, config) {
|
|
|
1123
1142
|
}
|
|
1124
1143
|
return null;
|
|
1125
1144
|
}
|
|
1126
|
-
function
|
|
1145
|
+
async function resolveMainWorkerSurfacePaths(cwd, config) {
|
|
1146
|
+
return {
|
|
1147
|
+
fetch: await resolveWorkerHandlerPath(cwd, config.files?.fetch, DEFAULT_FETCH_ENTRY_FILES),
|
|
1148
|
+
queue: await resolveWorkerHandlerPath(cwd, config.files?.queue, DEFAULT_QUEUE_ENTRY_FILES),
|
|
1149
|
+
scheduled: await resolveWorkerHandlerPath(cwd, config.files?.scheduled, DEFAULT_SCHEDULED_ENTRY_FILES),
|
|
1150
|
+
email: await resolveWorkerHandlerPath(cwd, config.files?.email, DEFAULT_EMAIL_ENTRY_FILES)
|
|
1151
|
+
};
|
|
1152
|
+
}
|
|
1153
|
+
function getFirstWorkerSurfacePath(surfacePaths) {
|
|
1154
|
+
return surfacePaths.fetch ?? surfacePaths.queue ?? surfacePaths.scheduled ?? surfacePaths.email;
|
|
1155
|
+
}
|
|
1156
|
+
function hasWorkerSurfacePaths(surfacePaths) {
|
|
1157
|
+
return Object.values(surfacePaths).some((surfacePath) => typeof surfacePath === "string" && surfacePath.length > 0);
|
|
1158
|
+
}
|
|
1159
|
+
function toImportSpecifier(fromFilePath, toFilePath) {
|
|
1160
|
+
const specifier = relative2(dirname2(fromFilePath), toFilePath).replace(/\\/g, "/");
|
|
1161
|
+
return specifier.startsWith(".") ? specifier : `./${specifier}`;
|
|
1162
|
+
}
|
|
1163
|
+
function getMainWorkerEntryScript(surfaceImportPaths) {
|
|
1164
|
+
const importLines = [`import { runWithContext } from 'devflare/runtime'`];
|
|
1165
|
+
const moduleFallbackLines = [];
|
|
1166
|
+
const registerSurfaceModule = (identifier, importPath) => {
|
|
1167
|
+
if (importPath) {
|
|
1168
|
+
importLines.push(`import * as ${identifier} from '${importPath}'`);
|
|
1169
|
+
return;
|
|
1170
|
+
}
|
|
1171
|
+
moduleFallbackLines.push(`const ${identifier} = {}`);
|
|
1172
|
+
};
|
|
1173
|
+
registerSurfaceModule("__devflareFetchModule", surfaceImportPaths.fetch);
|
|
1174
|
+
registerSurfaceModule("__devflareQueueModule", surfaceImportPaths.queue);
|
|
1175
|
+
registerSurfaceModule("__devflareScheduledModule", surfaceImportPaths.scheduled);
|
|
1176
|
+
registerSurfaceModule("__devflareEmailModule", surfaceImportPaths.email);
|
|
1177
|
+
return `
|
|
1178
|
+
${importLines.join(`
|
|
1179
|
+
`)}
|
|
1180
|
+
${moduleFallbackLines.join(`
|
|
1181
|
+
`)}
|
|
1182
|
+
|
|
1183
|
+
const __devflareResolveHandler = (module, namedExport) => {
|
|
1184
|
+
const defaultExport = module.default
|
|
1185
|
+
|
|
1186
|
+
if (typeof defaultExport === 'function') {
|
|
1187
|
+
return defaultExport
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
if (defaultExport && typeof defaultExport[namedExport] === 'function') {
|
|
1191
|
+
return defaultExport[namedExport].bind(defaultExport)
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
if (typeof module[namedExport] === 'function') {
|
|
1195
|
+
return module[namedExport]
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
return null
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
const __devflareFetchHandler = __devflareResolveHandler(__devflareFetchModule, 'fetch')
|
|
1202
|
+
const __devflareQueueHandler = __devflareResolveHandler(__devflareQueueModule, 'queue')
|
|
1203
|
+
const __devflareScheduledHandler = __devflareResolveHandler(__devflareScheduledModule, 'scheduled')
|
|
1204
|
+
const __devflareEmailHandler = __devflareResolveHandler(__devflareEmailModule, 'email')
|
|
1205
|
+
|
|
1206
|
+
function __devflareCreateEmailHeaders(rawBody) {
|
|
1207
|
+
const headers = new Headers()
|
|
1208
|
+
const lines = rawBody.split(/\\r?\\n/)
|
|
1209
|
+
|
|
1210
|
+
for (const line of lines) {
|
|
1211
|
+
if (line.trim() === '') {
|
|
1212
|
+
break
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
const colonIndex = line.indexOf(':')
|
|
1216
|
+
if (colonIndex <= 0) {
|
|
1217
|
+
continue
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1220
|
+
headers.append(line.slice(0, colonIndex).trim(), line.slice(colonIndex + 1).trim())
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
return headers
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
function __devflareCreateEmailRawStream(rawBody) {
|
|
1227
|
+
return new ReadableStream({
|
|
1228
|
+
start(controller) {
|
|
1229
|
+
controller.enqueue(new TextEncoder().encode(rawBody))
|
|
1230
|
+
controller.close()
|
|
1231
|
+
}
|
|
1232
|
+
})
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
async function __devflareHandleInternalEmail(request, env, ctx) {
|
|
1236
|
+
if (!__devflareEmailHandler) {
|
|
1237
|
+
return new Response('Email handler not configured', { status: 501 })
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
const from = request.headers.get('x-devflare-email-from') || 'unknown@example.com'
|
|
1241
|
+
const to = request.headers.get('x-devflare-email-to') || 'worker@example.com'
|
|
1242
|
+
const rawBody = await request.text()
|
|
1243
|
+
const emailMessage = {
|
|
1244
|
+
from,
|
|
1245
|
+
to,
|
|
1246
|
+
headers: __devflareCreateEmailHeaders(rawBody),
|
|
1247
|
+
raw: __devflareCreateEmailRawStream(rawBody),
|
|
1248
|
+
rawSize: rawBody.length,
|
|
1249
|
+
setReject(reason) {
|
|
1250
|
+
console.warn('[Devflare email rejected]', reason)
|
|
1251
|
+
},
|
|
1252
|
+
async forward(rcptTo) {
|
|
1253
|
+
console.log('[Devflare email forwarded]', rcptTo)
|
|
1254
|
+
return Promise.resolve()
|
|
1255
|
+
},
|
|
1256
|
+
async reply(message) {
|
|
1257
|
+
console.log('[Devflare email reply sent]', message?.from)
|
|
1258
|
+
return Promise.resolve()
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
await runWithContext(
|
|
1263
|
+
env,
|
|
1264
|
+
ctx,
|
|
1265
|
+
null,
|
|
1266
|
+
() => __devflareEmailHandler(emailMessage, env, ctx),
|
|
1267
|
+
'email'
|
|
1268
|
+
)
|
|
1269
|
+
|
|
1270
|
+
return new Response(JSON.stringify({ ok: true, from, to }), {
|
|
1271
|
+
headers: { 'Content-Type': 'application/json' }
|
|
1272
|
+
})
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
export default {
|
|
1276
|
+
async fetch(request, env, ctx) {
|
|
1277
|
+
const url = new URL(request.url)
|
|
1278
|
+
|
|
1279
|
+
if (
|
|
1280
|
+
request.headers.get('x-devflare-event') === 'email' &&
|
|
1281
|
+
url.pathname === '/_devflare/internal/email'
|
|
1282
|
+
) {
|
|
1283
|
+
return __devflareHandleInternalEmail(request, env, ctx)
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
if (!__devflareFetchHandler) {
|
|
1287
|
+
return new Response('Fetch handler not configured', { status: 404 })
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
return runWithContext(
|
|
1291
|
+
env,
|
|
1292
|
+
ctx,
|
|
1293
|
+
request,
|
|
1294
|
+
() => __devflareFetchHandler(request, env, ctx),
|
|
1295
|
+
'fetch'
|
|
1296
|
+
)
|
|
1297
|
+
},
|
|
1298
|
+
...(__devflareQueueHandler
|
|
1299
|
+
? {
|
|
1300
|
+
async queue(batch, env, ctx) {
|
|
1301
|
+
return runWithContext(
|
|
1302
|
+
env,
|
|
1303
|
+
ctx,
|
|
1304
|
+
null,
|
|
1305
|
+
() => __devflareQueueHandler(batch, env, ctx),
|
|
1306
|
+
'queue'
|
|
1307
|
+
)
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
: {}),
|
|
1311
|
+
...(__devflareScheduledHandler
|
|
1312
|
+
? {
|
|
1313
|
+
async scheduled(controller, env, ctx) {
|
|
1314
|
+
return runWithContext(
|
|
1315
|
+
env,
|
|
1316
|
+
ctx,
|
|
1317
|
+
null,
|
|
1318
|
+
() => __devflareScheduledHandler(controller, env, ctx),
|
|
1319
|
+
'scheduled'
|
|
1320
|
+
)
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
: {}),
|
|
1324
|
+
...(__devflareEmailHandler
|
|
1325
|
+
? {
|
|
1326
|
+
async email(message, env, ctx) {
|
|
1327
|
+
return runWithContext(
|
|
1328
|
+
env,
|
|
1329
|
+
ctx,
|
|
1330
|
+
null,
|
|
1331
|
+
() => __devflareEmailHandler(message, env, ctx),
|
|
1332
|
+
'email'
|
|
1333
|
+
)
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
: {})
|
|
1337
|
+
}
|
|
1338
|
+
`;
|
|
1339
|
+
}
|
|
1340
|
+
function addWorkerWatchRoots(roots, cwd, configuredPath, defaultEntries) {
|
|
1341
|
+
if (configuredPath === false) {
|
|
1342
|
+
return;
|
|
1343
|
+
}
|
|
1344
|
+
if (typeof configuredPath === "string" && configuredPath) {
|
|
1345
|
+
roots.add(dirname2(resolve2(cwd, configuredPath)));
|
|
1346
|
+
return;
|
|
1347
|
+
}
|
|
1348
|
+
for (const defaultEntry of defaultEntries) {
|
|
1349
|
+
roots.add(dirname2(resolve2(cwd, defaultEntry)));
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
function collectWorkerWatchRoots(cwd, config, mainWorkerSurfacePaths) {
|
|
1127
1353
|
const roots = new Set;
|
|
1128
1354
|
const addFileParent = (filePath) => {
|
|
1129
1355
|
if (typeof filePath !== "string" || !filePath) {
|
|
@@ -1131,13 +1357,15 @@ function collectWorkerWatchRoots(cwd, config, mainWorkerScriptPath) {
|
|
|
1131
1357
|
}
|
|
1132
1358
|
roots.add(dirname2(resolve2(cwd, filePath)));
|
|
1133
1359
|
};
|
|
1134
|
-
|
|
1135
|
-
|
|
1360
|
+
for (const surfacePath of Object.values(mainWorkerSurfacePaths)) {
|
|
1361
|
+
if (surfacePath) {
|
|
1362
|
+
roots.add(dirname2(surfacePath));
|
|
1363
|
+
}
|
|
1136
1364
|
}
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1365
|
+
addWorkerWatchRoots(roots, cwd, config.files?.fetch, DEFAULT_FETCH_ENTRY_FILES);
|
|
1366
|
+
addWorkerWatchRoots(roots, cwd, config.files?.queue, DEFAULT_QUEUE_ENTRY_FILES);
|
|
1367
|
+
addWorkerWatchRoots(roots, cwd, config.files?.scheduled, DEFAULT_SCHEDULED_ENTRY_FILES);
|
|
1368
|
+
addWorkerWatchRoots(roots, cwd, config.files?.email, DEFAULT_EMAIL_ENTRY_FILES);
|
|
1141
1369
|
addFileParent(config.files?.transport);
|
|
1142
1370
|
if (config.files?.routes && typeof config.files.routes === "object") {
|
|
1143
1371
|
roots.add(resolve2(cwd, config.files.routes.dir));
|
|
@@ -1263,69 +1491,27 @@ async function handleEmailIncoming(request, env, ctx, url) {
|
|
|
1263
1491
|
const rawBody = await request.text()
|
|
1264
1492
|
|
|
1265
1493
|
log('Email incoming:', { from, to, bodyLength: rawBody.length })
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
const value = line.slice(colonIdx + 1).trim()
|
|
1285
|
-
headers.append(key, value)
|
|
1286
|
-
}
|
|
1287
|
-
}
|
|
1288
|
-
|
|
1289
|
-
// Create ReadableStream from raw email
|
|
1290
|
-
const rawStream = new ReadableStream({
|
|
1291
|
-
start(controller) {
|
|
1292
|
-
controller.enqueue(new TextEncoder().encode(rawBody))
|
|
1293
|
-
controller.close()
|
|
1294
|
-
}
|
|
1295
|
-
})
|
|
1296
|
-
|
|
1297
|
-
// Create ForwardableEmailMessage-like object
|
|
1298
|
-
const emailMessage = {
|
|
1299
|
-
from,
|
|
1300
|
-
to,
|
|
1301
|
-
headers,
|
|
1302
|
-
raw: rawStream,
|
|
1303
|
-
rawSize: rawBody.length,
|
|
1304
|
-
|
|
1305
|
-
setReject(reason) {
|
|
1306
|
-
log('Email rejected:', reason)
|
|
1307
|
-
},
|
|
1308
|
-
|
|
1309
|
-
async forward(rcptTo, extraHeaders) {
|
|
1310
|
-
log('Email forwarded to:', rcptTo)
|
|
1311
|
-
return Promise.resolve()
|
|
1312
|
-
},
|
|
1313
|
-
|
|
1314
|
-
async reply(message) {
|
|
1315
|
-
log('Email reply sent to:', message.from)
|
|
1316
|
-
return Promise.resolve()
|
|
1494
|
+
|
|
1495
|
+
if (APP_SERVICE_BINDING) {
|
|
1496
|
+
const appWorker = env[APP_SERVICE_BINDING]
|
|
1497
|
+
if (appWorker && typeof appWorker.fetch === 'function') {
|
|
1498
|
+
const response = await appWorker.fetch(new Request('http://devflare.internal/_devflare/internal/email', {
|
|
1499
|
+
method: 'POST',
|
|
1500
|
+
headers: {
|
|
1501
|
+
'x-devflare-event': 'email',
|
|
1502
|
+
'x-devflare-email-from': from,
|
|
1503
|
+
'x-devflare-email-to': to,
|
|
1504
|
+
'content-type': request.headers.get('content-type') || 'text/plain'
|
|
1505
|
+
},
|
|
1506
|
+
body: rawBody
|
|
1507
|
+
}))
|
|
1508
|
+
|
|
1509
|
+
if (!response.ok) {
|
|
1510
|
+
return response
|
|
1511
|
+
}
|
|
1317
1512
|
}
|
|
1318
1513
|
}
|
|
1319
1514
|
|
|
1320
|
-
// Look for email handler in the worker module
|
|
1321
|
-
// For now, we call via a special RPC method that DO workers can implement
|
|
1322
|
-
// The email binding should be configured in the worker
|
|
1323
|
-
|
|
1324
|
-
// Check if there's an EMAIL_HANDLER binding (special DO for email handling)
|
|
1325
|
-
if (env.__emailHandler && typeof env.__emailHandler.email === 'function') {
|
|
1326
|
-
await env.__emailHandler.email(emailMessage, env, ctx)
|
|
1327
|
-
}
|
|
1328
|
-
|
|
1329
1515
|
return new Response(JSON.stringify({ ok: true, from, to }), {
|
|
1330
1516
|
headers: { 'Content-Type': 'application/json' }
|
|
1331
1517
|
})
|
|
@@ -1737,16 +1923,24 @@ function createDevServer(options) {
|
|
|
1737
1923
|
let miniflare = null;
|
|
1738
1924
|
let doBundler = null;
|
|
1739
1925
|
let workerSourceWatcher = null;
|
|
1926
|
+
let workerWatchTargets = [];
|
|
1740
1927
|
let viteProcess = null;
|
|
1741
1928
|
let config = null;
|
|
1742
1929
|
let browserShim = null;
|
|
1743
1930
|
let browserShimPort = 8788;
|
|
1931
|
+
let mainWorkerSurfacePaths = {
|
|
1932
|
+
fetch: null,
|
|
1933
|
+
queue: null,
|
|
1934
|
+
scheduled: null,
|
|
1935
|
+
email: null
|
|
1936
|
+
};
|
|
1937
|
+
let resolvedWorkerConfigPath = null;
|
|
1744
1938
|
let mainWorkerScriptPath = null;
|
|
1745
1939
|
let bundledMainWorkerScriptPath = null;
|
|
1746
1940
|
let currentDoResult = null;
|
|
1747
1941
|
let reloadChain = Promise.resolve();
|
|
1748
1942
|
async function bundleMainWorker() {
|
|
1749
|
-
if (!
|
|
1943
|
+
if (!hasWorkerSurfacePaths(mainWorkerSurfacePaths)) {
|
|
1750
1944
|
bundledMainWorkerScriptPath = null;
|
|
1751
1945
|
return;
|
|
1752
1946
|
}
|
|
@@ -1755,16 +1949,27 @@ function createDevServer(options) {
|
|
|
1755
1949
|
}
|
|
1756
1950
|
const fs = await import("node:fs/promises");
|
|
1757
1951
|
const outDir = resolve2(cwd, ".devflare", "worker-bundles");
|
|
1952
|
+
const entryDir = resolve2(cwd, ".devflare", "worker-entrypoints");
|
|
1758
1953
|
await fs.rm(outDir, { recursive: true, force: true });
|
|
1759
1954
|
await fs.mkdir(outDir, { recursive: true });
|
|
1955
|
+
await fs.mkdir(entryDir, { recursive: true });
|
|
1956
|
+
const entryPath = resolve2(entryDir, "fetch-entry.ts");
|
|
1957
|
+
const surfaceImportPaths = {
|
|
1958
|
+
fetch: mainWorkerSurfacePaths.fetch ? toImportSpecifier(entryPath, mainWorkerSurfacePaths.fetch) : null,
|
|
1959
|
+
queue: mainWorkerSurfacePaths.queue ? toImportSpecifier(entryPath, mainWorkerSurfacePaths.queue) : null,
|
|
1960
|
+
scheduled: mainWorkerSurfacePaths.scheduled ? toImportSpecifier(entryPath, mainWorkerSurfacePaths.scheduled) : null,
|
|
1961
|
+
email: mainWorkerSurfacePaths.email ? toImportSpecifier(entryPath, mainWorkerSurfacePaths.email) : null
|
|
1962
|
+
};
|
|
1963
|
+
await fs.writeFile(entryPath, getMainWorkerEntryScript(surfaceImportPaths));
|
|
1760
1964
|
const result = await Bun.build({
|
|
1761
|
-
entrypoints: [
|
|
1965
|
+
entrypoints: [entryPath],
|
|
1762
1966
|
outdir: outDir,
|
|
1763
1967
|
target: "browser",
|
|
1968
|
+
conditions: ["browser"],
|
|
1764
1969
|
format: "esm",
|
|
1765
1970
|
minify: false,
|
|
1766
1971
|
splitting: false,
|
|
1767
|
-
external: ["cloudflare:workers", "cloudflare:*"]
|
|
1972
|
+
external: ["cloudflare:workers", "cloudflare:*", "node:*"]
|
|
1768
1973
|
});
|
|
1769
1974
|
if (!result.success || result.outputs.length === 0) {
|
|
1770
1975
|
const logs = result.logs.map((log) => ("message" in log) ? log.message : String(log)).join(`
|
|
@@ -1782,7 +1987,7 @@ ${logs}`);
|
|
|
1782
1987
|
const bindings = loadedConfig.bindings ?? {};
|
|
1783
1988
|
const persistPath = resolve2(cwd, ".devflare/data");
|
|
1784
1989
|
const appWorkerName = loadedConfig.name;
|
|
1785
|
-
const shouldRunMainWorker = !enableVite &&
|
|
1990
|
+
const shouldRunMainWorker = !enableVite && hasWorkerSurfacePaths(mainWorkerSurfacePaths);
|
|
1786
1991
|
const queueProducers = (() => {
|
|
1787
1992
|
if (!bindings.queues?.producers) {
|
|
1788
1993
|
return;
|
|
@@ -1793,6 +1998,23 @@ ${logs}`);
|
|
|
1793
1998
|
}
|
|
1794
1999
|
return producers;
|
|
1795
2000
|
})();
|
|
2001
|
+
const queueConsumers = (() => {
|
|
2002
|
+
if (!bindings.queues?.consumers || bindings.queues.consumers.length === 0) {
|
|
2003
|
+
return;
|
|
2004
|
+
}
|
|
2005
|
+
const consumers = {};
|
|
2006
|
+
for (const consumer of bindings.queues.consumers) {
|
|
2007
|
+
consumers[consumer.queue] = {
|
|
2008
|
+
...consumer.maxBatchSize !== undefined && { maxBatchSize: consumer.maxBatchSize },
|
|
2009
|
+
...consumer.maxBatchTimeout !== undefined && { maxBatchTimeout: consumer.maxBatchTimeout },
|
|
2010
|
+
...consumer.maxRetries !== undefined && { maxRetries: consumer.maxRetries },
|
|
2011
|
+
...consumer.deadLetterQueue && { deadLetterQueue: consumer.deadLetterQueue },
|
|
2012
|
+
...consumer.maxConcurrency !== undefined && { maxConcurrency: consumer.maxConcurrency },
|
|
2013
|
+
...consumer.retryDelay !== undefined && { retryDelay: consumer.retryDelay }
|
|
2014
|
+
};
|
|
2015
|
+
}
|
|
2016
|
+
return consumers;
|
|
2017
|
+
})();
|
|
1796
2018
|
const sharedOptions = {
|
|
1797
2019
|
port: miniflarePort,
|
|
1798
2020
|
host: "127.0.0.1",
|
|
@@ -1828,7 +2050,9 @@ ${logs}`);
|
|
|
1828
2050
|
...bindings.r2 && { r2Buckets: bindings.r2 },
|
|
1829
2051
|
...bindings.d1 && { d1Databases: bindings.d1 },
|
|
1830
2052
|
...loadedConfig.vars && Object.keys(loadedConfig.vars).length > 0 && { bindings: loadedConfig.vars },
|
|
1831
|
-
...queueProducers && { queueProducers }
|
|
2053
|
+
...queueProducers && { queueProducers },
|
|
2054
|
+
...options2.queueConsumers && { queueConsumers: options2.queueConsumers },
|
|
2055
|
+
...options2.triggers && { triggers: options2.triggers }
|
|
1832
2056
|
};
|
|
1833
2057
|
if (options2.scriptPath) {
|
|
1834
2058
|
workerConfig.scriptPath = options2.scriptPath;
|
|
@@ -1878,7 +2102,9 @@ ${logs}`);
|
|
|
1878
2102
|
const mainWorkerConfig = createWorkerConfig({
|
|
1879
2103
|
name: appWorkerName,
|
|
1880
2104
|
scriptPath: bundledMainWorkerScriptPath ?? mainWorkerScriptPath,
|
|
1881
|
-
serviceBindings: mainWorkerServiceBindings
|
|
2105
|
+
serviceBindings: mainWorkerServiceBindings,
|
|
2106
|
+
queueConsumers,
|
|
2107
|
+
triggers: loadedConfig.triggers?.crons?.length ? { crons: loadedConfig.triggers.crons } : undefined
|
|
1882
2108
|
});
|
|
1883
2109
|
workers.push(mainWorkerConfig);
|
|
1884
2110
|
}
|
|
@@ -1993,12 +2219,68 @@ ${logs}`);
|
|
|
1993
2219
|
reloadChain = queuedReload.catch(() => {});
|
|
1994
2220
|
await queuedReload;
|
|
1995
2221
|
}
|
|
2222
|
+
async function resolveWorkerConfigWatchPath() {
|
|
2223
|
+
if (configPath) {
|
|
2224
|
+
const explicitPath = resolve2(cwd, configPath);
|
|
2225
|
+
const fs = await import("node:fs/promises");
|
|
2226
|
+
try {
|
|
2227
|
+
await fs.access(explicitPath);
|
|
2228
|
+
return explicitPath;
|
|
2229
|
+
} catch {}
|
|
2230
|
+
}
|
|
2231
|
+
return await resolveConfigPath(cwd) ?? null;
|
|
2232
|
+
}
|
|
2233
|
+
async function refreshWorkerOnlySurfaceState() {
|
|
2234
|
+
if (!config) {
|
|
2235
|
+
return;
|
|
2236
|
+
}
|
|
2237
|
+
mainWorkerSurfacePaths = await resolveMainWorkerSurfacePaths(cwd, config);
|
|
2238
|
+
mainWorkerScriptPath = getFirstWorkerSurfacePath(mainWorkerSurfacePaths);
|
|
2239
|
+
if (hasWorkerSurfacePaths(mainWorkerSurfacePaths)) {
|
|
2240
|
+
await bundleMainWorker();
|
|
2241
|
+
} else {
|
|
2242
|
+
bundledMainWorkerScriptPath = null;
|
|
2243
|
+
}
|
|
2244
|
+
await syncWorkerWatchTargets();
|
|
2245
|
+
}
|
|
2246
|
+
function getWorkerWatchTargets() {
|
|
2247
|
+
if (enableVite || !config) {
|
|
2248
|
+
return [];
|
|
2249
|
+
}
|
|
2250
|
+
const targets = collectWorkerWatchRoots(cwd, config, mainWorkerSurfacePaths);
|
|
2251
|
+
if (resolvedWorkerConfigPath) {
|
|
2252
|
+
targets.push(resolvedWorkerConfigPath);
|
|
2253
|
+
}
|
|
2254
|
+
return [...new Set(targets)];
|
|
2255
|
+
}
|
|
2256
|
+
async function syncWorkerWatchTargets() {
|
|
2257
|
+
if (!workerSourceWatcher) {
|
|
2258
|
+
return;
|
|
2259
|
+
}
|
|
2260
|
+
const nextWatchTargets = getWorkerWatchTargets();
|
|
2261
|
+
const nextWatchTargetSet = new Set(nextWatchTargets);
|
|
2262
|
+
const targetsToRemove = workerWatchTargets.filter((target) => !nextWatchTargetSet.has(target));
|
|
2263
|
+
const targetsToAdd = nextWatchTargets.filter((target) => !workerWatchTargets.includes(target));
|
|
2264
|
+
if (targetsToRemove.length > 0) {
|
|
2265
|
+
await workerSourceWatcher.unwatch(targetsToRemove);
|
|
2266
|
+
}
|
|
2267
|
+
if (targetsToAdd.length > 0) {
|
|
2268
|
+
workerSourceWatcher.add(targetsToAdd);
|
|
2269
|
+
}
|
|
2270
|
+
workerWatchTargets = nextWatchTargets;
|
|
2271
|
+
}
|
|
2272
|
+
async function reloadWorkerOnlyConfig() {
|
|
2273
|
+
config = await loadConfig({ cwd, configFile: configPath });
|
|
2274
|
+
resolvedWorkerConfigPath = await resolveWorkerConfigWatchPath();
|
|
2275
|
+
await refreshWorkerOnlySurfaceState();
|
|
2276
|
+
await reloadMiniflare(currentDoResult);
|
|
2277
|
+
}
|
|
1996
2278
|
async function startWorkerSourceWatcher() {
|
|
1997
|
-
if (enableVite || !config
|
|
2279
|
+
if (enableVite || !config) {
|
|
1998
2280
|
return;
|
|
1999
2281
|
}
|
|
2000
|
-
const
|
|
2001
|
-
if (
|
|
2282
|
+
const watchTargets = getWorkerWatchTargets();
|
|
2283
|
+
if (watchTargets.length === 0) {
|
|
2002
2284
|
return;
|
|
2003
2285
|
}
|
|
2004
2286
|
const chokidar = await import("chokidar");
|
|
@@ -2019,8 +2301,14 @@ ${logs}`);
|
|
|
2019
2301
|
}
|
|
2020
2302
|
reloadInProgress = true;
|
|
2021
2303
|
try {
|
|
2304
|
+
const normalizedConfigPath = resolvedWorkerConfigPath ? normalizePath(resolvedWorkerConfigPath) : null;
|
|
2305
|
+
if (normalizedConfigPath && normalizePath(filePath) === normalizedConfigPath) {
|
|
2306
|
+
logger?.info(`Devflare config changed: ${filePath}`);
|
|
2307
|
+
await reloadWorkerOnlyConfig();
|
|
2308
|
+
return;
|
|
2309
|
+
}
|
|
2022
2310
|
logger?.info(`Worker source changed: ${filePath}`);
|
|
2023
|
-
await
|
|
2311
|
+
await refreshWorkerOnlySurfaceState();
|
|
2024
2312
|
await reloadMiniflare(currentDoResult);
|
|
2025
2313
|
} catch (error) {
|
|
2026
2314
|
logger?.error("Worker source reload failed:", error);
|
|
@@ -2041,7 +2329,8 @@ ${logs}`);
|
|
|
2041
2329
|
triggerReload(filePath);
|
|
2042
2330
|
}, 150);
|
|
2043
2331
|
};
|
|
2044
|
-
|
|
2332
|
+
workerWatchTargets = watchTargets;
|
|
2333
|
+
workerSourceWatcher = chokidar.watch(watchTargets, {
|
|
2045
2334
|
ignoreInitial: true,
|
|
2046
2335
|
usePolling: isWindows,
|
|
2047
2336
|
interval: isWindows ? 300 : undefined,
|
|
@@ -2061,7 +2350,7 @@ ${logs}`);
|
|
|
2061
2350
|
workerSourceWatcher.on("add", onFileEvent);
|
|
2062
2351
|
workerSourceWatcher.on("unlink", onFileEvent);
|
|
2063
2352
|
workerSourceWatcher.on("ready", () => {
|
|
2064
|
-
logger?.info(`Worker source watcher ready (${
|
|
2353
|
+
logger?.info(`Worker source watcher ready (${watchTargets.length} target(s))`);
|
|
2065
2354
|
});
|
|
2066
2355
|
workerSourceWatcher.on("error", (error) => {
|
|
2067
2356
|
logger?.error("Worker source watcher error:", error);
|
|
@@ -2151,13 +2440,14 @@ ${logs}`);
|
|
|
2151
2440
|
async function start() {
|
|
2152
2441
|
logger?.info("Starting unified dev server...");
|
|
2153
2442
|
config = await loadConfig({ cwd, configFile: configPath });
|
|
2443
|
+
resolvedWorkerConfigPath = await resolveWorkerConfigWatchPath();
|
|
2154
2444
|
logger?.debug("Loaded config:", config.name);
|
|
2155
|
-
|
|
2156
|
-
if (!enableVite &&
|
|
2157
|
-
|
|
2158
|
-
|
|
2445
|
+
await refreshWorkerOnlySurfaceState();
|
|
2446
|
+
if (!enableVite && hasWorkerSurfacePaths(mainWorkerSurfacePaths)) {
|
|
2447
|
+
const detectedWorkerHandlers = Object.entries(mainWorkerSurfacePaths).filter(([, surfacePath]) => !!surfacePath).map(([surfaceName, surfacePath]) => `${surfaceName}=${surfacePath}`).join(", ");
|
|
2448
|
+
logger?.info(`Worker handlers detected: ${detectedWorkerHandlers}`);
|
|
2159
2449
|
} else if (!enableVite) {
|
|
2160
|
-
logger?.warn("No local
|
|
2450
|
+
logger?.warn("No local worker handler entry was found for worker-only mode");
|
|
2161
2451
|
}
|
|
2162
2452
|
const remoteCheck = await checkRemoteBindingRequirements(config);
|
|
2163
2453
|
if (remoteCheck.hasRemoteBindings) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/dev-server/server.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAC9C,OAAO,KAAK,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,WAAW,CAAA;AAc3D,MAAM,WAAW,gBAAgB;IAChC,6BAA6B;IAC7B,GAAG,EAAE,MAAM,CAAA;IACX,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,iDAAiD;IACjD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,2BAA2B;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,sBAAsB;IACtB,MAAM,CAAC,EAAE,eAAe,CAAA;IACxB,6BAA6B;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,OAAO,CAAA;CACf;AAED,MAAM,WAAW,SAAS;IACzB,2BAA2B;IAC3B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACtB,0BAA0B;IAC1B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACrB,yCAAyC;IACzC,YAAY,IAAI,aAAa,GAAG,IAAI,CAAA;CACpC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/dev-server/server.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAC9C,OAAO,KAAK,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,WAAW,CAAA;AAc3D,MAAM,WAAW,gBAAgB;IAChC,6BAA6B;IAC7B,GAAG,EAAE,MAAM,CAAA;IACX,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,iDAAiD;IACjD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,2BAA2B;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,sBAAsB;IACtB,MAAM,CAAC,EAAE,eAAe,CAAA;IACxB,6BAA6B;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,OAAO,CAAA;CACf;AAED,MAAM,WAAW,SAAS;IACzB,2BAA2B;IAC3B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACtB,0BAA0B;IAC1B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACrB,yCAAyC;IACzC,YAAY,IAAI,aAAa,GAAG,IAAI,CAAA;CACpC;AAy3BD,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,SAAS,CAi3BpE"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// src/workerName.ts
|
|
2
|
+
var workerName = (() => {
|
|
3
|
+
if (typeof __DEVFLARE_WORKER_NAME__ !== "undefined") {
|
|
4
|
+
return __DEVFLARE_WORKER_NAME__;
|
|
5
|
+
}
|
|
6
|
+
if (typeof process !== "undefined" && process.env?.DEVFLARE_WORKER_NAME) {
|
|
7
|
+
return process.env.DEVFLARE_WORKER_NAME;
|
|
8
|
+
}
|
|
9
|
+
return "unknown";
|
|
10
|
+
})();
|
|
11
|
+
|
|
12
|
+
export { workerName };
|