Skip to content
This repository was archived by the owner on Mar 13, 2025. It is now read-only.

Commit 0e73c59

Browse files
committed
Allow __STATIC_CONTENT_MANIFEST to be imported from any directory
Previously, `import manifest from "__STATIC_CONTENT_MANIFEST"` was only allowed in the "root" directory of the modules virtual file-system. This change adds stub modules for each additional module in each subdirectory, that re-export the module. This allows the manifest to be imported in any directory.
1 parent 195a900 commit 0e73c59

File tree

3 files changed

+85
-6
lines changed

3 files changed

+85
-6
lines changed

packages/miniflare/src/plugins/core/index.ts

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import assert from "assert";
22
import { readFileSync } from "fs";
33
import fs from "fs/promises";
4+
import path from "path";
45
import tls from "tls";
56
import { TextEncoder } from "util";
67
import { bold } from "kleur/colors";
@@ -374,10 +375,7 @@ export const CORE_PLUGIN: Plugin<
374375
sourceMapRegistry,
375376
}) {
376377
// Define regular user worker
377-
const additionalModuleNames = additionalModules.map(({ name }) => {
378-
assert(name !== undefined);
379-
return name;
380-
});
378+
const additionalModuleNames = additionalModules.map(({ name }) => name);
381379
const workerScript = getWorkerScript(
382380
sourceMapRegistry,
383381
options,
@@ -386,7 +384,32 @@ export const CORE_PLUGIN: Plugin<
386384
);
387385
// Add additional modules (e.g. "__STATIC_CONTENT_MANIFEST") if any
388386
if ("modules" in workerScript) {
389-
workerScript.modules.push(...additionalModules);
387+
const subDirs = new Set(
388+
workerScript.modules.map(({ name }) => path.posix.dirname(name))
389+
);
390+
// Ignore `.` as it's not a subdirectory, and we don't want to register
391+
// additional modules in the root twice.
392+
subDirs.delete(".");
393+
394+
for (const module of additionalModules) {
395+
workerScript.modules.push(module);
396+
// In addition to adding the module, we add stub modules in each
397+
// subdirectory re-exporting each additional module. These allow
398+
// additional modules to be imported in every directory.
399+
for (const subDir of subDirs) {
400+
const relativePath = path.posix.relative(subDir, module.name);
401+
const relativePathString = JSON.stringify(relativePath);
402+
workerScript.modules.push({
403+
name: path.posix.join(subDir, module.name),
404+
// TODO(someday): if we ever have additional modules without
405+
// default exports, this may be a problem. For now, our only
406+
// additional module is `__STATIC_CONTENT_MANIFEST` so it's fine.
407+
// If needed, we could look for instances of `export default` or
408+
// `as default` in the module's code as a heuristic.
409+
esModule: `export * from ${relativePathString}; export { default } from ${relativePathString};`,
410+
});
411+
}
412+
}
390413
}
391414

392415
const name = getUserServiceName(options.name);

packages/miniflare/src/runtime/config/workerd.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export type Worker_DurableObjectStorage =
6767
| { localDisk?: string };
6868

6969
export type Worker_Module = {
70-
name?: string;
70+
name: string;
7171
} & (
7272
| { esModule?: string }
7373
| { commonJsModule?: string }

packages/miniflare/test/plugins/kv/sites.spec.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,62 @@ test("gets assets with module worker", async (t) => {
169169
t.is(await res.text(), "nested");
170170
});
171171

172+
test("can import manifest from any directory", async (t) => {
173+
const tmp = await useTmp(t);
174+
const testPath = path.join(tmp, "test.txt");
175+
await fs.writeFile(testPath, "test", "utf8");
176+
const mf = new Miniflare({
177+
modules: [
178+
{
179+
type: "ESModule",
180+
path: "index.mjs",
181+
contents: `
182+
import root from "__STATIC_CONTENT_MANIFEST";
183+
import a1 from "./a/1.mjs";
184+
import ab2 from "./a/b/2.mjs";
185+
import ab3 from "./a/b/3.mjs";
186+
import abc4 from "./a/b/c/4.mjs";
187+
188+
export default {
189+
async fetch() {
190+
return Response.json({
191+
a1: a1 === root,
192+
ab2: ab2 === root,
193+
ab3: ab3 === root,
194+
abc4: abc4 === root,
195+
});
196+
}
197+
}
198+
`,
199+
},
200+
{
201+
type: "ESModule",
202+
path: "a/1.mjs",
203+
contents: 'export { default } from "__STATIC_CONTENT_MANIFEST";',
204+
},
205+
{
206+
type: "ESModule",
207+
path: "a/b/2.mjs",
208+
contents: 'export { default } from "__STATIC_CONTENT_MANIFEST";',
209+
},
210+
{
211+
type: "ESModule",
212+
path: "a/b/3.mjs",
213+
contents: 'export { default } from "__STATIC_CONTENT_MANIFEST";',
214+
},
215+
{
216+
type: "ESModule",
217+
path: "a/b/c/4.mjs",
218+
contents: 'export { default } from "__STATIC_CONTENT_MANIFEST";',
219+
},
220+
],
221+
sitePath: tmp,
222+
});
223+
t.teardown(() => mf.dispose());
224+
const res = await mf.dispatchFetch("http://localhost:8787/test.txt");
225+
t.deepEqual(await res.json(), { a1: true, ab2: true, ab3: true, abc4: true });
226+
});
227+
172228
test("gets assets with percent-encoded paths", async (t) => {
173229
// https://github.com/cloudflare/miniflare/issues/326
174230
const tmp = await useTmp(t);

0 commit comments

Comments
 (0)