@vp-tw/dirwell 0.0.0-stage → 0.1.0-alpha.1
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/CHANGELOG.md +13 -0
- package/LICENSE +21 -0
- package/README.md +182 -2
- package/THEME_PACKAGE_CONTRACT.md +64 -0
- package/THEMING.md +88 -0
- package/THIRD_PARTY_NOTICES.md +14 -0
- package/dist/bin.d.mts +1 -0
- package/dist/bin.mjs +306 -0
- package/dist/bin.mjs.map +1 -0
- package/dist/bun.d.mts +7 -0
- package/dist/bun.mjs +7 -0
- package/dist/bun.mjs.map +1 -0
- package/dist/config-BJG2Zc3Q.d.mts +34 -0
- package/dist/dev-server-Q7NC1wiB.mjs +132 -0
- package/dist/dev-server-Q7NC1wiB.mjs.map +1 -0
- package/dist/esbuild.d.mts +7 -0
- package/dist/esbuild.mjs +7 -0
- package/dist/esbuild.mjs.map +1 -0
- package/dist/farm.d.mts +7 -0
- package/dist/farm.mjs +7 -0
- package/dist/farm.mjs.map +1 -0
- package/dist/generator-CtX3iHhK.mjs +1783 -0
- package/dist/generator-CtX3iHhK.mjs.map +1 -0
- package/dist/index.d.mts +47 -0
- package/dist/index.mjs +74 -0
- package/dist/index.mjs.map +1 -0
- package/dist/model-CWjYM17j.d.mts +100 -0
- package/dist/rolldown.d.mts +7 -0
- package/dist/rolldown.mjs +7 -0
- package/dist/rolldown.mjs.map +1 -0
- package/dist/rollup.d.mts +7 -0
- package/dist/rollup.mjs +7 -0
- package/dist/rollup.mjs.map +1 -0
- package/dist/rsbuild.d.mts +7 -0
- package/dist/rsbuild.mjs +7 -0
- package/dist/rsbuild.mjs.map +1 -0
- package/dist/rspack.d.mts +7 -0
- package/dist/rspack.mjs +7 -0
- package/dist/rspack.mjs.map +1 -0
- package/dist/theme-components-CXzvdQY-.mjs +8 -0
- package/dist/theme-components-CXzvdQY-.mjs.map +1 -0
- package/dist/theme-components-DW0fv9_C.d.mts +141 -0
- package/dist/theme-components.d.mts +2 -0
- package/dist/theme-components.mjs +2 -0
- package/dist/theme-runtime.js +1128 -0
- package/dist/theme-worker.js +27 -0
- package/dist/unplugin-CKRUCTgW.d.mts +16 -0
- package/dist/unplugin-p6AXhL4F.mjs +421 -0
- package/dist/unplugin-p6AXhL4F.mjs.map +1 -0
- package/dist/unplugin.d.mts +2 -0
- package/dist/unplugin.mjs +2 -0
- package/dist/vite-JBsvRvuW.mjs +282 -0
- package/dist/vite-JBsvRvuW.mjs.map +1 -0
- package/dist/vite.d.mts +12 -0
- package/dist/vite.mjs +2 -0
- package/dist/vscode-icons/NOTICE.txt +16 -0
- package/dist/vscode-icons/default_file.svg +1 -0
- package/dist/vscode-icons/default_folder.svg +1 -0
- package/dist/vscode-icons/file_type_css.svg +1 -0
- package/dist/vscode-icons/file_type_html.svg +1 -0
- package/dist/vscode-icons/file_type_image.svg +1 -0
- package/dist/vscode-icons/file_type_js.svg +1 -0
- package/dist/vscode-icons/file_type_json.svg +1 -0
- package/dist/vscode-icons/file_type_markdown.svg +1 -0
- package/dist/vscode-icons/file_type_pdf2.svg +1 -0
- package/dist/vscode-icons/file_type_shell.svg +1 -0
- package/dist/vscode-icons/file_type_text.svg +1 -0
- package/dist/vscode-icons/file_type_typescript.svg +1 -0
- package/dist/vscode-icons/file_type_yaml.svg +1 -0
- package/dist/vscode-icons/file_type_zip.svg +1 -0
- package/dist/webpack.d.mts +7 -0
- package/dist/webpack.mjs +7 -0
- package/dist/webpack.mjs.map +1 -0
- package/package.json +133 -4
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { compareEntryValues, entryType, fuzzyScore } from "./dirwell.runtime.js";
|
|
2
|
+
|
|
3
|
+
let rows = [];
|
|
4
|
+
|
|
5
|
+
self.addEventListener("message", ({ data }) => {
|
|
6
|
+
if (data.type === "init") {
|
|
7
|
+
rows = data.rows;
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
if (data.type !== "query") return;
|
|
11
|
+
const { generation, query, types, sort } = data;
|
|
12
|
+
const selectedTypes = new Set(types);
|
|
13
|
+
const matches = [];
|
|
14
|
+
for (let index = 0; index < rows.length; index += 1) {
|
|
15
|
+
const row = rows[index];
|
|
16
|
+
if (!selectedTypes.has(entryType(row))) continue;
|
|
17
|
+
const score = fuzzyScore(query, row.search);
|
|
18
|
+
if (query !== "" && score === null) continue;
|
|
19
|
+
matches.push({ index, row, score });
|
|
20
|
+
}
|
|
21
|
+
matches.sort((left, right) => {
|
|
22
|
+
if (query !== "" && left.score !== right.score) return (right.score ?? 0) - (left.score ?? 0);
|
|
23
|
+
return compareEntryValues(left.row, right.row, sort) || left.index - right.index;
|
|
24
|
+
});
|
|
25
|
+
const indices = Uint32Array.from(matches, ({ index }) => index);
|
|
26
|
+
self.postMessage({ generation, indices }, [indices.buffer]);
|
|
27
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { t as DirwellConfig } from "./config-BJG2Zc3Q.mjs";
|
|
2
|
+
import { UnpluginInstance } from "unplugin";
|
|
3
|
+
//#region src/unplugin.d.ts
|
|
4
|
+
/** A directory explorer emitted beneath the host's output root. */
|
|
5
|
+
interface DirwellPluginOptions extends Omit<DirwellConfig, "extends" | "server" | "outDir"> {
|
|
6
|
+
/** Project directory used for config discovery and relative source paths. */
|
|
7
|
+
readonly cwd?: string;
|
|
8
|
+
/** Dedicated relative path inside the host output; defaults to `dirwell`. */
|
|
9
|
+
readonly outputPath?: string;
|
|
10
|
+
}
|
|
11
|
+
type DirwellPluginInput = DirwellPluginOptions | readonly DirwellPluginOptions[] | undefined;
|
|
12
|
+
/** The Vite host retains its server integration; all other hosts share asset generation. */
|
|
13
|
+
declare const unplugin: Pick<UnpluginInstance<DirwellPluginInput, true>, "vite" | "rollup" | "rolldown" | "webpack" | "rspack" | "rsbuild" | "esbuild" | "farm" | "bun">;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { DirwellPluginOptions as n, unplugin as r, DirwellPluginInput as t };
|
|
16
|
+
//# sourceMappingURL=unplugin-CKRUCTgW.d.mts.map
|
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
import { h as validateConfig, i as generateExplorerSkippingPaths, m as resolveGenerateOptions, p as loadDirwellConfig } from "./generator-CtX3iHhK.mjs";
|
|
2
|
+
import { i as isWithin, n as assertSafeMirroredSymlinks, r as canonicalPath, t as dirwellVite } from "./vite-JBsvRvuW.mjs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { lstat, mkdir, mkdtemp, readFile, readdir, realpath, rm, writeFile } from "node:fs/promises";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
import { createUnplugin } from "unplugin";
|
|
7
|
+
import { watch } from "chokidar";
|
|
8
|
+
//#region src/unplugin.ts
|
|
9
|
+
const marker = ".dirwell-plugin-output";
|
|
10
|
+
function outputPath(value = "dirwell") {
|
|
11
|
+
if (!value || path.isAbsolute(value) || value.includes("\\") || value.split("/").some((part) => !part || part === "." || part === "..")) throw new TypeError("Dirwell outputPath must be a dedicated relative path without dot segments");
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
async function watchPaths(source, excluded) {
|
|
15
|
+
const files = [];
|
|
16
|
+
const directories = [];
|
|
17
|
+
async function visit(directory) {
|
|
18
|
+
directories.push(directory);
|
|
19
|
+
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
|
20
|
+
const name = path.join(directory, entry.name);
|
|
21
|
+
if (excluded.some((candidate) => isWithin(candidate, name))) continue;
|
|
22
|
+
if (entry.isDirectory()) await visit(name);
|
|
23
|
+
else files.push(name);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
await visit(source);
|
|
27
|
+
return {
|
|
28
|
+
files,
|
|
29
|
+
directories
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
const core = createUnplugin((options, meta) => {
|
|
33
|
+
const entries = Array.isArray(options) ? options : [options ?? {}];
|
|
34
|
+
if (!entries.length) throw new TypeError("Dirwell options array must not be empty");
|
|
35
|
+
const prefixes = entries.map((entry) => outputPath(entry.outputPath));
|
|
36
|
+
for (let index = 0; index < prefixes.length; index++) for (let other = 0; other < index; other++) if (isWithin(prefixes[index], prefixes[other]) || isWithin(prefixes[other], prefixes[index])) throw new Error("Dirwell options array has overlapping outputPath paths");
|
|
37
|
+
return entries.map((inline, index) => {
|
|
38
|
+
const prefix = prefixes[index];
|
|
39
|
+
if (meta.framework === "vite") return {
|
|
40
|
+
name: `dirwell:${prefix}`,
|
|
41
|
+
vite: dirwellVite({
|
|
42
|
+
...inline,
|
|
43
|
+
outputPath: prefix
|
|
44
|
+
})
|
|
45
|
+
};
|
|
46
|
+
let cwd = path.resolve(inline.cwd ?? process.cwd());
|
|
47
|
+
let hostOutput;
|
|
48
|
+
let config;
|
|
49
|
+
let source;
|
|
50
|
+
let context;
|
|
51
|
+
let failed = false;
|
|
52
|
+
let previousFiles = [];
|
|
53
|
+
let emittedFiles = /* @__PURE__ */ new Set();
|
|
54
|
+
let sourceWatcher;
|
|
55
|
+
let watchDirectory;
|
|
56
|
+
let sentinel;
|
|
57
|
+
let revision = 0;
|
|
58
|
+
let sentinelWrites = Promise.resolve();
|
|
59
|
+
let sentinelTimer;
|
|
60
|
+
const virtual = `dirwell-watch:${index}:${prefix}`;
|
|
61
|
+
async function prepare() {
|
|
62
|
+
config = {
|
|
63
|
+
...(await loadDirwellConfig(cwd, "build")).config,
|
|
64
|
+
...inline
|
|
65
|
+
};
|
|
66
|
+
validateConfig(config);
|
|
67
|
+
source = path.resolve(cwd, config.root ?? ".");
|
|
68
|
+
}
|
|
69
|
+
async function paths() {
|
|
70
|
+
return watchPaths(source, hostOutput === void 0 ? [] : [hostOutput]);
|
|
71
|
+
}
|
|
72
|
+
async function emit(target) {
|
|
73
|
+
if (failed) return;
|
|
74
|
+
if (hostOutput === void 0) throw new Error("Dirwell requires a host output directory");
|
|
75
|
+
const destination = path.join(hostOutput, prefix);
|
|
76
|
+
if (isWithin(await canonicalPath(destination), await realpath(source))) throw new Error("Dirwell outputPath must not contain the source directory");
|
|
77
|
+
previousFiles = [];
|
|
78
|
+
try {
|
|
79
|
+
if ((await lstat(destination)).isSymbolicLink()) throw new Error("Dirwell refuses a symlink outputPath");
|
|
80
|
+
if ((await readdir(destination)).length) {
|
|
81
|
+
const value = JSON.parse(await readFile(path.join(destination, marker), "utf8").catch(() => "null"));
|
|
82
|
+
if (typeof value !== "object" || value === null || !("version" in value) || value.version !== 1 || !("files" in value) || !Array.isArray(value.files) || !value.files.every((file) => typeof file === "string")) throw new Error(`Dirwell refuses to replace an unowned outputPath: ${destination}`);
|
|
83
|
+
previousFiles = value.files.map(outputPath);
|
|
84
|
+
}
|
|
85
|
+
} catch (error) {
|
|
86
|
+
if (error.code !== "ENOENT") throw error;
|
|
87
|
+
}
|
|
88
|
+
const temporary = await mkdtemp(path.join(tmpdir(), "dirwell-plugin-"));
|
|
89
|
+
try {
|
|
90
|
+
const generate = resolveGenerateOptions(cwd, {
|
|
91
|
+
...config,
|
|
92
|
+
outDir: temporary
|
|
93
|
+
});
|
|
94
|
+
if (generate.mirror !== false) await assertSafeMirroredSymlinks(generate);
|
|
95
|
+
await generateExplorerSkippingPaths(generate, [hostOutput]);
|
|
96
|
+
const generated = await watchPaths(temporary, []);
|
|
97
|
+
emittedFiles = new Set(generated.files.map((file) => path.relative(temporary, file).split(path.sep).join("/")));
|
|
98
|
+
for (const file of generated.files) target.emitFile({
|
|
99
|
+
type: "asset",
|
|
100
|
+
fileName: `${prefix}/${path.relative(temporary, file).split(path.sep).join("/")}`,
|
|
101
|
+
source: await readFile(file)
|
|
102
|
+
});
|
|
103
|
+
target.emitFile({
|
|
104
|
+
type: "asset",
|
|
105
|
+
fileName: `${prefix}/${marker}`,
|
|
106
|
+
source: JSON.stringify({
|
|
107
|
+
version: 1,
|
|
108
|
+
files: [...emittedFiles]
|
|
109
|
+
})
|
|
110
|
+
});
|
|
111
|
+
} finally {
|
|
112
|
+
await rm(temporary, {
|
|
113
|
+
recursive: true,
|
|
114
|
+
force: true
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
async function removeStaleFiles() {
|
|
119
|
+
if (failed || hostOutput === void 0) return;
|
|
120
|
+
const destination = path.join(hostOutput, prefix);
|
|
121
|
+
const canonicalDestination = await canonicalPath(destination);
|
|
122
|
+
for (const file of previousFiles) {
|
|
123
|
+
if (emittedFiles.has(file)) continue;
|
|
124
|
+
const stale = path.join(destination, file);
|
|
125
|
+
if (!isWithin(canonicalDestination, await canonicalPath(path.dirname(stale)))) throw new Error("Dirwell refuses to remove a stale asset through a symlink");
|
|
126
|
+
await rm(stale, { force: true });
|
|
127
|
+
}
|
|
128
|
+
previousFiles = [];
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
name: `dirwell:${prefix}`,
|
|
132
|
+
async buildStart() {
|
|
133
|
+
context = { emitFile: (asset) => this.emitFile(asset) };
|
|
134
|
+
failed = false;
|
|
135
|
+
const native = this.getNativeBuildContext?.();
|
|
136
|
+
if (native?.framework === "webpack" || native?.framework === "rspack") {
|
|
137
|
+
if (inline.cwd === void 0) cwd = native.compiler.context;
|
|
138
|
+
hostOutput = native.compiler.options.output.path;
|
|
139
|
+
}
|
|
140
|
+
await prepare();
|
|
141
|
+
if (meta.framework === "rolldown" && "meta" in this && typeof this.meta === "object" && this.meta !== null && "watchMode" in this.meta && this.meta.watchMode) {
|
|
142
|
+
if (sourceWatcher === void 0) {
|
|
143
|
+
watchDirectory = await mkdtemp(path.join(tmpdir(), "dirwell-watch-"));
|
|
144
|
+
sentinel = path.join(watchDirectory, "revision.js");
|
|
145
|
+
await writeFile(sentinel, "export {};\n");
|
|
146
|
+
sourceWatcher = watch(source, {
|
|
147
|
+
ignoreInitial: true,
|
|
148
|
+
followSymlinks: false,
|
|
149
|
+
ignored: (name) => hostOutput !== void 0 && isWithin(hostOutput, name)
|
|
150
|
+
});
|
|
151
|
+
await new Promise((resolve, reject) => {
|
|
152
|
+
sourceWatcher.once("ready", resolve);
|
|
153
|
+
sourceWatcher.once("error", reject);
|
|
154
|
+
});
|
|
155
|
+
const notify = () => {
|
|
156
|
+
clearTimeout(sentinelTimer);
|
|
157
|
+
sentinelTimer = setTimeout(() => {
|
|
158
|
+
sentinelWrites = sentinelWrites.then(() => writeFile(sentinel, `// ${++revision}\nexport {};\n`)).catch((error) => console.error("Dirwell watch failed", error));
|
|
159
|
+
}, 50);
|
|
160
|
+
};
|
|
161
|
+
sourceWatcher.on("all", notify);
|
|
162
|
+
sourceWatcher.on("raw", (event, name, details) => {
|
|
163
|
+
if (event !== "rename" || typeof name !== "string" || typeof details !== "object" || details === null || !("watchedPath" in details) || typeof details.watchedPath !== "string") return;
|
|
164
|
+
const changed = path.isAbsolute(name) ? name : path.basename(details.watchedPath) === name ? details.watchedPath : path.resolve(details.watchedPath, name);
|
|
165
|
+
if (isWithin(source, changed) && (hostOutput === void 0 || !isWithin(hostOutput, changed))) notify();
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
this.addWatchFile(sentinel);
|
|
169
|
+
}
|
|
170
|
+
if (meta.framework !== "esbuild" && meta.framework !== "bun") {
|
|
171
|
+
const watched = await paths();
|
|
172
|
+
if (native?.framework === "webpack" || native?.framework === "rspack") for (const directory of watched.directories) native.compilation?.contextDependencies.add(directory);
|
|
173
|
+
else for (const directory of watched.directories) this.addWatchFile(directory);
|
|
174
|
+
for (const file of watched.files) this.addWatchFile(file);
|
|
175
|
+
if (native?.framework === "webpack" || native?.framework === "rspack") native.compilation?.hooks.processAssets.tapPromise({
|
|
176
|
+
name: `dirwell:${prefix}`,
|
|
177
|
+
stage: native.compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL
|
|
178
|
+
}, async () => {
|
|
179
|
+
if (!native.compilation?.errors.length) await emit({ emitFile: (asset) => this.emitFile(asset) });
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
async buildEnd() {
|
|
184
|
+
if (![
|
|
185
|
+
"rollup",
|
|
186
|
+
"rolldown",
|
|
187
|
+
"unloader",
|
|
188
|
+
"esbuild",
|
|
189
|
+
"bun",
|
|
190
|
+
"webpack",
|
|
191
|
+
"rspack",
|
|
192
|
+
"rsbuild"
|
|
193
|
+
].includes(meta.framework)) await emit(this);
|
|
194
|
+
},
|
|
195
|
+
async writeBundle() {
|
|
196
|
+
await removeStaleFiles();
|
|
197
|
+
},
|
|
198
|
+
rollup: { async generateBundle(output) {
|
|
199
|
+
hostOutput = path.resolve(cwd, output.dir ?? path.dirname(output.file ?? "dist/index.js"));
|
|
200
|
+
await emit(this);
|
|
201
|
+
} },
|
|
202
|
+
rolldown: {
|
|
203
|
+
transform(code, id) {
|
|
204
|
+
if (sentinel === void 0 || !this.getModuleInfo(id)?.isEntry) return null;
|
|
205
|
+
return {
|
|
206
|
+
code: `import ${JSON.stringify(sentinel)};\n${code}`,
|
|
207
|
+
map: null
|
|
208
|
+
};
|
|
209
|
+
},
|
|
210
|
+
async closeWatcher() {
|
|
211
|
+
await sourceWatcher?.close();
|
|
212
|
+
clearTimeout(sentinelTimer);
|
|
213
|
+
await sentinelWrites;
|
|
214
|
+
sourceWatcher = void 0;
|
|
215
|
+
if (watchDirectory !== void 0) await rm(watchDirectory, {
|
|
216
|
+
recursive: true,
|
|
217
|
+
force: true
|
|
218
|
+
});
|
|
219
|
+
watchDirectory = void 0;
|
|
220
|
+
sentinel = void 0;
|
|
221
|
+
},
|
|
222
|
+
async generateBundle(output) {
|
|
223
|
+
hostOutput = path.resolve(cwd, output.dir ?? path.dirname(output.file ?? "dist/index.js"));
|
|
224
|
+
await emit(this);
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
webpack(compiler) {
|
|
228
|
+
compiler.hooks.shouldEmit.tap(`dirwell:${prefix}`, (compilation) => {
|
|
229
|
+
failed = compilation.errors.length > 0;
|
|
230
|
+
});
|
|
231
|
+
},
|
|
232
|
+
rspack(compiler) {
|
|
233
|
+
compiler.hooks.shouldEmit.tap(`dirwell:${prefix}`, (compilation) => {
|
|
234
|
+
failed = compilation.errors.length > 0;
|
|
235
|
+
});
|
|
236
|
+
},
|
|
237
|
+
farm: {
|
|
238
|
+
configResolved(resolved) {
|
|
239
|
+
if (inline.cwd === void 0) cwd = resolved.compilation?.root ?? cwd;
|
|
240
|
+
hostOutput = path.resolve(cwd, resolved.compilation?.output?.path ?? "dist");
|
|
241
|
+
},
|
|
242
|
+
configureDevServer(server) {
|
|
243
|
+
let assets = /* @__PURE__ */ new Map();
|
|
244
|
+
let pending = Promise.resolve();
|
|
245
|
+
let timer;
|
|
246
|
+
let closed = false;
|
|
247
|
+
const clients = /* @__PURE__ */ new Set();
|
|
248
|
+
async function rebuild() {
|
|
249
|
+
if (closed) return;
|
|
250
|
+
const next = /* @__PURE__ */ new Map();
|
|
251
|
+
await prepare();
|
|
252
|
+
await emit({ emitFile(asset) {
|
|
253
|
+
next.set(asset.fileName, asset.source);
|
|
254
|
+
} });
|
|
255
|
+
assets = next;
|
|
256
|
+
for (const client of clients) client.write("event: reload\ndata: updated\n\n");
|
|
257
|
+
}
|
|
258
|
+
const ready = (async () => {
|
|
259
|
+
await rebuild();
|
|
260
|
+
sourceWatcher = watch(source, {
|
|
261
|
+
ignoreInitial: true,
|
|
262
|
+
followSymlinks: false,
|
|
263
|
+
ignored: (name) => hostOutput !== void 0 && isWithin(hostOutput, name)
|
|
264
|
+
});
|
|
265
|
+
await new Promise((resolve, reject) => {
|
|
266
|
+
sourceWatcher.once("ready", resolve);
|
|
267
|
+
sourceWatcher.once("error", reject);
|
|
268
|
+
});
|
|
269
|
+
sourceWatcher.on("all", () => {
|
|
270
|
+
clearTimeout(timer);
|
|
271
|
+
timer = setTimeout(() => {
|
|
272
|
+
pending = pending.then(rebuild).catch((error) => server.logger.error(`Dirwell rebuild failed: ${String(error)}`));
|
|
273
|
+
}, 75);
|
|
274
|
+
});
|
|
275
|
+
})();
|
|
276
|
+
ready.catch((error) => server.logger.error(`Dirwell preview failed: ${String(error)}`));
|
|
277
|
+
server.app().use(async (ctx, next) => {
|
|
278
|
+
await ready;
|
|
279
|
+
const base = `${new URL(server.publicPath ?? "/", "http://dirwell.local").pathname.replace(/\/+$/, "")}/${prefix}/`;
|
|
280
|
+
if (ctx.path === base.slice(0, -1)) {
|
|
281
|
+
ctx.redirect(base);
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
if (!ctx.path.startsWith(base)) {
|
|
285
|
+
await next();
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
const events = `${base}__dirwell_events`;
|
|
289
|
+
if (ctx.path === events) {
|
|
290
|
+
ctx.respond = false;
|
|
291
|
+
ctx.res.writeHead(200, {
|
|
292
|
+
"content-type": "text/event-stream",
|
|
293
|
+
"cache-control": "no-cache"
|
|
294
|
+
});
|
|
295
|
+
ctx.res.write(": connected\n\n");
|
|
296
|
+
clients.add(ctx.res);
|
|
297
|
+
ctx.req.on("close", () => clients.delete(ctx.res));
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
let relative;
|
|
301
|
+
try {
|
|
302
|
+
relative = decodeURIComponent(ctx.path.slice(base.length));
|
|
303
|
+
} catch {
|
|
304
|
+
ctx.status = 400;
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
if (relative.split("/").some((part) => part === "..") || relative.includes("\\")) {
|
|
308
|
+
ctx.status = 403;
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
const file = `${prefix}/${relative.endsWith("/") || !relative ? `${relative}index.html` : relative}`;
|
|
312
|
+
const contents = assets.get(file);
|
|
313
|
+
if (contents === void 0) {
|
|
314
|
+
ctx.status = 404;
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
ctx.type = path.extname(file) || "application/octet-stream";
|
|
318
|
+
ctx.set("cache-control", "no-store");
|
|
319
|
+
ctx.body = file.endsWith(".html") ? Buffer.from(contents).toString().replace("</body>", `<script>new EventSource(${JSON.stringify(events)}).addEventListener('reload',()=>location.reload())<\/script></body>`) : contents;
|
|
320
|
+
});
|
|
321
|
+
const close = server.close.bind(server);
|
|
322
|
+
server.close = async () => {
|
|
323
|
+
closed = true;
|
|
324
|
+
clearTimeout(timer);
|
|
325
|
+
for (const client of clients) client.end();
|
|
326
|
+
try {
|
|
327
|
+
await ready;
|
|
328
|
+
await sourceWatcher?.close();
|
|
329
|
+
await pending;
|
|
330
|
+
await server.watcher?.getInternalWatcher()?.close();
|
|
331
|
+
} finally {
|
|
332
|
+
sourceWatcher = void 0;
|
|
333
|
+
await close();
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
},
|
|
338
|
+
esbuild: { setup(build) {
|
|
339
|
+
if (inline.cwd === void 0) cwd = build.initialOptions.absWorkingDir ?? cwd;
|
|
340
|
+
const output = build.initialOptions.outdir ?? (build.initialOptions.outfile === void 0 ? void 0 : path.dirname(build.initialOptions.outfile));
|
|
341
|
+
if (output !== void 0) hostOutput = path.resolve(cwd, output);
|
|
342
|
+
build.initialOptions.inject = [...build.initialOptions.inject ?? [], virtual];
|
|
343
|
+
build.onResolve({ filter: /^dirwell-watch:/ }, (args) => args.path === virtual ? {
|
|
344
|
+
path: virtual,
|
|
345
|
+
namespace: virtual
|
|
346
|
+
} : void 0);
|
|
347
|
+
build.onLoad({
|
|
348
|
+
filter: /.*/,
|
|
349
|
+
namespace: virtual
|
|
350
|
+
}, async () => {
|
|
351
|
+
const watched = await paths();
|
|
352
|
+
return {
|
|
353
|
+
contents: "",
|
|
354
|
+
loader: "js",
|
|
355
|
+
watchFiles: watched.files,
|
|
356
|
+
watchDirs: watched.directories
|
|
357
|
+
};
|
|
358
|
+
});
|
|
359
|
+
build.onStart(async () => {
|
|
360
|
+
failed = false;
|
|
361
|
+
await prepare();
|
|
362
|
+
});
|
|
363
|
+
build.onEnd(async (result) => {
|
|
364
|
+
if (result.errors.length) return;
|
|
365
|
+
const assets = [];
|
|
366
|
+
await emit({ emitFile(asset) {
|
|
367
|
+
if (asset.fileName && asset.source !== void 0) assets.push({
|
|
368
|
+
fileName: asset.fileName,
|
|
369
|
+
source: asset.source
|
|
370
|
+
});
|
|
371
|
+
} });
|
|
372
|
+
for (const asset of assets) {
|
|
373
|
+
const destination = path.join(hostOutput, asset.fileName);
|
|
374
|
+
if (build.initialOptions.write !== false) {
|
|
375
|
+
await mkdir(path.dirname(destination), { recursive: true });
|
|
376
|
+
await writeFile(destination, asset.source);
|
|
377
|
+
} else {
|
|
378
|
+
const bytes = typeof asset.source === "string" ? Buffer.from(asset.source) : asset.source;
|
|
379
|
+
result.outputFiles ??= [];
|
|
380
|
+
result.outputFiles.push({
|
|
381
|
+
path: destination,
|
|
382
|
+
contents: bytes,
|
|
383
|
+
hash: "",
|
|
384
|
+
get text() {
|
|
385
|
+
return Buffer.from(bytes).toString();
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
if (build.initialOptions.write !== false) await removeStaleFiles();
|
|
391
|
+
});
|
|
392
|
+
} },
|
|
393
|
+
bun: { setup(build) {
|
|
394
|
+
if (build.config.outdir !== void 0) hostOutput = path.resolve(cwd, build.config.outdir);
|
|
395
|
+
build.onEnd(async (result) => {
|
|
396
|
+
failed = !result.success;
|
|
397
|
+
if (!failed) {
|
|
398
|
+
await emit(context);
|
|
399
|
+
await removeStaleFiles();
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
} }
|
|
403
|
+
};
|
|
404
|
+
});
|
|
405
|
+
});
|
|
406
|
+
/** The Vite host retains its server integration; all other hosts share asset generation. */
|
|
407
|
+
const unplugin = {
|
|
408
|
+
vite: core.vite,
|
|
409
|
+
rollup: core.rollup,
|
|
410
|
+
rolldown: core.rolldown,
|
|
411
|
+
webpack: core.webpack,
|
|
412
|
+
rspack: core.rspack,
|
|
413
|
+
rsbuild: core.rsbuild,
|
|
414
|
+
esbuild: core.esbuild,
|
|
415
|
+
farm: core.farm,
|
|
416
|
+
bun: core.bun
|
|
417
|
+
};
|
|
418
|
+
//#endregion
|
|
419
|
+
export { unplugin as t };
|
|
420
|
+
|
|
421
|
+
//# sourceMappingURL=unplugin-p6AXhL4F.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unplugin-p6AXhL4F.mjs","names":[],"sources":["../src/unplugin.ts"],"sourcesContent":["import {\n lstat,\n mkdir,\n mkdtemp,\n readdir,\n readFile,\n realpath,\n rm,\n writeFile,\n} from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { watch, type FSWatcher } from \"chokidar\";\nimport { createUnplugin, type UnpluginOptions, type UnpluginInstance } from \"unplugin\";\nimport {\n loadDirwellConfig,\n resolveGenerateOptions,\n validateConfig,\n type DirwellConfig,\n} from \"./config.ts\";\nimport { generateExplorerSkippingPaths } from \"./generator.ts\";\nimport dirwellVite from \"./vite.ts\";\nimport { assertSafeMirroredSymlinks, canonicalPath, isWithin } from \"./plugin-safety.ts\";\n\n/** A directory explorer emitted beneath the host's output root. */\nexport interface DirwellPluginOptions extends Omit<DirwellConfig, \"extends\" | \"server\" | \"outDir\"> {\n /** Project directory used for config discovery and relative source paths. */\n readonly cwd?: string;\n /** Dedicated relative path inside the host output; defaults to `dirwell`. */\n readonly outputPath?: string;\n}\n\nexport type DirwellPluginInput = DirwellPluginOptions | readonly DirwellPluginOptions[] | undefined;\ninterface PreviewContext {\n path: string;\n status: number;\n type: string;\n respond: boolean;\n body?: string | Uint8Array;\n req: IncomingMessage;\n res: ServerResponse;\n redirect(path: string): void;\n set(name: string, value: string): void;\n}\nconst marker = \".dirwell-plugin-output\";\n\nfunction outputPath(value = \"dirwell\"): string {\n if (\n !value ||\n path.isAbsolute(value) ||\n value.includes(\"\\\\\") ||\n value.split(\"/\").some((part) => !part || part === \".\" || part === \"..\")\n ) {\n throw new TypeError(\n \"Dirwell outputPath must be a dedicated relative path without dot segments\",\n );\n }\n return value;\n}\n\nasync function watchPaths(\n source: string,\n excluded: readonly string[],\n): Promise<{ files: string[]; directories: string[] }> {\n const files: string[] = [];\n const directories: string[] = [];\n async function visit(directory: string): Promise<void> {\n directories.push(directory);\n for (const entry of await readdir(directory, { withFileTypes: true })) {\n const name = path.join(directory, entry.name);\n if (excluded.some((candidate) => isWithin(candidate, name))) continue;\n if (entry.isDirectory()) await visit(name);\n else files.push(name);\n }\n }\n await visit(source);\n return { files, directories };\n}\n\nconst core = createUnplugin<DirwellPluginInput, true>((options, meta) => {\n const entries = Array.isArray(options) ? options : [options ?? {}];\n if (!entries.length) throw new TypeError(\"Dirwell options array must not be empty\");\n const prefixes = entries.map((entry) => outputPath(entry.outputPath));\n for (let index = 0; index < prefixes.length; index++) {\n for (let other = 0; other < index; other++) {\n if (\n isWithin(prefixes[index]!, prefixes[other]!) ||\n isWithin(prefixes[other]!, prefixes[index]!)\n ) {\n throw new Error(\"Dirwell options array has overlapping outputPath paths\");\n }\n }\n }\n return entries.map((inline, index): UnpluginOptions => {\n const prefix = prefixes[index]!;\n if (meta.framework === \"vite\")\n return { name: `dirwell:${prefix}`, vite: dirwellVite({ ...inline, outputPath: prefix }) };\n let cwd = path.resolve(inline.cwd ?? process.cwd());\n let hostOutput: string | undefined;\n let config: DirwellConfig;\n let source: string;\n let context: {\n emitFile(asset: { type: \"asset\"; fileName: string; source: string | Uint8Array }): unknown;\n };\n let failed = false;\n let previousFiles: string[] = [];\n let emittedFiles = new Set<string>();\n let sourceWatcher: FSWatcher | undefined;\n let watchDirectory: string | undefined;\n let sentinel: string | undefined;\n let revision = 0;\n let sentinelWrites = Promise.resolve();\n let sentinelTimer: ReturnType<typeof setTimeout> | undefined;\n const virtual = `dirwell-watch:${index}:${prefix}`;\n\n async function prepare(): Promise<void> {\n const loaded = await loadDirwellConfig(cwd, \"build\");\n config = { ...loaded.config, ...inline };\n validateConfig(config);\n source = path.resolve(cwd, config.root ?? \".\");\n }\n\n async function paths() {\n return watchPaths(source, hostOutput === undefined ? [] : [hostOutput]);\n }\n\n async function emit(target: {\n emitFile(asset: { type: \"asset\"; fileName: string; source: string | Uint8Array }): unknown;\n }): Promise<void> {\n if (failed) return;\n if (hostOutput === undefined) throw new Error(\"Dirwell requires a host output directory\");\n const destination = path.join(hostOutput, prefix);\n if (isWithin(await canonicalPath(destination), await realpath(source))) {\n throw new Error(\"Dirwell outputPath must not contain the source directory\");\n }\n previousFiles = [];\n try {\n if ((await lstat(destination)).isSymbolicLink())\n throw new Error(\"Dirwell refuses a symlink outputPath\");\n const existing = await readdir(destination);\n if (existing.length) {\n const value: unknown = JSON.parse(\n await readFile(path.join(destination, marker), \"utf8\").catch(() => \"null\"),\n );\n if (\n typeof value !== \"object\" ||\n value === null ||\n !(\"version\" in value) ||\n value.version !== 1 ||\n !(\"files\" in value) ||\n !Array.isArray(value.files) ||\n !value.files.every((file): file is string => typeof file === \"string\")\n ) {\n throw new Error(`Dirwell refuses to replace an unowned outputPath: ${destination}`);\n }\n previousFiles = value.files.map(outputPath);\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n const temporary = await mkdtemp(path.join(tmpdir(), \"dirwell-plugin-\"));\n try {\n const generate = resolveGenerateOptions(cwd, { ...config, outDir: temporary });\n if (generate.mirror !== false) await assertSafeMirroredSymlinks(generate);\n await generateExplorerSkippingPaths(generate, [hostOutput]);\n const generated = await watchPaths(temporary, []);\n emittedFiles = new Set(\n generated.files.map((file) => path.relative(temporary, file).split(path.sep).join(\"/\")),\n );\n for (const file of generated.files) {\n target.emitFile({\n type: \"asset\",\n fileName: `${prefix}/${path.relative(temporary, file).split(path.sep).join(\"/\")}`,\n source: await readFile(file),\n });\n }\n target.emitFile({\n type: \"asset\",\n fileName: `${prefix}/${marker}`,\n source: JSON.stringify({ version: 1, files: [...emittedFiles] }),\n });\n } finally {\n await rm(temporary, { recursive: true, force: true });\n }\n }\n\n async function removeStaleFiles(): Promise<void> {\n if (failed || hostOutput === undefined) return;\n const destination = path.join(hostOutput, prefix);\n const canonicalDestination = await canonicalPath(destination);\n for (const file of previousFiles) {\n if (emittedFiles.has(file)) continue;\n const stale = path.join(destination, file);\n if (!isWithin(canonicalDestination, await canonicalPath(path.dirname(stale))))\n throw new Error(\"Dirwell refuses to remove a stale asset through a symlink\");\n await rm(stale, { force: true });\n }\n previousFiles = [];\n }\n\n return {\n name: `dirwell:${prefix}`,\n async buildStart() {\n context = { emitFile: (asset) => this.emitFile(asset) };\n failed = false;\n const native = this.getNativeBuildContext?.();\n if (native?.framework === \"webpack\" || native?.framework === \"rspack\") {\n if (inline.cwd === undefined) cwd = native.compiler.context;\n hostOutput = native.compiler.options.output.path;\n }\n await prepare();\n if (\n meta.framework === \"rolldown\" &&\n \"meta\" in this &&\n typeof this.meta === \"object\" &&\n this.meta !== null &&\n \"watchMode\" in this.meta &&\n this.meta.watchMode\n ) {\n if (sourceWatcher === undefined) {\n watchDirectory = await mkdtemp(path.join(tmpdir(), \"dirwell-watch-\"));\n sentinel = path.join(watchDirectory, \"revision.js\");\n await writeFile(sentinel, \"export {};\\n\");\n sourceWatcher = watch(source, {\n ignoreInitial: true,\n followSymlinks: false,\n ignored: (name) => hostOutput !== undefined && isWithin(hostOutput, name),\n });\n await new Promise<void>((resolve, reject) => {\n sourceWatcher!.once(\"ready\", resolve);\n sourceWatcher!.once(\"error\", reject);\n });\n const notify = () => {\n clearTimeout(sentinelTimer);\n sentinelTimer = setTimeout(() => {\n sentinelWrites = sentinelWrites\n .then(() => writeFile(sentinel!, `// ${++revision}\\nexport {};\\n`))\n .catch((error) => console.error(\"Dirwell watch failed\", error));\n }, 50);\n };\n sourceWatcher.on(\"all\", notify);\n // A rapid add/unlink can precede Chokidar's per-file watcher registration.\n // Parent-directory rename events still identify that tree change.\n sourceWatcher.on(\"raw\", (event: string, name: string, details: unknown) => {\n if (\n event !== \"rename\" ||\n typeof name !== \"string\" ||\n typeof details !== \"object\" ||\n details === null ||\n !(\"watchedPath\" in details) ||\n typeof details.watchedPath !== \"string\"\n )\n return;\n const changed = path.isAbsolute(name)\n ? name\n : path.basename(details.watchedPath) === name\n ? details.watchedPath\n : path.resolve(details.watchedPath, name);\n if (\n isWithin(source, changed) &&\n (hostOutput === undefined || !isWithin(hostOutput, changed))\n )\n notify();\n });\n }\n this.addWatchFile(sentinel!);\n }\n if (meta.framework !== \"esbuild\" && meta.framework !== \"bun\") {\n const watched = await paths();\n if (native?.framework === \"webpack\" || native?.framework === \"rspack\") {\n for (const directory of watched.directories)\n native.compilation?.contextDependencies.add(directory);\n } else {\n for (const directory of watched.directories) this.addWatchFile(directory);\n }\n for (const file of watched.files) this.addWatchFile(file);\n if (native?.framework === \"webpack\" || native?.framework === \"rspack\") {\n native.compilation?.hooks.processAssets.tapPromise(\n {\n name: `dirwell:${prefix}`,\n stage: native.compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL,\n },\n async () => {\n if (!native.compilation?.errors.length)\n await emit({ emitFile: (asset) => this.emitFile(asset) });\n },\n );\n }\n }\n },\n async buildEnd() {\n if (\n ![\n \"rollup\",\n \"rolldown\",\n \"unloader\",\n \"esbuild\",\n \"bun\",\n \"webpack\",\n \"rspack\",\n \"rsbuild\",\n ].includes(meta.framework)\n )\n await emit(this);\n },\n async writeBundle() {\n await removeStaleFiles();\n },\n rollup: {\n async generateBundle(output) {\n hostOutput = path.resolve(\n cwd,\n output.dir ?? path.dirname(output.file ?? \"dist/index.js\"),\n );\n await emit(this);\n },\n },\n rolldown: {\n transform(code, id) {\n if (sentinel === undefined || !this.getModuleInfo(id)?.isEntry) return null;\n return { code: `import ${JSON.stringify(sentinel)};\\n${code}`, map: null };\n },\n async closeWatcher() {\n await sourceWatcher?.close();\n clearTimeout(sentinelTimer);\n await sentinelWrites;\n sourceWatcher = undefined;\n if (watchDirectory !== undefined)\n await rm(watchDirectory, { recursive: true, force: true });\n watchDirectory = undefined;\n sentinel = undefined;\n },\n async generateBundle(output) {\n hostOutput = path.resolve(\n cwd,\n output.dir ?? path.dirname(output.file ?? \"dist/index.js\"),\n );\n await emit(this);\n },\n },\n webpack(compiler) {\n compiler.hooks.shouldEmit.tap(`dirwell:${prefix}`, (compilation) => {\n failed = compilation.errors.length > 0;\n });\n },\n rspack(compiler) {\n compiler.hooks.shouldEmit.tap(`dirwell:${prefix}`, (compilation) => {\n failed = compilation.errors.length > 0;\n });\n },\n farm: {\n configResolved(resolved) {\n if (inline.cwd === undefined) cwd = resolved.compilation?.root ?? cwd;\n hostOutput = path.resolve(cwd, resolved.compilation?.output?.path ?? \"dist\");\n },\n configureDevServer(server) {\n let assets = new Map<string, string | Uint8Array>();\n let pending = Promise.resolve();\n let timer: ReturnType<typeof setTimeout> | undefined;\n let closed = false;\n const clients = new Set<ServerResponse>();\n async function rebuild() {\n if (closed) return;\n const next = new Map<string, string | Uint8Array>();\n await prepare();\n await emit({\n emitFile(asset) {\n next.set(asset.fileName, asset.source);\n },\n });\n assets = next;\n for (const client of clients) client.write(\"event: reload\\ndata: updated\\n\\n\");\n }\n const ready = (async () => {\n await rebuild();\n sourceWatcher = watch(source, {\n ignoreInitial: true,\n followSymlinks: false,\n ignored: (name) => hostOutput !== undefined && isWithin(hostOutput, name),\n });\n await new Promise<void>((resolve, reject) => {\n sourceWatcher!.once(\"ready\", resolve);\n sourceWatcher!.once(\"error\", reject);\n });\n sourceWatcher.on(\"all\", () => {\n clearTimeout(timer);\n timer = setTimeout(() => {\n pending = pending\n .then(rebuild)\n .catch((error) =>\n server.logger.error(`Dirwell rebuild failed: ${String(error)}`),\n );\n }, 75);\n });\n })();\n void ready.catch((error) =>\n server.logger.error(`Dirwell preview failed: ${String(error)}`),\n );\n // Farm does not await configureDevServer; await readiness in its middleware.\n server\n .app()\n .use(async (ctx: PreviewContext, next: () => Promise<unknown>): Promise<void> => {\n await ready;\n const base = `${new URL(server.publicPath ?? \"/\", \"http://dirwell.local\").pathname.replace(/\\/+$/, \"\")}/${prefix}/`;\n if (ctx.path === base.slice(0, -1)) {\n ctx.redirect(base);\n return;\n }\n if (!ctx.path.startsWith(base)) {\n await next();\n return;\n }\n const events = `${base}__dirwell_events`;\n if (ctx.path === events) {\n ctx.respond = false;\n ctx.res.writeHead(200, {\n \"content-type\": \"text/event-stream\",\n \"cache-control\": \"no-cache\",\n });\n ctx.res.write(\": connected\\n\\n\");\n clients.add(ctx.res);\n ctx.req.on(\"close\", () => clients.delete(ctx.res));\n return;\n }\n let relative: string;\n try {\n relative = decodeURIComponent(ctx.path.slice(base.length));\n } catch {\n ctx.status = 400;\n return;\n }\n if (relative.split(\"/\").some((part) => part === \"..\") || relative.includes(\"\\\\\")) {\n ctx.status = 403;\n return;\n }\n const file = `${prefix}/${relative.endsWith(\"/\") || !relative ? `${relative}index.html` : relative}`;\n const contents = assets.get(file);\n if (contents === undefined) {\n ctx.status = 404;\n return;\n }\n ctx.type = path.extname(file) || \"application/octet-stream\";\n ctx.set(\"cache-control\", \"no-store\");\n ctx.body = file.endsWith(\".html\")\n ? Buffer.from(contents)\n .toString()\n .replace(\n \"</body>\",\n `<script>new EventSource(${JSON.stringify(events)}).addEventListener('reload',()=>location.reload())</script></body>`,\n )\n : contents;\n });\n const close = server.close.bind(server);\n server.close = async () => {\n closed = true;\n clearTimeout(timer);\n for (const client of clients) client.end();\n try {\n await ready;\n await sourceWatcher?.close();\n await pending;\n await server.watcher?.getInternalWatcher()?.close();\n } finally {\n sourceWatcher = undefined;\n await close();\n }\n };\n },\n },\n esbuild: {\n setup(build) {\n if (inline.cwd === undefined) cwd = build.initialOptions.absWorkingDir ?? cwd;\n const output =\n build.initialOptions.outdir ??\n (build.initialOptions.outfile === undefined\n ? undefined\n : path.dirname(build.initialOptions.outfile));\n if (output !== undefined) hostOutput = path.resolve(cwd, output);\n build.initialOptions.inject = [...(build.initialOptions.inject ?? []), virtual];\n build.onResolve({ filter: /^dirwell-watch:/ }, (args) =>\n args.path === virtual ? { path: virtual, namespace: virtual } : undefined,\n );\n build.onLoad({ filter: /.*/, namespace: virtual }, async () => {\n const watched = await paths();\n return {\n contents: \"\",\n loader: \"js\",\n watchFiles: watched.files,\n watchDirs: watched.directories,\n };\n });\n build.onStart(async () => {\n failed = false;\n await prepare();\n });\n build.onEnd(async (result) => {\n if (result.errors.length) return;\n const assets: { fileName: string; source: string | Uint8Array }[] = [];\n await emit({\n emitFile(asset) {\n if (asset.fileName && asset.source !== undefined)\n assets.push({ fileName: asset.fileName, source: asset.source });\n },\n });\n for (const asset of assets) {\n const destination = path.join(hostOutput!, asset.fileName);\n if (build.initialOptions.write !== false) {\n await mkdir(path.dirname(destination), { recursive: true });\n await writeFile(destination, asset.source);\n } else {\n const bytes =\n typeof asset.source === \"string\" ? Buffer.from(asset.source) : asset.source;\n result.outputFiles ??= [];\n result.outputFiles.push({\n path: destination,\n contents: bytes,\n hash: \"\",\n get text() {\n return Buffer.from(bytes).toString();\n },\n });\n }\n }\n if (build.initialOptions.write !== false) await removeStaleFiles();\n });\n },\n },\n bun: {\n setup(build) {\n if (build.config.outdir !== undefined)\n hostOutput = path.resolve(cwd, build.config.outdir);\n build.onEnd(async (result: { success: boolean }) => {\n failed = !result.success;\n if (!failed) {\n await emit(context);\n await removeStaleFiles();\n }\n });\n },\n },\n };\n });\n});\n\n/** The Vite host retains its server integration; all other hosts share asset generation. */\nexport const unplugin: Pick<\n UnpluginInstance<DirwellPluginInput, true>,\n \"vite\" | \"rollup\" | \"rolldown\" | \"webpack\" | \"rspack\" | \"rsbuild\" | \"esbuild\" | \"farm\" | \"bun\"\n> = {\n vite: core.vite,\n rollup: core.rollup,\n rolldown: core.rolldown,\n webpack: core.webpack,\n rspack: core.rspack,\n rsbuild: core.rsbuild,\n esbuild: core.esbuild,\n farm: core.farm,\n bun: core.bun,\n};\nexport default unplugin;\n"],"mappings":"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"}
|