-
Notifications
You must be signed in to change notification settings - Fork 27
Expand file tree
/
Copy pathvite-plugin-worker-comunica.ts
More file actions
117 lines (108 loc) · 3.61 KB
/
Copy pathvite-plugin-worker-comunica.ts
File metadata and controls
117 lines (108 loc) · 3.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import { build, type Plugin as EsbuildPlugin } from "esbuild";
import type { Plugin } from "vite";
import path from "node:path";
import { fileURLToPath } from "node:url";
const VIRTUAL_ID = "\0virtual:comunica-prebundled";
const DIAG_STUB_ID = "\0virtual:node-diagnostics-channel-stub";
const COMUNICA_PKG = "@comunica/query-sparql-rdfjs";
/**
* esbuild plugin that stubs `node:diagnostics_channel` for the browser.
*
* lru-cache (used by Comunica) imports this Node.js built-in. Vite's default
* browser-external Proxy stub returns undefined for all property accesses, so
* `(0, L.channel)("lru-cache:metrics")` throws at module initialisation time.
* This stub provides no-op implementations that satisfy lru-cache's usage.
*/
export const diagnosticsChannelStub: EsbuildPlugin = {
name: "stub-node-diagnostics-channel",
setup(build) {
build.onResolve({ filter: /^node:diagnostics_channel$/ }, () => ({
path: "node-diagnostics-channel-stub",
namespace: "diagnostics-channel-stub",
}));
build.onLoad({ filter: /.*/, namespace: "diagnostics-channel-stub" }, () => ({
contents: `
const noop = () => {};
const noopChannel = () => ({
hasSubscribers: false,
subscribe: noop,
unsubscribe: noop,
publish: () => false,
bindStore: noop,
unbindStore: noop,
});
module.exports = {
channel: noopChannel,
tracingChannel: noopChannel,
hasSubscribers: () => false,
subscribe: noop,
unsubscribe: noop,
};
`,
loader: "js",
}));
},
};
const DIAG_CHANNEL_ESM_STUB = `
const noop = () => {};
const noopChannel = () => ({
hasSubscribers: false,
subscribe: noop,
unsubscribe: noop,
publish: () => false,
bindStore: noop,
unbindStore: noop,
});
export const channel = noopChannel;
export const tracingChannel = noopChannel;
export const hasSubscribers = () => false;
export const subscribe = noop;
export const unsubscribe = noop;
export default { channel: noopChannel, tracingChannel: noopChannel, hasSubscribers: () => false, subscribe: noop, unsubscribe: noop };
`;
/**
* Pre-bundles Comunica with esbuild when building the web worker.
*
* Vite's Rollup worker bundler generates broken require_libXXX stubs for
* Comunica's circular CJS deps. esbuild handles them correctly (same as
* InProcessWorker tests). This plugin intercepts the Comunica import inside
* the worker bundle and substitutes an esbuild-compiled flat ESM module.
*/
export function workerComunicaPlugin(): Plugin {
let prebundled: string | null = null;
const __dirname = path.dirname(fileURLToPath(import.meta.url));
return {
name: "worker-comunica-prebundle",
async buildStart() {
if (prebundled) return;
const result = await build({
stdin: {
contents: `export { QueryEngine } from "${COMUNICA_PKG}";`,
resolveDir: __dirname,
loader: "ts",
},
bundle: true,
platform: "browser",
format: "esm",
target: "es2020",
write: false,
logLevel: "silent",
define: {
global: "globalThis",
},
plugins: [diagnosticsChannelStub],
});
prebundled = result.outputFiles[0].text;
},
enforce: "pre" as const,
resolveId(id: string) {
if (id === COMUNICA_PKG) return VIRTUAL_ID;
if (id === "node:diagnostics_channel" || id === "diagnostics_channel")
return DIAG_STUB_ID;
},
load(id: string) {
if (id === VIRTUAL_ID) return prebundled ?? "";
if (id === DIAG_STUB_ID) return DIAG_CHANNEL_ESM_STUB;
},
};
}