devflare 1.0.0-next.6 → 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.
@@ -0,0 +1,198 @@
1
+ import {
2
+ __require
3
+ } from "./index-37x76zdn.js";
4
+
5
+ // src/worker-entry/composed-worker.ts
6
+ import { defu } from "defu";
7
+ import { dirname, relative, resolve } from "pathe";
8
+ var DEFAULT_FETCH_ENTRY_FILES = [
9
+ "src/fetch.ts",
10
+ "src/fetch.js",
11
+ "src/fetch.mts",
12
+ "src/fetch.mjs"
13
+ ];
14
+ var DEFAULT_QUEUE_ENTRY_FILES = [
15
+ "src/queue.ts",
16
+ "src/queue.js",
17
+ "src/queue.mts",
18
+ "src/queue.mjs"
19
+ ];
20
+ var DEFAULT_SCHEDULED_ENTRY_FILES = [
21
+ "src/scheduled.ts",
22
+ "src/scheduled.js",
23
+ "src/scheduled.mts",
24
+ "src/scheduled.mjs"
25
+ ];
26
+ var DEFAULT_EMAIL_ENTRY_FILES = [
27
+ "src/email.ts",
28
+ "src/email.js",
29
+ "src/email.mts",
30
+ "src/email.mjs"
31
+ ];
32
+ function resolveConfigForEnvironment(config, environment) {
33
+ if (environment && config.env?.[environment]) {
34
+ return defu(config.env[environment], config);
35
+ }
36
+ return config;
37
+ }
38
+ async function resolveWorkerHandlerPath(cwd, configuredPath, defaultEntries) {
39
+ if (configuredPath === false) {
40
+ return null;
41
+ }
42
+ const fs = await import("node:fs/promises");
43
+ const candidates = new Set;
44
+ if (typeof configuredPath === "string" && configuredPath) {
45
+ candidates.add(configuredPath);
46
+ }
47
+ for (const defaultEntry of defaultEntries) {
48
+ candidates.add(defaultEntry);
49
+ }
50
+ for (const candidate of candidates) {
51
+ const absolutePath = resolve(cwd, candidate);
52
+ try {
53
+ await fs.access(absolutePath);
54
+ return absolutePath;
55
+ } catch {
56
+ continue;
57
+ }
58
+ }
59
+ return null;
60
+ }
61
+ async function resolveWorkerSurfacePaths(cwd, config) {
62
+ return {
63
+ fetch: await resolveWorkerHandlerPath(cwd, config.files?.fetch, DEFAULT_FETCH_ENTRY_FILES),
64
+ queue: await resolveWorkerHandlerPath(cwd, config.files?.queue, DEFAULT_QUEUE_ENTRY_FILES),
65
+ scheduled: await resolveWorkerHandlerPath(cwd, config.files?.scheduled, DEFAULT_SCHEDULED_ENTRY_FILES),
66
+ email: await resolveWorkerHandlerPath(cwd, config.files?.email, DEFAULT_EMAIL_ENTRY_FILES)
67
+ };
68
+ }
69
+ function toImportSpecifier(fromFilePath, toFilePath) {
70
+ const specifier = relative(dirname(fromFilePath), toFilePath).replace(/\\/g, "/");
71
+ return specifier.startsWith(".") ? specifier : `./${specifier}`;
72
+ }
73
+ function needsComposedWorkerEntrypoint(surfacePaths) {
74
+ return Boolean(surfacePaths.queue || surfacePaths.scheduled || surfacePaths.email);
75
+ }
76
+ function getComposedWorkerEntrypointSource(surfaceImportPaths) {
77
+ const importLines = [`import { runWithContext } from 'devflare/runtime'`];
78
+ const moduleFallbackLines = [];
79
+ const registerSurfaceModule = (identifier, importPath) => {
80
+ if (importPath) {
81
+ importLines.push(`import * as ${identifier} from '${importPath}'`);
82
+ return;
83
+ }
84
+ moduleFallbackLines.push(`const ${identifier} = {}`);
85
+ };
86
+ registerSurfaceModule("__devflareFetchModule", surfaceImportPaths.fetch);
87
+ registerSurfaceModule("__devflareQueueModule", surfaceImportPaths.queue);
88
+ registerSurfaceModule("__devflareScheduledModule", surfaceImportPaths.scheduled);
89
+ registerSurfaceModule("__devflareEmailModule", surfaceImportPaths.email);
90
+ return `
91
+ ${importLines.join(`
92
+ `)}
93
+ ${moduleFallbackLines.join(`
94
+ `)}
95
+
96
+ const __devflareResolveHandler = (module, namedExport) => {
97
+ const defaultExport = module.default
98
+
99
+ if (typeof defaultExport === 'function') {
100
+ return defaultExport
101
+ }
102
+
103
+ if (defaultExport && typeof defaultExport[namedExport] === 'function') {
104
+ return defaultExport[namedExport].bind(defaultExport)
105
+ }
106
+
107
+ if (typeof module[namedExport] === 'function') {
108
+ return module[namedExport]
109
+ }
110
+
111
+ return null
112
+ }
113
+
114
+ const __devflareFetchHandler = __devflareResolveHandler(__devflareFetchModule, 'fetch')
115
+ const __devflareQueueHandler = __devflareResolveHandler(__devflareQueueModule, 'queue')
116
+ const __devflareScheduledHandler = __devflareResolveHandler(__devflareScheduledModule, 'scheduled')
117
+ const __devflareEmailHandler = __devflareResolveHandler(__devflareEmailModule, 'email')
118
+
119
+ export default {
120
+ ...(__devflareFetchHandler
121
+ ? {
122
+ async fetch(request, env, ctx) {
123
+ return runWithContext(
124
+ env,
125
+ ctx,
126
+ request,
127
+ () => __devflareFetchHandler(request, env, ctx),
128
+ 'fetch'
129
+ )
130
+ }
131
+ }
132
+ : {}),
133
+ ...(__devflareQueueHandler
134
+ ? {
135
+ async queue(batch, env, ctx) {
136
+ return runWithContext(
137
+ env,
138
+ ctx,
139
+ null,
140
+ () => __devflareQueueHandler(batch, env, ctx),
141
+ 'queue'
142
+ )
143
+ }
144
+ }
145
+ : {}),
146
+ ...(__devflareScheduledHandler
147
+ ? {
148
+ async scheduled(controller, env, ctx) {
149
+ return runWithContext(
150
+ env,
151
+ ctx,
152
+ null,
153
+ () => __devflareScheduledHandler(controller, env, ctx),
154
+ 'scheduled'
155
+ )
156
+ }
157
+ }
158
+ : {}),
159
+ ...(__devflareEmailHandler
160
+ ? {
161
+ async email(message, env, ctx) {
162
+ return runWithContext(
163
+ env,
164
+ ctx,
165
+ null,
166
+ () => __devflareEmailHandler(message, env, ctx),
167
+ 'email'
168
+ )
169
+ }
170
+ }
171
+ : {})
172
+ }
173
+ `.trimStart();
174
+ }
175
+ async function prepareComposedWorkerEntrypoint(cwd, config, environment) {
176
+ const resolvedConfig = resolveConfigForEnvironment(config, environment);
177
+ if (resolvedConfig.wrangler?.passthrough && Object.prototype.hasOwnProperty.call(resolvedConfig.wrangler.passthrough, "main")) {
178
+ return null;
179
+ }
180
+ const surfacePaths = await resolveWorkerSurfacePaths(cwd, resolvedConfig);
181
+ if (!needsComposedWorkerEntrypoint(surfacePaths)) {
182
+ return null;
183
+ }
184
+ const fs = await import("node:fs/promises");
185
+ const entryDir = resolve(cwd, ".devflare", "worker-entrypoints");
186
+ const entryPath = resolve(entryDir, "main.ts");
187
+ await fs.mkdir(entryDir, { recursive: true });
188
+ const surfaceImportPaths = {
189
+ fetch: surfacePaths.fetch ? toImportSpecifier(entryPath, surfacePaths.fetch) : null,
190
+ queue: surfacePaths.queue ? toImportSpecifier(entryPath, surfacePaths.queue) : null,
191
+ scheduled: surfacePaths.scheduled ? toImportSpecifier(entryPath, surfacePaths.scheduled) : null,
192
+ email: surfacePaths.email ? toImportSpecifier(entryPath, surfacePaths.email) : null
193
+ };
194
+ await fs.writeFile(entryPath, getComposedWorkerEntrypointSource(surfaceImportPaths));
195
+ return ".devflare/worker-entrypoints/main.ts";
196
+ }
197
+
198
+ export { prepareComposedWorkerEntrypoint };
@@ -35,7 +35,8 @@ import {
35
35
  } from "./index-ccrh4w3t.js";
36
36
  import {
37
37
  loadConfig,
38
- normalizeDOBinding
38
+ normalizeDOBinding,
39
+ resolveConfigPath
39
40
  } from "./index-hcex3rgh.js";
40
41
  import {
41
42
  canProceedWithTest,
@@ -1062,15 +1063,12 @@ function getCallerDirectory() {
1062
1063
  }
1063
1064
  return process.cwd();
1064
1065
  }
1065
- function findNearestConfig(startDir) {
1066
- const configNames = ["devflare.config.ts", "devflare.config.js"];
1066
+ async function findNearestConfig(startDir) {
1067
1067
  let currentDir = startDir;
1068
1068
  while (true) {
1069
- for (const name of configNames) {
1070
- const configPath = join6(currentDir, name);
1071
- if (existsSync2(configPath)) {
1072
- return configPath;
1073
- }
1069
+ const configPath = await resolveConfigPath(currentDir);
1070
+ if (configPath) {
1071
+ return configPath;
1074
1072
  }
1075
1073
  const parentDir = dirname2(currentDir);
1076
1074
  if (parentDir === currentDir) {
@@ -1085,9 +1083,10 @@ async function createTestContext(configPath) {
1085
1083
  if (configPath) {
1086
1084
  absolutePath = resolve2(callerDir, configPath);
1087
1085
  } else {
1088
- const found = findNearestConfig(callerDir);
1086
+ const found = await findNearestConfig(callerDir);
1089
1087
  if (!found) {
1090
- throw new Error(`Could not find devflare.config.ts. Searched upward from: ${callerDir}
1088
+ throw new Error(`Could not find a devflare config file. Searched upward from: ${callerDir}
1089
+ ` + `Expected one of: devflare.config.ts, devflare.config.mts, devflare.config.js, devflare.config.mjs
1091
1090
  ` + `Either create a config file or provide an explicit path: createTestContext('./path/to/config.ts')`);
1092
1091
  }
1093
1092
  absolutePath = found;
package/dist/index.js CHANGED
@@ -14,7 +14,7 @@ import {
14
14
  stopBridgeTestContext,
15
15
  testEnv,
16
16
  withTestContext
17
- } from "./index-rprrn24p.js";
17
+ } from "./index-f8qh2tyh.js";
18
18
  import"./index-d8bdkx2h.js";
19
19
  import {
20
20
  findExportedFunctions,
@@ -215,19 +215,19 @@ async function runInit(parsed, logger, options) {
215
215
  return runInitCommand(parsed, logger, options);
216
216
  }
217
217
  async function runDev(parsed, logger, options) {
218
- const { runDevCommand } = await import("./dev-7agn9g5s.js");
218
+ const { runDevCommand } = await import("./dev-rsdssknb.js");
219
219
  return runDevCommand(parsed, logger, options);
220
220
  }
221
221
  async function runBuild(parsed, logger, options) {
222
- const { runBuildCommand } = await import("./build-nz5yrj7f.js");
222
+ const { runBuildCommand } = await import("./build-9myaxf07.js");
223
223
  return runBuildCommand(parsed, logger, options);
224
224
  }
225
225
  async function runDeploy(parsed, logger, options) {
226
- const { runDeployCommand } = await import("./deploy-a5pcxd5w.js");
226
+ const { runDeployCommand } = await import("./deploy-h1wz5p7m.js");
227
227
  return runDeployCommand(parsed, logger, options);
228
228
  }
229
229
  async function runTypes(parsed, logger, options) {
230
- const { runTypesCommand } = await import("./types-vss6vrz7.js");
230
+ const { runTypesCommand } = await import("./types-wdcpnfvy.js");
231
231
  return runTypesCommand(parsed, logger, options);
232
232
  }
233
233
  async function runDoctor(parsed, logger, options) {
@@ -26,7 +26,7 @@ import {
26
26
  testEnv,
27
27
  withTestContext,
28
28
  worker
29
- } from "../index-rprrn24p.js";
29
+ } from "../index-f8qh2tyh.js";
30
30
  import"../index-d8bdkx2h.js";
31
31
  import"../index-z14anrqp.js";
32
32
  import"../index-tk6ej9dj.js";
@@ -3,7 +3,7 @@
3
3
  * This starts Miniflare with the configured bindings and sets up the bridge.
4
4
  *
5
5
  * @param configPath - Optional path to config file. If not provided, searches
6
- * upward from the test file for devflare.config.ts.
6
+ * upward from the test file for a supported devflare config.
7
7
  * If provided, path is resolved relative to the test file.
8
8
  */
9
9
  export declare function createTestContext(configPath?: string): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"simple-context.d.ts","sourceRoot":"","sources":["../../src/test/simple-context.ts"],"names":[],"mappings":"AAiKA;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAse1E;AA+BD;;;GAGG;AACH,MAAM,WAAW,OAAO;IACvB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACxB;AAED;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,WAAW;CAAI;AAEhC;;;;;;;;GAQG;AACH,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAA"}
1
+ {"version":3,"file":"simple-context.d.ts","sourceRoot":"","sources":["../../src/test/simple-context.ts"],"names":[],"mappings":"AA8JA;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAue1E;AA+BD;;;GAGG;AACH,MAAM,WAAW,OAAO;IACvB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACxB;AAED;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,WAAW;CAAI;AAEhC;;;;;;;;GAQG;AACH,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAA"}
@@ -18,7 +18,8 @@ import"./index-v8vvsn9x.js";
18
18
  import"./index-67qcae0f.js";
19
19
  import {
20
20
  loadConfig,
21
- normalizeDOBinding
21
+ normalizeDOBinding,
22
+ resolveConfigPath
22
23
  } from "./index-hcex3rgh.js";
23
24
  import {
24
25
  __require
@@ -26,6 +27,34 @@ import {
26
27
 
27
28
  // src/cli/commands/types.ts
28
29
  import { resolve, relative, dirname } from "pathe";
30
+ var CONFIG_FILE_EXTENSIONS = [".ts", ".mts", ".js", ".mjs"];
31
+ function hasKnownConfigExtension(filePath) {
32
+ return CONFIG_FILE_EXTENSIONS.some((extension) => filePath.endsWith(extension));
33
+ }
34
+ async function resolveConfigCandidatePath(candidatePath) {
35
+ const fs = await import("node:fs/promises");
36
+ const candidates = [candidatePath];
37
+ const getExistingFilePath = async (filePath) => {
38
+ try {
39
+ const stat = await fs.stat(filePath);
40
+ return stat.isFile() ? filePath : null;
41
+ } catch {
42
+ return null;
43
+ }
44
+ };
45
+ if (!hasKnownConfigExtension(candidatePath)) {
46
+ for (const extension of CONFIG_FILE_EXTENSIONS) {
47
+ candidates.push(`${candidatePath}${extension}`);
48
+ }
49
+ }
50
+ for (const candidate of candidates) {
51
+ const existingFilePath = await getExistingFilePath(candidate);
52
+ if (existingFilePath) {
53
+ return existingFilePath;
54
+ }
55
+ }
56
+ return await resolveConfigPath(candidatePath) ?? null;
57
+ }
29
58
  async function parseConfigForRefs(configPath) {
30
59
  const fs = await import("node:fs/promises");
31
60
  const refs = [];
@@ -99,7 +128,6 @@ async function findInterfaceTypes(searchDirs) {
99
128
  return interfaces;
100
129
  }
101
130
  async function resolveReferencedConfigs(configPath, cwd) {
102
- const fs = await import("node:fs/promises");
103
131
  const referenced = [];
104
132
  const { refs, serviceBindings, doBindings } = await parseConfigForRefs(configPath);
105
133
  if (refs.length === 0) {
@@ -107,12 +135,12 @@ async function resolveReferencedConfigs(configPath, cwd) {
107
135
  }
108
136
  const configDir = dirname(configPath);
109
137
  for (const ref of refs) {
110
- let refConfigPath = resolvePackageSpecifier(ref.importPath, configDir);
111
- if (!refConfigPath.endsWith(".ts") && !refConfigPath.endsWith(".js")) {
112
- refConfigPath += ".ts";
138
+ const refImportPath = resolvePackageSpecifier(ref.importPath, configDir);
139
+ const refConfigPath = await resolveConfigCandidatePath(refImportPath);
140
+ if (!refConfigPath) {
141
+ continue;
113
142
  }
114
143
  try {
115
- await fs.access(refConfigPath);
116
144
  const refDir = dirname(refConfigPath);
117
145
  const entrypoints = await discoverEntrypointsAsync(refDir, DEFAULT_ENTRYPOINT_PATTERN);
118
146
  const refDOs = await discoverDurableObjects(refDir, DEFAULT_DO_PATTERN);
@@ -371,8 +399,12 @@ async function runTypesCommand(parsed, logger, options) {
371
399
  const outputPath = parsed.options.output || "env.d.ts";
372
400
  logger.info("Generating TypeScript types...");
373
401
  try {
374
- const actualConfigPath = configPath ? resolve(cwd, configPath) : resolve(cwd, "devflare.config.ts");
375
402
  const config = await loadConfig({ cwd, configFile: configPath });
403
+ const requestedConfigPath = configPath ? resolve(cwd, configPath) : cwd;
404
+ const actualConfigPath = await resolveConfigCandidatePath(requestedConfigPath);
405
+ if (!actualConfigPath) {
406
+ throw new Error("Could not resolve the loaded devflare config file path");
407
+ }
376
408
  const doPattern = typeof config.files?.durableObjects === "string" ? config.files.durableObjects : DEFAULT_DO_PATTERN;
377
409
  let discoveredDOs = [];
378
410
  if (config.files?.durableObjects !== false) {
@@ -1,3 +1,6 @@
1
+ import {
2
+ prepareComposedWorkerEntrypoint
3
+ } from "../index-a0fjkq68.js";
1
4
  import {
2
5
  DEFAULT_DO_PATTERN,
3
6
  findFiles
@@ -11,14 +14,15 @@ import {
11
14
  writeWranglerConfig
12
15
  } from "../index-67qcae0f.js";
13
16
  import {
14
- loadConfig
17
+ loadConfig,
18
+ resolveConfigPath
15
19
  } from "../index-hcex3rgh.js";
16
20
  import {
17
21
  __require
18
22
  } from "../index-37x76zdn.js";
19
23
 
20
24
  // src/vite/plugin.ts
21
- import { resolve } from "pathe";
25
+ import { isAbsolute, relative, resolve } from "pathe";
22
26
  var CONFIG_DIR = ".devflare";
23
27
  var VIRTUAL_DO_ENTRY = "virtual:devflare-do-entry";
24
28
  var RESOLVED_VIRTUAL_DO_ENTRY = "\x00" + VIRTUAL_DO_ENTRY;
@@ -89,6 +93,89 @@ function createAuxiliaryWorkerConfig(wranglerConfig, discovery) {
89
93
  }
90
94
  };
91
95
  }
96
+ function rebaseMainPathForConfigDir(projectRoot, configDir, mainEntry) {
97
+ if (!mainEntry) {
98
+ return mainEntry;
99
+ }
100
+ const absoluteMainPath = isAbsolute(mainEntry) ? mainEntry : resolve(projectRoot, mainEntry);
101
+ return relative(configDir, absoluteMainPath).replace(/\\/g, "/");
102
+ }
103
+ function logDiscoveredDurableObjects(projectRoot, discovery) {
104
+ if (!discovery || discovery.files.size === 0) {
105
+ return;
106
+ }
107
+ console.log(`[devflare] Discovered ${discovery.files.size} DO file(s):`);
108
+ for (const [filePath, classes] of discovery.files) {
109
+ console.log(` • ${filePath.replace(projectRoot, ".")} → ${classes.join(", ")}`);
110
+ }
111
+ }
112
+ async function buildPluginContextState(projectRoot, devflareConfig, environment) {
113
+ const wranglerConfig = compileConfig(devflareConfig, environment);
114
+ const cloudflareConfig = compileToProgrammaticConfig(devflareConfig, environment);
115
+ const composedMainEntry = await prepareComposedWorkerEntrypoint(projectRoot, devflareConfig, environment);
116
+ if (composedMainEntry) {
117
+ wranglerConfig.main = composedMainEntry;
118
+ cloudflareConfig.main = composedMainEntry;
119
+ }
120
+ let durableObjects = null;
121
+ let auxiliaryWorkerConfig = null;
122
+ const doPatternConfig = devflareConfig.files?.durableObjects;
123
+ const doPattern = typeof doPatternConfig === "string" ? doPatternConfig : DEFAULT_DO_PATTERN;
124
+ if (doPatternConfig !== false) {
125
+ const doWorkerName = `${wranglerConfig.name}-do`;
126
+ const discovery = await discoverDurableObjects(projectRoot, doPattern, doWorkerName);
127
+ if (discovery.files.size > 0) {
128
+ durableObjects = discovery;
129
+ if (wranglerConfig.durable_objects?.bindings) {
130
+ for (const binding of wranglerConfig.durable_objects.bindings) {
131
+ binding.script_name = doWorkerName;
132
+ }
133
+ }
134
+ if (cloudflareConfig.durable_objects) {
135
+ const doConfig = cloudflareConfig.durable_objects;
136
+ for (const binding of doConfig.bindings) {
137
+ binding.script_name = doWorkerName;
138
+ }
139
+ }
140
+ auxiliaryWorkerConfig = createAuxiliaryWorkerConfig(wranglerConfig, discovery);
141
+ }
142
+ }
143
+ return {
144
+ wranglerConfig,
145
+ cloudflareConfig,
146
+ durableObjects,
147
+ auxiliaryWorkerConfig
148
+ };
149
+ }
150
+ async function ensureGeneratedConfigDir(projectRoot) {
151
+ const configDir = resolve(projectRoot, CONFIG_DIR);
152
+ const fs = await import("node:fs/promises");
153
+ await fs.mkdir(configDir, { recursive: true });
154
+ const gitignorePath = resolve(configDir, ".gitignore");
155
+ try {
156
+ await fs.access(gitignorePath);
157
+ } catch {
158
+ await fs.writeFile(gitignorePath, `*
159
+ `, "utf-8");
160
+ }
161
+ return configDir;
162
+ }
163
+ async function writeGeneratedWranglerConfig(projectRoot, wranglerConfig) {
164
+ const configDir = await ensureGeneratedConfigDir(projectRoot);
165
+ const wranglerFileConfig = {
166
+ ...wranglerConfig,
167
+ ...wranglerConfig.main && {
168
+ main: rebaseMainPathForConfigDir(projectRoot, configDir, wranglerConfig.main)
169
+ }
170
+ };
171
+ await writeWranglerConfig(configDir, wranglerFileConfig, "wrangler.jsonc");
172
+ }
173
+ async function resolvePluginConfigPath(projectRoot, configPath) {
174
+ if (configPath) {
175
+ return isAbsolute(configPath) ? configPath : resolve(projectRoot, configPath);
176
+ }
177
+ return await resolveConfigPath(projectRoot) ?? null;
178
+ }
92
179
  function devflarePlugin(options = {}) {
93
180
  const {
94
181
  configPath,
@@ -100,6 +187,7 @@ function devflarePlugin(options = {}) {
100
187
  } = options;
101
188
  let projectRoot;
102
189
  let devflareConfig;
190
+ let resolvedPluginConfigPath = null;
103
191
  return {
104
192
  name: "devflare",
105
193
  enforce: "pre",
@@ -175,54 +263,22 @@ export default { fetch: () => new Response("No DOs") }`;
175
263
  async configResolved(config) {
176
264
  projectRoot = config.root;
177
265
  pluginContext.projectRoot = projectRoot;
266
+ resolvedPluginConfigPath = await resolvePluginConfigPath(projectRoot, configPath);
178
267
  try {
179
268
  devflareConfig = await loadConfig({
180
269
  cwd: projectRoot,
181
270
  configFile: configPath
182
271
  });
183
- const wranglerConfig = compileConfig(devflareConfig, environment);
184
- pluginContext.wranglerConfig = wranglerConfig;
185
- const cloudflareConfig = compileToProgrammaticConfig(devflareConfig, environment);
186
- pluginContext.cloudflareConfig = cloudflareConfig;
187
- const doPatternConfig = devflareConfig.files?.durableObjects;
188
- const doPattern = typeof doPatternConfig === "string" ? doPatternConfig : DEFAULT_DO_PATTERN;
189
- if (doPatternConfig !== false) {
190
- const doWorkerName = `${wranglerConfig.name}-do`;
191
- const discovery = await discoverDurableObjects(projectRoot, doPattern, doWorkerName);
192
- pluginContext.durableObjects = discovery;
193
- if (discovery.files.size > 0) {
194
- if (wranglerConfig.durable_objects?.bindings) {
195
- for (const binding of wranglerConfig.durable_objects.bindings) {
196
- binding.script_name = doWorkerName;
197
- }
198
- }
199
- if (cloudflareConfig.durable_objects) {
200
- const doConfig = cloudflareConfig.durable_objects;
201
- for (const binding of doConfig.bindings) {
202
- binding.script_name = doWorkerName;
203
- }
204
- }
205
- pluginContext.auxiliaryWorkerConfig = createAuxiliaryWorkerConfig(wranglerConfig, discovery);
206
- console.log(`[devflare] Discovered ${discovery.files.size} DO file(s):`);
207
- for (const [filePath, classes] of discovery.files) {
208
- console.log(` • ${filePath.replace(projectRoot, ".")} → ${classes.join(", ")}`);
209
- }
210
- }
211
- }
212
- const configDir = resolve(projectRoot, CONFIG_DIR);
213
- const fs = await import("node:fs/promises");
214
- await fs.mkdir(configDir, { recursive: true });
215
- const gitignorePath = resolve(configDir, ".gitignore");
216
- try {
217
- await fs.access(gitignorePath);
218
- } catch {
219
- await fs.writeFile(gitignorePath, `*
220
- `, "utf-8");
221
- }
222
- await writeWranglerConfig(configDir, wranglerConfig, "wrangler.jsonc");
272
+ const pluginState = await buildPluginContextState(projectRoot, devflareConfig, environment);
273
+ Object.assign(pluginContext, {
274
+ projectRoot,
275
+ ...pluginState
276
+ });
277
+ logDiscoveredDurableObjects(projectRoot, pluginState.durableObjects);
278
+ await writeGeneratedWranglerConfig(projectRoot, pluginState.wranglerConfig);
223
279
  if (config.command === "serve") {
224
280
  console.log("[devflare] Config generated to .devflare/wrangler.jsonc");
225
- if (pluginContext.auxiliaryWorkerConfig) {
281
+ if (pluginState.auxiliaryWorkerConfig) {
226
282
  console.log("[devflare] ✓ Auxiliary DO worker configured");
227
283
  }
228
284
  }
@@ -239,8 +295,7 @@ export default { fetch: () => new Response("No DOs") }`;
239
295
  configureServer(server) {
240
296
  if (!watchConfig)
241
297
  return;
242
- const configFileName = configPath || "devflare.config.ts";
243
- const fullConfigPath = resolve(projectRoot, configFileName);
298
+ const fullConfigPath = resolvedPluginConfigPath ?? resolve(projectRoot, configPath || "devflare.config.ts");
244
299
  server.watcher.add(fullConfigPath);
245
300
  server.watcher.on("change", async (changedPath) => {
246
301
  if (changedPath === fullConfigPath) {
@@ -250,10 +305,13 @@ export default { fetch: () => new Response("No DOs") }`;
250
305
  cwd: projectRoot,
251
306
  configFile: configPath
252
307
  });
253
- const wranglerConfig = compileConfig(devflareConfig, environment);
254
- pluginContext.wranglerConfig = wranglerConfig;
255
- const cloudflareConfig = compileToProgrammaticConfig(devflareConfig, environment);
256
- pluginContext.cloudflareConfig = cloudflareConfig;
308
+ const pluginState = await buildPluginContextState(projectRoot, devflareConfig, environment);
309
+ Object.assign(pluginContext, {
310
+ projectRoot,
311
+ ...pluginState
312
+ });
313
+ logDiscoveredDurableObjects(projectRoot, pluginState.durableObjects);
314
+ await writeGeneratedWranglerConfig(projectRoot, pluginState.wranglerConfig);
257
315
  console.log("[devflare] Config reloaded");
258
316
  server.ws.send({
259
317
  type: "full-reload",
@@ -302,7 +360,12 @@ async function getCloudflareConfig(options = {}) {
302
360
  cwd,
303
361
  configFile: options.configPath
304
362
  });
305
- return compileToProgrammaticConfig(devflareConfig, options.environment);
363
+ const composedMainEntry = await prepareComposedWorkerEntrypoint(cwd, devflareConfig, options.environment);
364
+ const cloudflareConfig = compileToProgrammaticConfig(devflareConfig, options.environment);
365
+ if (composedMainEntry) {
366
+ cloudflareConfig.main = composedMainEntry;
367
+ }
368
+ return cloudflareConfig;
306
369
  }
307
370
  async function getDevflareConfigs(options = {}) {
308
371
  const cwd = options.cwd ?? process.cwd();
@@ -310,8 +373,13 @@ async function getDevflareConfigs(options = {}) {
310
373
  cwd,
311
374
  configFile: options.configPath
312
375
  });
376
+ const composedMainEntry = await prepareComposedWorkerEntrypoint(cwd, devflareConfig, options.environment);
313
377
  const wranglerConfig = compileConfig(devflareConfig, options.environment);
314
378
  const cloudflareConfig = { ...wranglerConfig };
379
+ if (composedMainEntry) {
380
+ wranglerConfig.main = composedMainEntry;
381
+ cloudflareConfig.main = composedMainEntry;
382
+ }
315
383
  const auxiliaryWorkers = [];
316
384
  const doPatternConfig = devflareConfig.files?.durableObjects;
317
385
  const doPattern = typeof doPatternConfig === "string" ? doPatternConfig : DEFAULT_DO_PATTERN;
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/vite/plugin.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,MAAM,EAAiC,MAAM,MAAM,CAAA;AAGjE,OAAO,EAIN,KAAK,cAAc,EACnB,MAAM,oBAAoB,CAAA;AAW3B,MAAM,WAAW,qBAAqB;IACrC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IAEtB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;IAErB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;CAC1B;AAED,MAAM,WAAW,qBAAqB;IACrC;;OAEG;IACH,cAAc,EAAE,cAAc,GAAG,IAAI,CAAA;IAErC;;OAEG;IACH,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IAEhD;;OAEG;IACH,WAAW,EAAE,MAAM,CAAA;IAEnB;;;OAGG;IACH,qBAAqB,EAAE,qBAAqB,GAAG,IAAI,CAAA;IAEnD;;OAEG;IACH,cAAc,EAAE,iBAAiB,GAAG,IAAI,CAAA;CACxC;AAED,MAAM,WAAW,iBAAiB;IACjC,gDAA8C;IAC9C,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;IAC5B,8CAA8C;IAC9C,UAAU,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,qBAAqB;IACrC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC/B;AAWD;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,qBAAqB,CAExD;AA8FD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,MAAM,CAmR1E;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,GAAE;IAClD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;CACf,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAQxC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,GAAE;IACjD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;CACf,GAAG,OAAO,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACzC,gBAAgB,EAAE,qBAAqB,EAAE,CAAA;CACzC,CAAC,CAiCD;AAGD,eAAe,cAAc,CAAA"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/vite/plugin.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,MAAM,EAAiC,MAAM,MAAM,CAAA;AAGjE,OAAO,EAIN,KAAK,cAAc,EACnB,MAAM,oBAAoB,CAAA;AAY3B,MAAM,WAAW,qBAAqB;IACrC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IAEtB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;IAErB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;CAC1B;AAED,MAAM,WAAW,qBAAqB;IACrC;;OAEG;IACH,cAAc,EAAE,cAAc,GAAG,IAAI,CAAA;IAErC;;OAEG;IACH,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IAEhD;;OAEG;IACH,WAAW,EAAE,MAAM,CAAA;IAEnB;;;OAGG;IACH,qBAAqB,EAAE,qBAAqB,GAAG,IAAI,CAAA;IAEnD;;OAEG;IACH,cAAc,EAAE,iBAAiB,GAAG,IAAI,CAAA;CACxC;AAED,MAAM,WAAW,iBAAiB;IACjC,gDAA8C;IAC9C,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;IAC5B,8CAA8C;IAC9C,UAAU,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,qBAAqB;IACrC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC/B;AAkBD;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,qBAAqB,CAExD;AAwND;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,MAAM,CAuO1E;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,GAAE;IAClD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;CACf,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAaxC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,GAAE;IACjD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;CACf,GAAG,OAAO,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACzC,gBAAgB,EAAE,qBAAqB,EAAE,CAAA;CACzC,CAAC,CAsCD;AAGD,eAAe,cAAc,CAAA"}
@@ -0,0 +1,10 @@
1
+ import type { DevflareConfig } from '../config';
2
+ export interface WorkerSurfacePaths {
3
+ fetch: string | null;
4
+ queue: string | null;
5
+ scheduled: string | null;
6
+ email: string | null;
7
+ }
8
+ export declare function resolveWorkerSurfacePaths(cwd: string, config: DevflareConfig): Promise<WorkerSurfacePaths>;
9
+ export declare function prepareComposedWorkerEntrypoint(cwd: string, config: DevflareConfig, environment?: string): Promise<string | null>;
10
+ //# sourceMappingURL=composed-worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composed-worker.d.ts","sourceRoot":"","sources":["../../src/worker-entry/composed-worker.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AA8B/C,MAAM,WAAW,kBAAkB;IAClC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACpB;AA8CD,wBAAsB,yBAAyB,CAC9C,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,cAAc,GACpB,OAAO,CAAC,kBAAkB,CAAC,CAO7B;AAiHD,wBAAsB,+BAA+B,CACpD,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,cAAc,EACtB,WAAW,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA8BxB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devflare",
3
- "version": "1.0.0-next.6",
3
+ "version": "1.0.0-next.7",
4
4
  "description": "Devflare is a developer-first toolkit for Cloudflare Workers that sits on top of Miniflare and Wrangler-compatible config",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",