-
Notifications
You must be signed in to change notification settings - Fork 0
/
esbuild-barrelsby.plugin.ts
80 lines (68 loc) · 2.86 KB
/
esbuild-barrelsby.plugin.ts
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
import { exec } from 'node:child_process';
import { existsSync, watchFile } from 'node:fs';
import { readFile, writeFile } from 'node:fs/promises';
import { resolve } from 'node:path';
import { cwd } from 'node:process';
import { promisify } from 'node:util';
import type { OnResolveResult, Plugin } from 'esbuild';
export type BarrelsbyPluginOptions = {
/**
* Path to barrelsby config file
*/
configPath: string;
/**
* Optionally add `*.js` extensions to generated barrels if missing
*/
addMissingJsExtensions?: boolean;
};
export function barrelsbyPlugin({ configPath, addMissingJsExtensions = false }: BarrelsbyPluginOptions): Plugin {
const pluginName = 'esbuild-plugin-barrelsby';
return {
name: pluginName,
setup(build) {
build.onResolve({ filter: /index\.ts$/ }, async ({ path, resolveDir }) => {
// resolve the path to the index file
const index = resolve(resolveDir, path);
// return a promise that resolves when the watcher fires
return new Promise<OnResolveResult | undefined>((done) => {
// as we can not await the result of barrelsby directly,
// we have to watch the file system for a change
const watcher = watchFile(index, { interval: 200, persistent: false }, async () => {
// if the file is created entirely new, we have to wait
// for the next change event, by checking for existence
if (!existsSync(index)) return;
// add missing js extension if configured
// https://regex101.com/r/9wGBMU/1
if (addMissingJsExtensions) {
const barrel = await readFile(index, 'utf-8');
const fixed = barrel.replace(/(?<!\.js)';$/gm, `.js';`);
await writeFile(index, fixed, 'utf-8');
}
// inform the user
const message = `updated${addMissingJsExtensions ? ' and *.js extensions added' : ''}`;
const level = build.initialOptions.logLevel ?? 'info';
if (['verbose', 'debug', 'info'].includes(level)) {
console.info('[barrelsby]', message);
}
// let esbuild go on with the build; in case the file hasn't
// been existed before, we need to tell about the resolved path
done({ path: index });
// remove watcher
watcher.removeAllListeners();
});
watcher.addListener('error', ({ message, name, stack }) => {
// report errors
done({
path: index,
errors: [{ pluginName, id: name, text: message, detail: stack }],
});
// remove watcher
watcher.removeAllListeners();
});
// call barrelsby to generate the initial barrel
promisify(exec)(`barrelsby --config ${configPath}`, { cwd: cwd() });
});
});
},
};
}