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.
Files changed (37) hide show
  1. package/LLM.md +7 -2
  2. package/README.md +4 -2
  3. package/dist/browser.d.ts +50 -0
  4. package/dist/browser.d.ts.map +1 -0
  5. package/dist/browser.js +149 -0
  6. package/dist/{build-mnf6v8gd.js → build-9myaxf07.js} +22 -5
  7. package/dist/cli/commands/build.d.ts.map +1 -1
  8. package/dist/cli/commands/deploy.d.ts.map +1 -1
  9. package/dist/cli/commands/types.d.ts.map +1 -1
  10. package/dist/{deploy-nhceck39.js → deploy-h1wz5p7m.js} +29 -13
  11. package/dist/{dev-b9dmrj7b.js → dev-rsdssknb.js} +381 -91
  12. package/dist/dev-server/server.d.ts.map +1 -1
  13. package/dist/index-62b3gt2g.js +12 -0
  14. package/dist/index-9ats0s83.js +70 -0
  15. package/dist/index-a0fjkq68.js +198 -0
  16. package/dist/{index-pf5s73n9.js → index-ccrh4w3t.js} +1 -281
  17. package/dist/{index-ep3445yc.js → index-f8qh2tyh.js} +34 -107
  18. package/dist/index-k7r18na8.js +0 -0
  19. package/dist/{index-m2q41jwa.js → index-n3np2d6t.js} +1 -1
  20. package/dist/index-npc1c8jx.js +44 -0
  21. package/dist/index-p7g30wd2.js +281 -0
  22. package/dist/{index-07q6yxyc.js → index-v8vvsn9x.js} +1 -0
  23. package/dist/index.js +25 -26
  24. package/dist/runtime/index.d.ts +2 -0
  25. package/dist/runtime/index.d.ts.map +1 -1
  26. package/dist/runtime/index.js +73 -0
  27. package/dist/sveltekit/index.js +5 -3
  28. package/dist/test/index.js +10 -5
  29. package/dist/test/simple-context.d.ts +1 -1
  30. package/dist/test/simple-context.d.ts.map +1 -1
  31. package/dist/{types-5nyrz1sz.js → types-wdcpnfvy.js} +44 -11
  32. package/dist/vite/index.js +118 -50
  33. package/dist/vite/plugin.d.ts.map +1 -1
  34. package/dist/worker-entry/composed-worker.d.ts +10 -0
  35. package/dist/worker-entry/composed-worker.d.ts.map +1 -0
  36. package/package.json +3 -2
  37. 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 resolveMainWorkerScriptPath(cwd, config) {
1104
- if (config.files?.fetch === false) {
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 config.files?.fetch === "string" && config.files.fetch) {
1110
- candidates.add(config.files.fetch);
1128
+ if (typeof configuredPath === "string" && configuredPath) {
1129
+ candidates.add(configuredPath);
1111
1130
  }
1112
- for (const defaultEntry of DEFAULT_FETCH_ENTRY_FILES) {
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 collectWorkerWatchRoots(cwd, config, mainWorkerScriptPath) {
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
- if (mainWorkerScriptPath) {
1135
- roots.add(dirname2(mainWorkerScriptPath));
1360
+ for (const surfacePath of Object.values(mainWorkerSurfacePaths)) {
1361
+ if (surfacePath) {
1362
+ roots.add(dirname2(surfacePath));
1363
+ }
1136
1364
  }
1137
- addFileParent(config.files?.fetch);
1138
- addFileParent(config.files?.queue);
1139
- addFileParent(config.files?.scheduled);
1140
- addFileParent(config.files?.email);
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
- // Parse headers from raw email for the Headers object
1268
- const headerLines = []
1269
- const lines = rawBody.split(/\\r?\\n/)
1270
- let bodyStart = 0
1271
- for (let i = 0; i < lines.length; i++) {
1272
- if (lines[i].trim() === '') {
1273
- bodyStart = i + 1
1274
- break
1275
- }
1276
- headerLines.push(lines[i])
1277
- }
1278
-
1279
- const headers = new Headers()
1280
- for (const line of headerLines) {
1281
- const colonIdx = line.indexOf(':')
1282
- if (colonIdx > 0) {
1283
- const key = line.slice(0, colonIdx).trim()
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 (!mainWorkerScriptPath) {
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: [mainWorkerScriptPath],
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 && !!mainWorkerScriptPath;
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 || !mainWorkerScriptPath) {
2279
+ if (enableVite || !config) {
1998
2280
  return;
1999
2281
  }
2000
- const watchRoots = collectWorkerWatchRoots(cwd, config, mainWorkerScriptPath);
2001
- if (watchRoots.length === 0) {
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 bundleMainWorker();
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
- workerSourceWatcher = chokidar.watch(watchRoots, {
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 (${watchRoots.length} root(s))`);
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
- mainWorkerScriptPath = await resolveMainWorkerScriptPath(cwd, config);
2156
- if (!enableVite && mainWorkerScriptPath) {
2157
- logger?.info(`Worker entry detected: ${mainWorkerScriptPath}`);
2158
- await bundleMainWorker();
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 fetch worker entry was found for worker-only mode");
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;AAmqBD,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,SAAS,CAkuBpE"}
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 };