@distilled.cloud/cloudflare-rolldown-plugin 0.1.0
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/README.md +49 -0
- package/dist/plugin.d.ts +9 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +16 -0
- package/dist/plugin.js.map +1 -0
- package/dist/plugins/additional-modules.d.ts +3 -0
- package/dist/plugins/additional-modules.d.ts.map +1 -0
- package/dist/plugins/additional-modules.js +75 -0
- package/dist/plugins/additional-modules.js.map +1 -0
- package/dist/plugins/cloudflare-externals.d.ts +3 -0
- package/dist/plugins/cloudflare-externals.d.ts.map +1 -0
- package/dist/plugins/cloudflare-externals.js +23 -0
- package/dist/plugins/cloudflare-externals.js.map +1 -0
- package/dist/plugins/nodejs-compat.d.ts +4 -0
- package/dist/plugins/nodejs-compat.d.ts.map +1 -0
- package/dist/plugins/nodejs-compat.js +125 -0
- package/dist/plugins/nodejs-compat.js.map +1 -0
- package/dist/plugins/options.d.ts +6 -0
- package/dist/plugins/options.d.ts.map +1 -0
- package/dist/plugins/options.js +47 -0
- package/dist/plugins/options.js.map +1 -0
- package/dist/plugins/wasm-init.d.ts +3 -0
- package/dist/plugins/wasm-init.d.ts.map +1 -0
- package/dist/plugins/wasm-init.js +18 -0
- package/dist/plugins/wasm-init.js.map +1 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +8 -0
- package/dist/utils.js.map +1 -0
- package/package.json +63 -0
- package/src/plugin.ts +25 -0
- package/src/plugins/additional-modules.ts +82 -0
- package/src/plugins/cloudflare-externals.ts +26 -0
- package/src/plugins/nodejs-compat.ts +141 -0
- package/src/plugins/options.ts +51 -0
- package/src/plugins/wasm-init.ts +20 -0
- package/src/utils.ts +9 -0
package/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# `@distilled.cloud/cloudflare-rolldown-plugin`
|
|
2
|
+
|
|
3
|
+
Rolldown plugin for Cloudflare Workers.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun add -d @distilled.cloud/cloudflare-rolldown-plugin rolldown
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { rolldown } from "rolldown";
|
|
15
|
+
import cloudflare from "@distilled.cloud/cloudflare-rolldown-plugin";
|
|
16
|
+
|
|
17
|
+
const bundle = await rolldown({
|
|
18
|
+
input: "./src/index.ts",
|
|
19
|
+
plugins: [
|
|
20
|
+
cloudflare({
|
|
21
|
+
compatibilityDate: "2026-04-01",
|
|
22
|
+
compatibilityFlags: ["nodejs_compat"],
|
|
23
|
+
}),
|
|
24
|
+
],
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
await bundle.write({
|
|
28
|
+
file: "./dist/index.js",
|
|
29
|
+
format: "esm",
|
|
30
|
+
sourcemap: true,
|
|
31
|
+
});
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## What It Does
|
|
35
|
+
|
|
36
|
+
- Applies Cloudflare-friendly Rolldown defaults for resolution and output targeting.
|
|
37
|
+
- Treats supported `cloudflare:*` imports as external.
|
|
38
|
+
- Enables Node.js compatibility shims when `nodejs_compat` is set.
|
|
39
|
+
- Supports Cloudflare-style additional modules for `.wasm`, `.bin`, `.txt`, `.html`, and `.sql`.
|
|
40
|
+
- Supports `.wasm?init` imports.
|
|
41
|
+
|
|
42
|
+
## Options
|
|
43
|
+
|
|
44
|
+
- `compatibilityDate?: string`
|
|
45
|
+
- `compatibilityFlags?: string[]`
|
|
46
|
+
|
|
47
|
+
## License
|
|
48
|
+
|
|
49
|
+
MIT
|
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { RolldownPluginOption } from "rolldown";
|
|
2
|
+
export interface CloudflarePluginOptions {
|
|
3
|
+
compatibilityDate?: string;
|
|
4
|
+
compatibilityFlags?: Array<string>;
|
|
5
|
+
}
|
|
6
|
+
export type CloudflarePlugin = (options?: CloudflarePluginOptions) => RolldownPluginOption;
|
|
7
|
+
declare const cloudflare: CloudflarePlugin;
|
|
8
|
+
export default cloudflare;
|
|
9
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAOrD,MAAM,WAAW,uBAAuB;IACtC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kBAAkB,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CACpC;AAED,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,CAAC,EAAE,uBAAuB,KAAK,oBAAoB,CAAC;AAE3F,QAAA,MAAM,UAAU,EAAE,gBAQjB,CAAC;AAEF,eAAe,UAAU,CAAC"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { makeAdditionalModulesPlugin } from "./plugins/additional-modules.js";
|
|
2
|
+
import { cloudflareExternalsPlugin } from "./plugins/cloudflare-externals.js";
|
|
3
|
+
import { makeNodejsCompatPlugin } from "./plugins/nodejs-compat.js";
|
|
4
|
+
import { makeOptionsPlugin } from "./plugins/options.js";
|
|
5
|
+
import { wasmInitPlugin } from "./plugins/wasm-init.js";
|
|
6
|
+
const cloudflare = async (options = {}) => {
|
|
7
|
+
return [
|
|
8
|
+
makeOptionsPlugin(options),
|
|
9
|
+
cloudflareExternalsPlugin,
|
|
10
|
+
makeNodejsCompatPlugin(options),
|
|
11
|
+
wasmInitPlugin,
|
|
12
|
+
makeAdditionalModulesPlugin(),
|
|
13
|
+
];
|
|
14
|
+
};
|
|
15
|
+
export default cloudflare;
|
|
16
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,2BAA2B,EAAE,MAAM,iCAAiC,CAAC;AAC9E,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AASxD,MAAM,UAAU,GAAqB,KAAK,EAAE,OAAO,GAAG,EAAE,EAAE,EAAE;IAC1D,OAAO;QACL,iBAAiB,CAAC,OAAO,CAAC;QAC1B,yBAAyB;QACzB,sBAAsB,CAAC,OAAO,CAAC;QAC/B,cAAc;QACd,2BAA2B,EAAE;KAC9B,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,UAAU,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"additional-modules.d.ts","sourceRoot":"","sources":["../../src/plugins/additional-modules.ts"],"names":[],"mappings":"AACA,OAAO,EAAuB,KAAK,MAAM,EAAE,MAAM,UAAU,CAAC;AAa5D,wBAAgB,2BAA2B,IAAI,MAAM,CA+DpD"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { RolldownMagicString } from "rolldown";
|
|
3
|
+
import { sanitizePath } from "../utils.js";
|
|
4
|
+
const MODULE_RULES = [
|
|
5
|
+
{ type: "CompiledWasm", pattern: /\.wasm(\?module)?$/ },
|
|
6
|
+
{ type: "Data", pattern: /\.bin$/ },
|
|
7
|
+
{ type: "Text", pattern: /\.(txt|html|sql)$/ },
|
|
8
|
+
];
|
|
9
|
+
const MODULE_REFERENCE_PATTERN = `__CLOUDFLARE_MODULE__(${MODULE_RULES.map((rule) => rule.type).join("|")})__(.*?)__CLOUDFLARE_MODULE__`;
|
|
10
|
+
const MODULE_REFERENCE_REGEX = new RegExp(MODULE_REFERENCE_PATTERN);
|
|
11
|
+
const MODULE_REFERENCE_GLOBAL_REGEX = new RegExp(MODULE_REFERENCE_PATTERN, "g");
|
|
12
|
+
export function makeAdditionalModulesPlugin() {
|
|
13
|
+
const additionalModulePaths = new Set();
|
|
14
|
+
return {
|
|
15
|
+
name: "rolldown-plugin-cloudflare:additional-modules",
|
|
16
|
+
// TODO: these are Vite options, not Rolldown
|
|
17
|
+
// enforce: "pre",
|
|
18
|
+
// applyToEnvironment(environment) {
|
|
19
|
+
// return environment.name === "development";
|
|
20
|
+
// },
|
|
21
|
+
// hotUpdate(options) {
|
|
22
|
+
// if (additionalModulePaths.has(options.file)) {
|
|
23
|
+
// void options.server.restart();
|
|
24
|
+
// return [];
|
|
25
|
+
// }
|
|
26
|
+
// },
|
|
27
|
+
resolveId: {
|
|
28
|
+
filter: { id: MODULE_RULES.map((rule) => rule.pattern) },
|
|
29
|
+
async handler(source, importer, options) {
|
|
30
|
+
const resolved = await this.resolve(source, importer, options);
|
|
31
|
+
if (!resolved) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const rule = MODULE_RULES.find((rule) => rule.pattern.test(resolved.id));
|
|
35
|
+
if (!rule) {
|
|
36
|
+
return resolved;
|
|
37
|
+
}
|
|
38
|
+
const filePath = sanitizePath(resolved.id);
|
|
39
|
+
additionalModulePaths.add(filePath);
|
|
40
|
+
return {
|
|
41
|
+
external: true,
|
|
42
|
+
id: moduleReferenceId(rule.type, filePath),
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
renderChunk: {
|
|
47
|
+
filter: { code: { include: MODULE_REFERENCE_REGEX } },
|
|
48
|
+
async handler(code, chunk) {
|
|
49
|
+
const matches = code.matchAll(MODULE_REFERENCE_GLOBAL_REGEX);
|
|
50
|
+
let magicString;
|
|
51
|
+
for (const match of matches) {
|
|
52
|
+
magicString ??= new RolldownMagicString(code);
|
|
53
|
+
const [full, , id] = match;
|
|
54
|
+
const source = await this.fs.readFile(id);
|
|
55
|
+
const referenceId = this.emitFile({
|
|
56
|
+
type: "asset",
|
|
57
|
+
name: path.basename(id),
|
|
58
|
+
source,
|
|
59
|
+
});
|
|
60
|
+
const fileName = this.getFileName(referenceId);
|
|
61
|
+
const relativePath = path.relative(path.dirname(chunk.fileName), fileName);
|
|
62
|
+
const importPath = relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
|
|
63
|
+
magicString.update(match.index, match.index + full.length, importPath);
|
|
64
|
+
}
|
|
65
|
+
if (magicString) {
|
|
66
|
+
return magicString;
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function moduleReferenceId(type, id) {
|
|
73
|
+
return `__CLOUDFLARE_MODULE__${type}__${id}__CLOUDFLARE_MODULE__`;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=additional-modules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"additional-modules.js","sourceRoot":"","sources":["../../src/plugins/additional-modules.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloudflare-externals.d.ts","sourceRoot":"","sources":["../../src/plugins/cloudflare-externals.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAUvC,eAAO,MAAM,yBAAyB,EAAE,MAevC,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const CLOUDFLARE_BUILTIN_MODULES = [
|
|
2
|
+
"cloudflare:email",
|
|
3
|
+
"cloudflare:node",
|
|
4
|
+
"cloudflare:sockets",
|
|
5
|
+
"cloudflare:workers",
|
|
6
|
+
"cloudflare:workflows",
|
|
7
|
+
];
|
|
8
|
+
export const cloudflareExternalsPlugin = {
|
|
9
|
+
name: "rolldown-plugin-cloudflare:cloudflare-externals",
|
|
10
|
+
resolveId: {
|
|
11
|
+
filter: { id: /^cloudflare:/ },
|
|
12
|
+
handler(id) {
|
|
13
|
+
if (!CLOUDFLARE_BUILTIN_MODULES.includes(id)) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
id,
|
|
18
|
+
external: true,
|
|
19
|
+
};
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=cloudflare-externals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloudflare-externals.js","sourceRoot":"","sources":["../../src/plugins/cloudflare-externals.ts"],"names":[],"mappings":"AAEA,MAAM,0BAA0B,GAAG;IACjC,kBAAkB;IAClB,iBAAiB;IACjB,oBAAoB;IACpB,oBAAoB;IACpB,sBAAsB;CACvB,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAW;IAC/C,IAAI,EAAE,iDAAiD;IACvD,SAAS,EAAE;QACT,MAAM,EAAE,EAAE,EAAE,EAAE,cAAc,EAAE;QAC9B,OAAO,CAAC,EAAE;YACR,IAAI,CAAC,0BAA0B,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;gBAC7C,OAAO;YACT,CAAC;YAED,OAAO;gBACL,EAAE;gBACF,QAAQ,EAAE,IAAI;aACf,CAAC;QACJ,CAAC;KACF;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nodejs-compat.d.ts","sourceRoot":"","sources":["../../src/plugins/nodejs-compat.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAU,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAG7D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAM5D,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,uBAAuB,GAAG,oBAAoB,CAK7F"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { getCloudflarePreset, nonPrefixedNodeModules } from "@cloudflare/unenv-preset";
|
|
2
|
+
import assert from "node:assert";
|
|
3
|
+
import { esmExternalRequirePlugin } from "rolldown/plugins";
|
|
4
|
+
import { defineEnv } from "unenv";
|
|
5
|
+
import { hasNodejsCompat } from "../utils.js";
|
|
6
|
+
const NODE_BUILTIN_MODULES_REGEXP = new RegExp(`^(${nonPrefixedNodeModules.join("|")}|node:.+)$`);
|
|
7
|
+
const VIRTUAL_MODULE_ID_REGEXP = /^virtual:nodejs-global-inject\/.+$/;
|
|
8
|
+
export function makeNodejsCompatPlugin(options) {
|
|
9
|
+
if (hasNodejsCompat(options.compatibilityFlags)) {
|
|
10
|
+
return makeUnenvPlugin(options);
|
|
11
|
+
}
|
|
12
|
+
return makeNodeJsImportWarningPlugin();
|
|
13
|
+
}
|
|
14
|
+
function makeUnenvPlugin(options) {
|
|
15
|
+
const { alias, inject, external, polyfill } = defineEnv({
|
|
16
|
+
presets: [
|
|
17
|
+
getCloudflarePreset({
|
|
18
|
+
compatibilityDate: options.compatibilityDate,
|
|
19
|
+
compatibilityFlags: options.compatibilityFlags,
|
|
20
|
+
}),
|
|
21
|
+
],
|
|
22
|
+
}).env;
|
|
23
|
+
const injectVirtualModules = makeInjectVirtualModules(inject);
|
|
24
|
+
return [
|
|
25
|
+
esmExternalRequirePlugin({
|
|
26
|
+
external: [...external],
|
|
27
|
+
skipDuplicateCheck: true,
|
|
28
|
+
}),
|
|
29
|
+
{
|
|
30
|
+
name: "rolldown-plugin-cloudflare:nodejs-compat:injects",
|
|
31
|
+
resolveId: {
|
|
32
|
+
filter: { id: VIRTUAL_MODULE_ID_REGEXP },
|
|
33
|
+
handler(id) {
|
|
34
|
+
if (injectVirtualModules.has(id)) {
|
|
35
|
+
return { id };
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
load: {
|
|
40
|
+
filter: { id: VIRTUAL_MODULE_ID_REGEXP },
|
|
41
|
+
handler(id) {
|
|
42
|
+
return injectVirtualModules.get(id);
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: "rolldown-plugin-cloudflare:nodejs-compat",
|
|
48
|
+
resolveId: {
|
|
49
|
+
filter: { id: NODE_BUILTIN_MODULES_REGEXP },
|
|
50
|
+
handler(source, importer, options) {
|
|
51
|
+
const aliased = alias[source];
|
|
52
|
+
if (!aliased) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (external.includes(aliased)) {
|
|
56
|
+
return {
|
|
57
|
+
id: aliased,
|
|
58
|
+
external: true,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return this.resolve(aliased, importer, options);
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
transform(code, id) {
|
|
65
|
+
const info = this.getModuleInfo(id);
|
|
66
|
+
if (!info?.isEntry) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
return [
|
|
70
|
+
...polyfill.map((module) => `import "${module}";`),
|
|
71
|
+
...Array.from(injectVirtualModules.keys()).map((module) => `import "${module}";`),
|
|
72
|
+
code,
|
|
73
|
+
].join("\n");
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
];
|
|
77
|
+
}
|
|
78
|
+
function makeNodeJsImportWarningPlugin() {
|
|
79
|
+
const imports = new Map();
|
|
80
|
+
return {
|
|
81
|
+
name: "rolldown-plugin-cloudflare:nodejs-compat:import-warnings",
|
|
82
|
+
resolveId: {
|
|
83
|
+
filter: { id: NODE_BUILTIN_MODULES_REGEXP },
|
|
84
|
+
async handler(id, importer, options) {
|
|
85
|
+
const resolved = await this.resolve(id, importer, options);
|
|
86
|
+
if (!resolved) {
|
|
87
|
+
if (importer) {
|
|
88
|
+
if (!imports.has(id)) {
|
|
89
|
+
imports.set(id, new Set());
|
|
90
|
+
}
|
|
91
|
+
imports.get(id)?.add(importer);
|
|
92
|
+
}
|
|
93
|
+
return { id, external: true };
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
buildStart() {
|
|
98
|
+
imports.clear();
|
|
99
|
+
},
|
|
100
|
+
buildEnd() {
|
|
101
|
+
if (imports.size > 0) {
|
|
102
|
+
for (const [id, importers] of imports.entries()) {
|
|
103
|
+
this.warn([
|
|
104
|
+
`Node.js built-in module "${id}" was imported without \`nodejs_compat\`. Imported from:`,
|
|
105
|
+
...Array.from(importers).map((importer) => `- ${importer}`),
|
|
106
|
+
].join("\n"));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function makeInjectVirtualModules(inject) {
|
|
113
|
+
const virtualModules = new Map();
|
|
114
|
+
for (const [injectedName, moduleSpecifier] of Object.entries(inject)) {
|
|
115
|
+
// The type from unenv is string | string[], but the Cloudflare preset only uses string.
|
|
116
|
+
// This indicates a default export that we set on globalThis.
|
|
117
|
+
assert(typeof moduleSpecifier === "string", `expected moduleSpecifier to be a string`);
|
|
118
|
+
virtualModules.set(injectVirtualModuleId(injectedName), `import virtualModule from "${moduleSpecifier}"; globalThis.${injectedName} = virtualModule;`);
|
|
119
|
+
}
|
|
120
|
+
return virtualModules;
|
|
121
|
+
}
|
|
122
|
+
function injectVirtualModuleId(module) {
|
|
123
|
+
return `virtual:nodejs-global-inject/${module}`;
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=nodejs-compat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nodejs-compat.js","sourceRoot":"","sources":["../../src/plugins/nodejs-compat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AACvF,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,2BAA2B,GAAG,IAAI,MAAM,CAAC,KAAK,sBAAsB,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;AAClG,MAAM,wBAAwB,GAAG,oCAAoC,CAAC;AAEtE,MAAM,UAAU,sBAAsB,CAAC,OAAgC;IACrE,IAAI,eAAe,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE,CAAC;QAChD,OAAO,eAAe,CAAC,OAAO,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,6BAA6B,EAAE,CAAC;AACzC,CAAC;AAED,SAAS,eAAe,CAAC,OAAgC;IACvD,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAC;QACtD,OAAO,EAAE;YACP,mBAAmB,CAAC;gBAClB,iBAAiB,EAAE,OAAO,CAAC,iBAAiB;gBAC5C,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;aAC/C,CAAC;SACH;KACF,CAAC,CAAC,GAAG,CAAC;IAEP,MAAM,oBAAoB,GAAG,wBAAwB,CAAC,MAAM,CAAC,CAAC;IAE9D,OAAO;QACL,wBAAwB,CAAC;YACvB,QAAQ,EAAE,CAAC,GAAG,QAAQ,CAAC;YACvB,kBAAkB,EAAE,IAAI;SACzB,CAAC;QACF;YACE,IAAI,EAAE,kDAAkD;YACxD,SAAS,EAAE;gBACT,MAAM,EAAE,EAAE,EAAE,EAAE,wBAAwB,EAAE;gBACxC,OAAO,CAAC,EAAE;oBACR,IAAI,oBAAoB,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;wBACjC,OAAO,EAAE,EAAE,EAAE,CAAC;oBAChB,CAAC;gBACH,CAAC;aACF;YACD,IAAI,EAAE;gBACJ,MAAM,EAAE,EAAE,EAAE,EAAE,wBAAwB,EAAE;gBACxC,OAAO,CAAC,EAAE;oBACR,OAAO,oBAAoB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACtC,CAAC;aACF;SACF;QACD;YACE,IAAI,EAAE,0CAA0C;YAChD,SAAS,EAAE;gBACT,MAAM,EAAE,EAAE,EAAE,EAAE,2BAA2B,EAAE;gBAC3C,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO;oBAC/B,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;oBAC9B,IAAI,CAAC,OAAO,EAAE,CAAC;wBACb,OAAO;oBACT,CAAC;oBACD,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;wBAC/B,OAAO;4BACL,EAAE,EAAE,OAAO;4BACX,QAAQ,EAAE,IAAI;yBACf,CAAC;oBACJ,CAAC;oBACD,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAClD,CAAC;aACF;YACD,SAAS,CAAC,IAAI,EAAE,EAAE;gBAChB,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;gBACpC,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC;oBACnB,OAAO;gBACT,CAAC;gBACD,OAAO;oBACL,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,WAAW,MAAM,IAAI,CAAC;oBAClD,GAAG,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,WAAW,MAAM,IAAI,CAAC;oBACjF,IAAI;iBACL,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACf,CAAC;SACe;KACnB,CAAC;AACJ,CAAC;AAED,SAAS,6BAA6B;IACpC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC/C,OAAO;QACL,IAAI,EAAE,0DAA0D;QAChE,SAAS,EAAE;YACT,MAAM,EAAE,EAAE,EAAE,EAAE,2BAA2B,EAAE;YAC3C,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO;gBACjC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAC3D,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACd,IAAI,QAAQ,EAAE,CAAC;wBACb,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;4BACrB,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;wBAC7B,CAAC;wBACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;oBACjC,CAAC;oBACD,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;gBAChC,CAAC;YACH,CAAC;SACF;QACD,UAAU;YACR,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC;QACD,QAAQ;YACN,IAAI,OAAO,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;gBACrB,KAAK,MAAM,CAAC,EAAE,EAAE,SAAS,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;oBAChD,IAAI,CAAC,IAAI,CACP;wBACE,4BAA4B,EAAE,0DAA0D;wBACxF,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,KAAK,QAAQ,EAAE,CAAC;qBAC5D,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,wBAAwB,CAC/B,MAAgE;IAEhE,MAAM,cAAc,GAAG,IAAI,GAAG,EAAkB,CAAC;IACjD,KAAK,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACrE,wFAAwF;QACxF,6DAA6D;QAC7D,MAAM,CAAC,OAAO,eAAe,KAAK,QAAQ,EAAE,yCAAyC,CAAC,CAAC;QACvF,cAAc,CAAC,GAAG,CAChB,qBAAqB,CAAC,YAAY,CAAC,EACnC,8BAA8B,eAAe,iBAAiB,YAAY,mBAAmB,CAC9F,CAAC;IACJ,CAAC;IACD,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,SAAS,qBAAqB,CAAC,MAAc;IAC3C,OAAO,gCAAgC,MAAM,EAAW,CAAC;AAC3D,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CloudflarePluginOptions } from "../plugin.js";
|
|
2
|
+
export declare function makeOptionsPlugin(pluginOptions: CloudflarePluginOptions): {
|
|
3
|
+
name: string;
|
|
4
|
+
options(this: import("rolldown").MinimalPluginContext, options: import("rolldown").InputOptions): import("rolldown").InputOptions;
|
|
5
|
+
};
|
|
6
|
+
//# sourceMappingURL=options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/plugins/options.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAkB5D,wBAAgB,iBAAiB,CAAC,aAAa,EAAE,uBAAuB;;;EA+BvE"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { hasNodejsCompat } from "../utils.js";
|
|
2
|
+
const DEFAULT_RESOLVE_CONDITION_NAMES = ["workerd", "worker", "module", "browser", "production"];
|
|
3
|
+
const DEFAULT_RESOLVE_EXTENSIONS = [
|
|
4
|
+
".mjs",
|
|
5
|
+
".js",
|
|
6
|
+
".mts",
|
|
7
|
+
".ts",
|
|
8
|
+
".jsx",
|
|
9
|
+
".tsx",
|
|
10
|
+
".json",
|
|
11
|
+
".cjs",
|
|
12
|
+
".cts",
|
|
13
|
+
".ctx",
|
|
14
|
+
];
|
|
15
|
+
export function makeOptionsPlugin(pluginOptions) {
|
|
16
|
+
return {
|
|
17
|
+
name: "rolldown-plugin-cloudflare:options",
|
|
18
|
+
options(options) {
|
|
19
|
+
options.platform ??= "neutral";
|
|
20
|
+
options.resolve ??= {};
|
|
21
|
+
options.resolve.conditionNames ??= DEFAULT_RESOLVE_CONDITION_NAMES;
|
|
22
|
+
options.resolve.extensions ??= DEFAULT_RESOLVE_EXTENSIONS;
|
|
23
|
+
options.transform ??= {};
|
|
24
|
+
options.transform.target ??= "es2024";
|
|
25
|
+
options.transform.define ??= {};
|
|
26
|
+
Object.assign(options.transform.define, {
|
|
27
|
+
"process.env.NODE_ENV": '"production"',
|
|
28
|
+
"global.process.env.NODE_ENV": '"production"',
|
|
29
|
+
"globalThis.process.env.NODE_ENV": '"production"',
|
|
30
|
+
...(hasNodejsCompat(pluginOptions.compatibilityFlags)
|
|
31
|
+
? {}
|
|
32
|
+
: {
|
|
33
|
+
"process.env": "{}",
|
|
34
|
+
"global.process.env": "{}",
|
|
35
|
+
"globalThis.process.env": "{}",
|
|
36
|
+
}),
|
|
37
|
+
...(pluginOptions.compatibilityDate && pluginOptions.compatibilityDate >= "2022-03-21"
|
|
38
|
+
? {
|
|
39
|
+
"navigator.userAgent": '"Cloudflare-Workers"',
|
|
40
|
+
}
|
|
41
|
+
: {}),
|
|
42
|
+
});
|
|
43
|
+
return options;
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../src/plugins/options.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,+BAA+B,GAAG,CAAC,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;AAEjG,MAAM,0BAA0B,GAAG;IACjC,MAAM;IACN,KAAK;IACL,MAAM;IACN,KAAK;IACL,MAAM;IACN,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,MAAM;CACP,CAAC;AAEF,MAAM,UAAU,iBAAiB,CAAC,aAAsC;IACtE,OAAO;QACL,IAAI,EAAE,oCAAoC;QAC1C,OAAO,CAAC,OAAO;YACb,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC;YAC/B,OAAO,CAAC,OAAO,KAAK,EAAE,CAAC;YACvB,OAAO,CAAC,OAAO,CAAC,cAAc,KAAK,+BAA+B,CAAC;YACnE,OAAO,CAAC,OAAO,CAAC,UAAU,KAAK,0BAA0B,CAAC;YAC1D,OAAO,CAAC,SAAS,KAAK,EAAE,CAAC;YACzB,OAAO,CAAC,SAAS,CAAC,MAAM,KAAK,QAAQ,CAAC;YACtC,OAAO,CAAC,SAAS,CAAC,MAAM,KAAK,EAAE,CAAC;YAChC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,EAAE;gBACtC,sBAAsB,EAAE,cAAc;gBACtC,6BAA6B,EAAE,cAAc;gBAC7C,iCAAiC,EAAE,cAAc;gBACjD,GAAG,CAAC,eAAe,CAAC,aAAa,CAAC,kBAAkB,CAAC;oBACnD,CAAC,CAAC,EAAE;oBACJ,CAAC,CAAC;wBACE,aAAa,EAAE,IAAI;wBACnB,oBAAoB,EAAE,IAAI;wBAC1B,wBAAwB,EAAE,IAAI;qBAC/B,CAAC;gBACN,GAAG,CAAC,aAAa,CAAC,iBAAiB,IAAI,aAAa,CAAC,iBAAiB,IAAI,YAAY;oBACpF,CAAC,CAAC;wBACE,qBAAqB,EAAE,sBAAsB;qBAC9C;oBACH,CAAC,CAAC,EAAE,CAAC;aACR,CAAC,CAAC;YACH,OAAO,OAAO,CAAC;QACjB,CAAC;KACe,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wasm-init.d.ts","sourceRoot":"","sources":["../../src/plugins/wasm-init.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAKvC,eAAO,MAAM,cAAc,EAAE,MAc5B,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { sanitizePath } from "../utils.js";
|
|
2
|
+
const WASM_INIT_QUERY = /\.wasm\?init$/;
|
|
3
|
+
export const wasmInitPlugin = {
|
|
4
|
+
name: "rolldown-plugin-cloudflare:wasm-init",
|
|
5
|
+
load: {
|
|
6
|
+
filter: { id: WASM_INIT_QUERY },
|
|
7
|
+
handler(id) {
|
|
8
|
+
return [
|
|
9
|
+
`import wasmModule from "${sanitizePath(id)}";`,
|
|
10
|
+
`export default async (imports) => {`,
|
|
11
|
+
` const result = await WebAssembly.instantiate(wasmModule, imports);`,
|
|
12
|
+
` return "instance" in result ? result.instance : result;`,
|
|
13
|
+
`};`,
|
|
14
|
+
].join("\n");
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=wasm-init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wasm-init.js","sourceRoot":"","sources":["../../src/plugins/wasm-init.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,eAAe,GAAG,eAAe,CAAC;AAExC,MAAM,CAAC,MAAM,cAAc,GAAW;IACpC,IAAI,EAAE,sCAAsC;IAC5C,IAAI,EAAE;QACJ,MAAM,EAAE,EAAE,EAAE,EAAE,eAAe,EAAE;QAC/B,OAAO,CAAC,EAAE;YACR,OAAO;gBACL,2BAA2B,YAAY,CAAC,EAAE,CAAC,IAAI;gBAC/C,qCAAqC;gBACrC,sEAAsE;gBACtE,2DAA2D;gBAC3D,IAAI;aACL,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACf,CAAC;KACF;CACF,CAAC"}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAEA,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,eAAe,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,OAAO,CAEtE"}
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
const POSTFIX_REGEX = /[?#].*$/;
|
|
2
|
+
export function sanitizePath(path) {
|
|
3
|
+
return path.replace(POSTFIX_REGEX, "");
|
|
4
|
+
}
|
|
5
|
+
export function hasNodejsCompat(flags) {
|
|
6
|
+
return flags?.some((flag) => flag === "nodejs_compat" || flag === "nodejs_compat_v2") ?? false;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,MAAM,aAAa,GAAG,SAAS,CAAC;AAEhC,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAA6B;IAC3D,OAAO,KAAK,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,eAAe,IAAI,IAAI,KAAK,kBAAkB,CAAC,IAAI,KAAK,CAAC;AACjG,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@distilled.cloud/cloudflare-rolldown-plugin",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Rolldown plugin for Cloudflare Workers.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"cloudflare",
|
|
7
|
+
"rolldown",
|
|
8
|
+
"workers"
|
|
9
|
+
],
|
|
10
|
+
"homepage": "https://github.com/alchemy-run/cloudflare-tools/tree/main/packages/rolldown-plugin-cloudflare#readme",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/alchemy-run/cloudflare-tools/issues"
|
|
13
|
+
},
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"author": {
|
|
16
|
+
"name": "John Royal",
|
|
17
|
+
"email": "john@alchemy.run",
|
|
18
|
+
"url": "https://distilled.cloud"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/alchemy-run/cloudflare-tools.git",
|
|
23
|
+
"directory": "packages/cloudflare-rolldown-plugin"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist",
|
|
27
|
+
"src"
|
|
28
|
+
],
|
|
29
|
+
"type": "module",
|
|
30
|
+
"sideEffects": false,
|
|
31
|
+
"main": "./dist/plugin.js",
|
|
32
|
+
"types": "./dist/plugin.d.ts",
|
|
33
|
+
"exports": {
|
|
34
|
+
".": {
|
|
35
|
+
"bun": "./src/plugin.ts",
|
|
36
|
+
"types": "./dist/plugin.d.ts",
|
|
37
|
+
"import": "./dist/plugin.js"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "tsc",
|
|
45
|
+
"clean": "rm -rf dist tsconfig.tsbuildinfo",
|
|
46
|
+
"test": "vitest run",
|
|
47
|
+
"test:watch": "vitest",
|
|
48
|
+
"typecheck": "tsc --noEmit",
|
|
49
|
+
"prepublishOnly": "bun run clean && bun run build"
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"@cloudflare/unenv-preset": "^2.16.0",
|
|
53
|
+
"unenv": "^2.0.0-rc.24"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@cloudflare/workers-types": "catalog:",
|
|
57
|
+
"miniflare": "^4.20260329.0",
|
|
58
|
+
"vitest": "catalog:"
|
|
59
|
+
},
|
|
60
|
+
"peerDependencies": {
|
|
61
|
+
"rolldown": "^1.0.0-rc.9"
|
|
62
|
+
}
|
|
63
|
+
}
|
package/src/plugin.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { RolldownPluginOption } from "rolldown";
|
|
2
|
+
import { makeAdditionalModulesPlugin } from "./plugins/additional-modules.js";
|
|
3
|
+
import { cloudflareExternalsPlugin } from "./plugins/cloudflare-externals.js";
|
|
4
|
+
import { makeNodejsCompatPlugin } from "./plugins/nodejs-compat.js";
|
|
5
|
+
import { makeOptionsPlugin } from "./plugins/options.js";
|
|
6
|
+
import { wasmInitPlugin } from "./plugins/wasm-init.js";
|
|
7
|
+
|
|
8
|
+
export interface CloudflarePluginOptions {
|
|
9
|
+
compatibilityDate?: string;
|
|
10
|
+
compatibilityFlags?: Array<string>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type CloudflarePlugin = (options?: CloudflarePluginOptions) => RolldownPluginOption;
|
|
14
|
+
|
|
15
|
+
const cloudflare: CloudflarePlugin = async (options = {}) => {
|
|
16
|
+
return [
|
|
17
|
+
makeOptionsPlugin(options),
|
|
18
|
+
cloudflareExternalsPlugin,
|
|
19
|
+
makeNodejsCompatPlugin(options),
|
|
20
|
+
wasmInitPlugin,
|
|
21
|
+
makeAdditionalModulesPlugin(),
|
|
22
|
+
];
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export default cloudflare;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { RolldownMagicString, type Plugin } from "rolldown";
|
|
3
|
+
import { sanitizePath } from "../utils.js";
|
|
4
|
+
|
|
5
|
+
const MODULE_RULES = [
|
|
6
|
+
{ type: "CompiledWasm", pattern: /\.wasm(\?module)?$/ },
|
|
7
|
+
{ type: "Data", pattern: /\.bin$/ },
|
|
8
|
+
{ type: "Text", pattern: /\.(txt|html|sql)$/ },
|
|
9
|
+
] as const;
|
|
10
|
+
|
|
11
|
+
const MODULE_REFERENCE_PATTERN = `__CLOUDFLARE_MODULE__(${MODULE_RULES.map((rule) => rule.type).join("|")})__(.*?)__CLOUDFLARE_MODULE__`;
|
|
12
|
+
const MODULE_REFERENCE_REGEX = new RegExp(MODULE_REFERENCE_PATTERN);
|
|
13
|
+
const MODULE_REFERENCE_GLOBAL_REGEX = new RegExp(MODULE_REFERENCE_PATTERN, "g");
|
|
14
|
+
|
|
15
|
+
export function makeAdditionalModulesPlugin(): Plugin {
|
|
16
|
+
const additionalModulePaths = new Set<string>();
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
name: "rolldown-plugin-cloudflare:additional-modules",
|
|
20
|
+
// TODO: these are Vite options, not Rolldown
|
|
21
|
+
// enforce: "pre",
|
|
22
|
+
// applyToEnvironment(environment) {
|
|
23
|
+
// return environment.name === "development";
|
|
24
|
+
// },
|
|
25
|
+
// hotUpdate(options) {
|
|
26
|
+
// if (additionalModulePaths.has(options.file)) {
|
|
27
|
+
// void options.server.restart();
|
|
28
|
+
// return [];
|
|
29
|
+
// }
|
|
30
|
+
// },
|
|
31
|
+
resolveId: {
|
|
32
|
+
filter: { id: MODULE_RULES.map((rule) => rule.pattern) },
|
|
33
|
+
async handler(source, importer, options) {
|
|
34
|
+
const resolved = await this.resolve(source, importer, options);
|
|
35
|
+
if (!resolved) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const rule = MODULE_RULES.find((rule) => rule.pattern.test(resolved.id));
|
|
40
|
+
if (!rule) {
|
|
41
|
+
return resolved;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const filePath = sanitizePath(resolved.id);
|
|
45
|
+
additionalModulePaths.add(filePath);
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
external: true,
|
|
49
|
+
id: moduleReferenceId(rule.type, filePath),
|
|
50
|
+
};
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
renderChunk: {
|
|
54
|
+
filter: { code: { include: MODULE_REFERENCE_REGEX } },
|
|
55
|
+
async handler(code, chunk) {
|
|
56
|
+
const matches = code.matchAll(MODULE_REFERENCE_GLOBAL_REGEX);
|
|
57
|
+
let magicString: RolldownMagicString | undefined;
|
|
58
|
+
for (const match of matches) {
|
|
59
|
+
magicString ??= new RolldownMagicString(code);
|
|
60
|
+
const [full, , id] = match;
|
|
61
|
+
const source = await this.fs.readFile(id);
|
|
62
|
+
const referenceId = this.emitFile({
|
|
63
|
+
type: "asset",
|
|
64
|
+
name: path.basename(id),
|
|
65
|
+
source,
|
|
66
|
+
});
|
|
67
|
+
const fileName = this.getFileName(referenceId);
|
|
68
|
+
const relativePath = path.relative(path.dirname(chunk.fileName), fileName);
|
|
69
|
+
const importPath = relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
|
|
70
|
+
magicString.update(match.index, match.index + full.length, importPath);
|
|
71
|
+
}
|
|
72
|
+
if (magicString) {
|
|
73
|
+
return magicString;
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function moduleReferenceId(type: "CompiledWasm" | "Data" | "Text", id: string) {
|
|
81
|
+
return `__CLOUDFLARE_MODULE__${type}__${id}__CLOUDFLARE_MODULE__` as const;
|
|
82
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Plugin } from "rolldown";
|
|
2
|
+
|
|
3
|
+
const CLOUDFLARE_BUILTIN_MODULES = [
|
|
4
|
+
"cloudflare:email",
|
|
5
|
+
"cloudflare:node",
|
|
6
|
+
"cloudflare:sockets",
|
|
7
|
+
"cloudflare:workers",
|
|
8
|
+
"cloudflare:workflows",
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
export const cloudflareExternalsPlugin: Plugin = {
|
|
12
|
+
name: "rolldown-plugin-cloudflare:cloudflare-externals",
|
|
13
|
+
resolveId: {
|
|
14
|
+
filter: { id: /^cloudflare:/ },
|
|
15
|
+
handler(id) {
|
|
16
|
+
if (!CLOUDFLARE_BUILTIN_MODULES.includes(id)) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
id,
|
|
22
|
+
external: true,
|
|
23
|
+
};
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
};
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { getCloudflarePreset, nonPrefixedNodeModules } from "@cloudflare/unenv-preset";
|
|
2
|
+
import assert from "node:assert";
|
|
3
|
+
import type { Plugin, RolldownPluginOption } from "rolldown";
|
|
4
|
+
import { esmExternalRequirePlugin } from "rolldown/plugins";
|
|
5
|
+
import { defineEnv } from "unenv";
|
|
6
|
+
import type { CloudflarePluginOptions } from "../plugin.js";
|
|
7
|
+
import { hasNodejsCompat } from "../utils.js";
|
|
8
|
+
|
|
9
|
+
const NODE_BUILTIN_MODULES_REGEXP = new RegExp(`^(${nonPrefixedNodeModules.join("|")}|node:.+)$`);
|
|
10
|
+
const VIRTUAL_MODULE_ID_REGEXP = /^virtual:nodejs-global-inject\/.+$/;
|
|
11
|
+
|
|
12
|
+
export function makeNodejsCompatPlugin(options: CloudflarePluginOptions): RolldownPluginOption {
|
|
13
|
+
if (hasNodejsCompat(options.compatibilityFlags)) {
|
|
14
|
+
return makeUnenvPlugin(options);
|
|
15
|
+
}
|
|
16
|
+
return makeNodeJsImportWarningPlugin();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function makeUnenvPlugin(options: CloudflarePluginOptions): RolldownPluginOption {
|
|
20
|
+
const { alias, inject, external, polyfill } = defineEnv({
|
|
21
|
+
presets: [
|
|
22
|
+
getCloudflarePreset({
|
|
23
|
+
compatibilityDate: options.compatibilityDate,
|
|
24
|
+
compatibilityFlags: options.compatibilityFlags,
|
|
25
|
+
}),
|
|
26
|
+
],
|
|
27
|
+
}).env;
|
|
28
|
+
|
|
29
|
+
const injectVirtualModules = makeInjectVirtualModules(inject);
|
|
30
|
+
|
|
31
|
+
return [
|
|
32
|
+
esmExternalRequirePlugin({
|
|
33
|
+
external: [...external],
|
|
34
|
+
skipDuplicateCheck: true,
|
|
35
|
+
}),
|
|
36
|
+
{
|
|
37
|
+
name: "rolldown-plugin-cloudflare:nodejs-compat:injects",
|
|
38
|
+
resolveId: {
|
|
39
|
+
filter: { id: VIRTUAL_MODULE_ID_REGEXP },
|
|
40
|
+
handler(id) {
|
|
41
|
+
if (injectVirtualModules.has(id)) {
|
|
42
|
+
return { id };
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
load: {
|
|
47
|
+
filter: { id: VIRTUAL_MODULE_ID_REGEXP },
|
|
48
|
+
handler(id) {
|
|
49
|
+
return injectVirtualModules.get(id);
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: "rolldown-plugin-cloudflare:nodejs-compat",
|
|
55
|
+
resolveId: {
|
|
56
|
+
filter: { id: NODE_BUILTIN_MODULES_REGEXP },
|
|
57
|
+
handler(source, importer, options) {
|
|
58
|
+
const aliased = alias[source];
|
|
59
|
+
if (!aliased) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (external.includes(aliased)) {
|
|
63
|
+
return {
|
|
64
|
+
id: aliased,
|
|
65
|
+
external: true,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return this.resolve(aliased, importer, options);
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
transform(code, id) {
|
|
72
|
+
const info = this.getModuleInfo(id);
|
|
73
|
+
if (!info?.isEntry) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
return [
|
|
77
|
+
...polyfill.map((module) => `import "${module}";`),
|
|
78
|
+
...Array.from(injectVirtualModules.keys()).map((module) => `import "${module}";`),
|
|
79
|
+
code,
|
|
80
|
+
].join("\n");
|
|
81
|
+
},
|
|
82
|
+
} satisfies Plugin,
|
|
83
|
+
];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function makeNodeJsImportWarningPlugin(): RolldownPluginOption {
|
|
87
|
+
const imports = new Map<string, Set<string>>();
|
|
88
|
+
return {
|
|
89
|
+
name: "rolldown-plugin-cloudflare:nodejs-compat:import-warnings",
|
|
90
|
+
resolveId: {
|
|
91
|
+
filter: { id: NODE_BUILTIN_MODULES_REGEXP },
|
|
92
|
+
async handler(id, importer, options) {
|
|
93
|
+
const resolved = await this.resolve(id, importer, options);
|
|
94
|
+
if (!resolved) {
|
|
95
|
+
if (importer) {
|
|
96
|
+
if (!imports.has(id)) {
|
|
97
|
+
imports.set(id, new Set());
|
|
98
|
+
}
|
|
99
|
+
imports.get(id)?.add(importer);
|
|
100
|
+
}
|
|
101
|
+
return { id, external: true };
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
buildStart() {
|
|
106
|
+
imports.clear();
|
|
107
|
+
},
|
|
108
|
+
buildEnd() {
|
|
109
|
+
if (imports.size > 0) {
|
|
110
|
+
for (const [id, importers] of imports.entries()) {
|
|
111
|
+
this.warn(
|
|
112
|
+
[
|
|
113
|
+
`Node.js built-in module "${id}" was imported without \`nodejs_compat\`. Imported from:`,
|
|
114
|
+
...Array.from(importers).map((importer) => `- ${importer}`),
|
|
115
|
+
].join("\n"),
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function makeInjectVirtualModules(
|
|
124
|
+
inject: Readonly<Record<string, string | ReadonlyArray<string>>>,
|
|
125
|
+
) {
|
|
126
|
+
const virtualModules = new Map<string, string>();
|
|
127
|
+
for (const [injectedName, moduleSpecifier] of Object.entries(inject)) {
|
|
128
|
+
// The type from unenv is string | string[], but the Cloudflare preset only uses string.
|
|
129
|
+
// This indicates a default export that we set on globalThis.
|
|
130
|
+
assert(typeof moduleSpecifier === "string", `expected moduleSpecifier to be a string`);
|
|
131
|
+
virtualModules.set(
|
|
132
|
+
injectVirtualModuleId(injectedName),
|
|
133
|
+
`import virtualModule from "${moduleSpecifier}"; globalThis.${injectedName} = virtualModule;`,
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
return virtualModules;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function injectVirtualModuleId(module: string) {
|
|
140
|
+
return `virtual:nodejs-global-inject/${module}` as const;
|
|
141
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { Plugin } from "rolldown";
|
|
2
|
+
import type { CloudflarePluginOptions } from "../plugin.js";
|
|
3
|
+
import { hasNodejsCompat } from "../utils.js";
|
|
4
|
+
|
|
5
|
+
const DEFAULT_RESOLVE_CONDITION_NAMES = ["workerd", "worker", "module", "browser", "production"];
|
|
6
|
+
|
|
7
|
+
const DEFAULT_RESOLVE_EXTENSIONS = [
|
|
8
|
+
".mjs",
|
|
9
|
+
".js",
|
|
10
|
+
".mts",
|
|
11
|
+
".ts",
|
|
12
|
+
".jsx",
|
|
13
|
+
".tsx",
|
|
14
|
+
".json",
|
|
15
|
+
".cjs",
|
|
16
|
+
".cts",
|
|
17
|
+
".ctx",
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
export function makeOptionsPlugin(pluginOptions: CloudflarePluginOptions) {
|
|
21
|
+
return {
|
|
22
|
+
name: "rolldown-plugin-cloudflare:options",
|
|
23
|
+
options(options) {
|
|
24
|
+
options.platform ??= "neutral";
|
|
25
|
+
options.resolve ??= {};
|
|
26
|
+
options.resolve.conditionNames ??= DEFAULT_RESOLVE_CONDITION_NAMES;
|
|
27
|
+
options.resolve.extensions ??= DEFAULT_RESOLVE_EXTENSIONS;
|
|
28
|
+
options.transform ??= {};
|
|
29
|
+
options.transform.target ??= "es2024";
|
|
30
|
+
options.transform.define ??= {};
|
|
31
|
+
Object.assign(options.transform.define, {
|
|
32
|
+
"process.env.NODE_ENV": '"production"',
|
|
33
|
+
"global.process.env.NODE_ENV": '"production"',
|
|
34
|
+
"globalThis.process.env.NODE_ENV": '"production"',
|
|
35
|
+
...(hasNodejsCompat(pluginOptions.compatibilityFlags)
|
|
36
|
+
? {}
|
|
37
|
+
: {
|
|
38
|
+
"process.env": "{}",
|
|
39
|
+
"global.process.env": "{}",
|
|
40
|
+
"globalThis.process.env": "{}",
|
|
41
|
+
}),
|
|
42
|
+
...(pluginOptions.compatibilityDate && pluginOptions.compatibilityDate >= "2022-03-21"
|
|
43
|
+
? {
|
|
44
|
+
"navigator.userAgent": '"Cloudflare-Workers"',
|
|
45
|
+
}
|
|
46
|
+
: {}),
|
|
47
|
+
});
|
|
48
|
+
return options;
|
|
49
|
+
},
|
|
50
|
+
} satisfies Plugin;
|
|
51
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Plugin } from "rolldown";
|
|
2
|
+
import { sanitizePath } from "../utils.js";
|
|
3
|
+
|
|
4
|
+
const WASM_INIT_QUERY = /\.wasm\?init$/;
|
|
5
|
+
|
|
6
|
+
export const wasmInitPlugin: Plugin = {
|
|
7
|
+
name: "rolldown-plugin-cloudflare:wasm-init",
|
|
8
|
+
load: {
|
|
9
|
+
filter: { id: WASM_INIT_QUERY },
|
|
10
|
+
handler(id) {
|
|
11
|
+
return [
|
|
12
|
+
`import wasmModule from "${sanitizePath(id)}";`,
|
|
13
|
+
`export default async (imports) => {`,
|
|
14
|
+
` const result = await WebAssembly.instantiate(wasmModule, imports);`,
|
|
15
|
+
` return "instance" in result ? result.instance : result;`,
|
|
16
|
+
`};`,
|
|
17
|
+
].join("\n");
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
};
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
const POSTFIX_REGEX = /[?#].*$/;
|
|
2
|
+
|
|
3
|
+
export function sanitizePath(path: string): string {
|
|
4
|
+
return path.replace(POSTFIX_REGEX, "");
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function hasNodejsCompat(flags?: ReadonlyArray<string>): boolean {
|
|
8
|
+
return flags?.some((flag) => flag === "nodejs_compat" || flag === "nodejs_compat_v2") ?? false;
|
|
9
|
+
}
|