-
Notifications
You must be signed in to change notification settings - Fork 0
/
esbuild-plugin-add-declarations.ts
71 lines (61 loc) · 1.97 KB
/
esbuild-plugin-add-declarations.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
import type { Plugin } from 'esbuild';
import type { Program } from 'typescript';
import ts from 'typescript';
import { dirname, join, relative, resolve } from 'node:path';
type PluginOptions = {
filter: RegExp;
include: string[];
sourceRoot: string;
outdir: string;
};
function reportDiagnostics(program: Program): string {
return ts.formatDiagnostics(ts.getPreEmitDiagnostics(program), {
getCurrentDirectory: () => ts.sys.getCurrentDirectory(),
getCanonicalFileName: (f) => f,
getNewLine: () => '\n',
});
}
async function generateDeclarations(path: string, include: string[], src: string, dist: string): Promise<void> {
// resolve paths for package.json
const basePath = dirname(relative(src, path));
const declarationDir = join(dist, basePath);
const rootDir = dirname(path);
// generate declarations
const program = ts.createProgram([path, ...include], {
declaration: true,
emitDeclarationOnly: true,
outDir: declarationDir,
rootDir,
});
const source = program.getSourceFile(path);
const result = program.emit(source);
// check for errors
if (result.emitSkipped) {
console.error(reportDiagnostics(program));
return Promise.reject();
}
}
export function addDeclarations(options?: Partial<PluginOptions>): Plugin {
return {
name: 'add declarations',
async setup(build) {
// receive options, fill in defaults from esbuild, set fallbacks
const {
filter = /\.ts$/,
include = [],
outdir = build.initialOptions.outdir ?? 'dist',
sourceRoot = build.initialOptions.sourceRoot ?? 'src',
} = options || {};
// derive paths
const src = resolve(sourceRoot);
const dist = resolve(outdir);
// intercept plugins that are resolved
build.onLoad({ filter }, async ({ path }) => {
// add package.json to all targets
await generateDeclarations(path, include, src, dist);
// go on as usual
return undefined;
});
},
};
}