@hypernym/bundler 0.14.4 → 0.21.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/LICENSE.txt +2 -1
- package/README.md +155 -120
- package/dist/bin/index.mjs +178 -479
- package/dist/build/index.mjs +254 -0
- package/dist/index.d.mts +627 -658
- package/dist/index.mjs +50 -17
- package/dist/plugins/index.d.mts +14 -0
- package/dist/plugins/index.mjs +37 -0
- package/package.json +25 -30
- package/dist/index.cjs +0 -26
- package/dist/index.d.cts +0 -709
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import process, { cwd } from "node:process";
|
|
2
|
+
import { parse, resolve } from "node:path";
|
|
3
|
+
import { stat } from "node:fs/promises";
|
|
4
|
+
import { dim } from "@hypernym/colors";
|
|
5
|
+
import { isUndefined } from "@hypernym/utils";
|
|
6
|
+
import { copy, readdir, write } from "@hypernym/utils/fs";
|
|
7
|
+
import { rolldown } from "rolldown";
|
|
8
|
+
import { dts } from "rolldown-plugin-dts";
|
|
9
|
+
import { outputPaths } from "../plugins/index.mjs";
|
|
10
|
+
|
|
11
|
+
//#region src/bin/meta.ts
|
|
12
|
+
const name = `Hyperbundler`;
|
|
13
|
+
|
|
14
|
+
//#endregion
|
|
15
|
+
//#region src/utils/logger.ts
|
|
16
|
+
const cl = console.log;
|
|
17
|
+
const separator = `|`;
|
|
18
|
+
const logger = {
|
|
19
|
+
info: (...args) => {
|
|
20
|
+
cl(name, dim(separator), ...args);
|
|
21
|
+
},
|
|
22
|
+
error: (...args) => {
|
|
23
|
+
cl();
|
|
24
|
+
cl(name, dim(separator), ...args);
|
|
25
|
+
cl();
|
|
26
|
+
},
|
|
27
|
+
exit: (message) => {
|
|
28
|
+
cl();
|
|
29
|
+
cl(name, dim(separator), message);
|
|
30
|
+
cl();
|
|
31
|
+
return process.exit();
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/utils/error.ts
|
|
37
|
+
function error(err) {
|
|
38
|
+
logger.error("Something went wrong...");
|
|
39
|
+
console.error(err);
|
|
40
|
+
return process.exit();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
//#endregion
|
|
44
|
+
//#region src/utils/format-ms.ts
|
|
45
|
+
function formatMs(ms) {
|
|
46
|
+
const s = 1e3;
|
|
47
|
+
const m = s * 60;
|
|
48
|
+
const h = m * 60;
|
|
49
|
+
const msAbs = Math.abs(ms);
|
|
50
|
+
if (msAbs >= h) return `${(ms / h).toFixed(2)}h`;
|
|
51
|
+
if (msAbs >= m) return `${(ms / m).toFixed(2)}m`;
|
|
52
|
+
if (msAbs >= s) return `${(ms / s).toFixed(2)}s`;
|
|
53
|
+
return `${ms}ms`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
//#endregion
|
|
57
|
+
//#region src/utils/format-bytes.ts
|
|
58
|
+
function formatBytes(bytes) {
|
|
59
|
+
const decimals = 2;
|
|
60
|
+
const units = [
|
|
61
|
+
"B",
|
|
62
|
+
"KB",
|
|
63
|
+
"MB",
|
|
64
|
+
"GB",
|
|
65
|
+
"TB"
|
|
66
|
+
];
|
|
67
|
+
if (bytes === 0) return `0 B`;
|
|
68
|
+
const k = 1024;
|
|
69
|
+
const dm = decimals < 0 ? 0 : decimals;
|
|
70
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
71
|
+
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${units[i]}`;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
//#endregion
|
|
75
|
+
//#region src/utils/get-output-path.ts
|
|
76
|
+
function getOutputPath(outDir, input, { extension = "auto" } = {}) {
|
|
77
|
+
const src = input.startsWith("./") ? input.slice(2) : input;
|
|
78
|
+
let output = src.includes("/") ? src.replace(src.split("/")[0], outDir) : `${outDir}/${src}`;
|
|
79
|
+
if (extension !== "original") {
|
|
80
|
+
const ext = output.match(/\.[^/.]+$/)?.[0] ?? "";
|
|
81
|
+
const esm = [
|
|
82
|
+
".js",
|
|
83
|
+
".mjs",
|
|
84
|
+
".ts",
|
|
85
|
+
".mts"
|
|
86
|
+
];
|
|
87
|
+
const legacy = [".cjs", ".cts"];
|
|
88
|
+
let newExt = "";
|
|
89
|
+
if (esm.includes(ext)) newExt = extension === "dts" ? ".d.mts" : ".mjs";
|
|
90
|
+
else if (legacy.includes(ext)) newExt = extension === "dts" ? ".d.cts" : ".cjs";
|
|
91
|
+
if (newExt) output = `${output.slice(0, -ext.length)}${newExt}`;
|
|
92
|
+
}
|
|
93
|
+
return outDir.startsWith("./") || outDir.startsWith("../") ? output : `./${output}`;
|
|
94
|
+
}
|
|
95
|
+
function parseOutputPath(path) {
|
|
96
|
+
if (!path) return;
|
|
97
|
+
if (path.startsWith("./")) return path;
|
|
98
|
+
else return `./${path}`;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
//#endregion
|
|
102
|
+
//#region src/bin/build.ts
|
|
103
|
+
function logEntryStats(stats) {
|
|
104
|
+
const cl$1 = console.log;
|
|
105
|
+
const base = parse(stats.path).base;
|
|
106
|
+
const path = stats.path.replace(base, "");
|
|
107
|
+
let format = stats.format;
|
|
108
|
+
if (format === "commonjs") format = "cjs";
|
|
109
|
+
if (format === "es" || format === "module") format = "esm";
|
|
110
|
+
const pathDim = dim(path);
|
|
111
|
+
const output = pathDim + base;
|
|
112
|
+
const outputLength = output.length + 2;
|
|
113
|
+
cl$1("▸", format.padEnd(5), output.padEnd(outputLength), dim(`[${formatBytes(stats.size)}, ${formatMs(stats.buildTime)}]`));
|
|
114
|
+
if (stats.logs) for (const log of stats.logs) cl$1("!", log.level.padEnd(5), output.padEnd(outputLength), dim(log.log.message));
|
|
115
|
+
}
|
|
116
|
+
async function build(options) {
|
|
117
|
+
const { cwd: cwdir = cwd(), outDir = "dist", entries, externals, tsconfig, hooks, minify } = options;
|
|
118
|
+
let start = 0;
|
|
119
|
+
const buildStats = {
|
|
120
|
+
cwd: cwdir,
|
|
121
|
+
size: 0,
|
|
122
|
+
buildTime: 0,
|
|
123
|
+
files: []
|
|
124
|
+
};
|
|
125
|
+
await hooks?.["build:start"]?.(options, buildStats);
|
|
126
|
+
if (entries) {
|
|
127
|
+
start = Date.now();
|
|
128
|
+
for (const entry of entries) {
|
|
129
|
+
const entryStart = Date.now();
|
|
130
|
+
if (entry.input || entry.dts) {
|
|
131
|
+
const buildLogs = [];
|
|
132
|
+
const isChunk = !isUndefined(entry.input);
|
|
133
|
+
const outputRawPath = parseOutputPath(entry.output) || getOutputPath(outDir, entry.input || entry.dts, { extension: isChunk ? "auto" : "dts" });
|
|
134
|
+
const outputResolvePath = resolve(cwdir, outputRawPath);
|
|
135
|
+
let format = entry.format || "esm";
|
|
136
|
+
if (outputRawPath.endsWith(".cjs")) format = "cjs";
|
|
137
|
+
const entryInput = {
|
|
138
|
+
input: resolve(cwdir, entry.input || entry.dts),
|
|
139
|
+
external: entry.externals || externals,
|
|
140
|
+
plugins: isChunk ? entry.plugins : entry.plugins || [dts({
|
|
141
|
+
...entry.dtsPlugin,
|
|
142
|
+
emitDtsOnly: true
|
|
143
|
+
})],
|
|
144
|
+
onLog: (level, log, handler) => {
|
|
145
|
+
if (entry.onLog) entry.onLog(level, log, handler, buildLogs);
|
|
146
|
+
else buildLogs.push({
|
|
147
|
+
level,
|
|
148
|
+
log
|
|
149
|
+
});
|
|
150
|
+
},
|
|
151
|
+
resolve: entry.resolve,
|
|
152
|
+
define: entry.define,
|
|
153
|
+
inject: entry.inject,
|
|
154
|
+
tsconfig: entry.tsconfig || tsconfig
|
|
155
|
+
};
|
|
156
|
+
const entryOutput = {
|
|
157
|
+
file: isChunk ? outputResolvePath : void 0,
|
|
158
|
+
minify: isChunk ? !isUndefined(entry.minify) ? entry.minify : minify : void 0,
|
|
159
|
+
format,
|
|
160
|
+
banner: entry.banner,
|
|
161
|
+
footer: entry.footer,
|
|
162
|
+
intro: entry.intro,
|
|
163
|
+
outro: entry.outro,
|
|
164
|
+
name: entry.name,
|
|
165
|
+
globals: entry.globals,
|
|
166
|
+
extend: entry.extend,
|
|
167
|
+
plugins: entry.paths ? [outputPaths(entry.paths)] : void 0
|
|
168
|
+
};
|
|
169
|
+
const entryOptions = {
|
|
170
|
+
...entryInput,
|
|
171
|
+
...entryOutput,
|
|
172
|
+
externals: entryInput.external
|
|
173
|
+
};
|
|
174
|
+
const entryStats = {
|
|
175
|
+
cwd: cwdir,
|
|
176
|
+
path: outputRawPath,
|
|
177
|
+
size: 0,
|
|
178
|
+
buildTime: entryStart,
|
|
179
|
+
format: isChunk ? format : "dts",
|
|
180
|
+
logs: buildLogs
|
|
181
|
+
};
|
|
182
|
+
await hooks?.["build:entry:start"]?.(entryOptions, entryStats);
|
|
183
|
+
const bundle = await rolldown(entryInput);
|
|
184
|
+
if (isChunk) await bundle.write(entryOutput);
|
|
185
|
+
else {
|
|
186
|
+
const generated = await bundle.generate(entryOutput);
|
|
187
|
+
await write(outputResolvePath, generated.output[0].code);
|
|
188
|
+
}
|
|
189
|
+
const stats = await stat(outputResolvePath);
|
|
190
|
+
entryStats.size = stats.size;
|
|
191
|
+
entryStats.buildTime = Date.now() - entryStart;
|
|
192
|
+
entryStats.logs = buildLogs;
|
|
193
|
+
buildStats.files.push(entryStats);
|
|
194
|
+
buildStats.size = buildStats.size + stats.size;
|
|
195
|
+
logEntryStats(entryStats);
|
|
196
|
+
await hooks?.["build:entry:end"]?.(entryOptions, entryStats);
|
|
197
|
+
}
|
|
198
|
+
if (entry.copy) {
|
|
199
|
+
const inputResolvePath = resolve(cwdir, entry.copy);
|
|
200
|
+
const outputRawPath = parseOutputPath(entry.output) || getOutputPath(outDir, entry.copy, { extension: "original" });
|
|
201
|
+
const outputResolvePath = resolve(cwdir, outputRawPath);
|
|
202
|
+
await copy(inputResolvePath, outputResolvePath, {
|
|
203
|
+
recursive: entry.recursive || true,
|
|
204
|
+
filter: entry.filter
|
|
205
|
+
}).catch(error);
|
|
206
|
+
const stats = await stat(outputResolvePath);
|
|
207
|
+
let totalSize = 0;
|
|
208
|
+
if (!stats.isDirectory()) totalSize = stats.size;
|
|
209
|
+
else {
|
|
210
|
+
const files = await readdir(outputResolvePath);
|
|
211
|
+
for (const file of files) {
|
|
212
|
+
const filePath = resolve(outputResolvePath, file);
|
|
213
|
+
const fileStat = await stat(filePath);
|
|
214
|
+
totalSize = totalSize + fileStat.size;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
const entryStats = {
|
|
218
|
+
cwd: cwdir,
|
|
219
|
+
path: outputRawPath,
|
|
220
|
+
size: totalSize,
|
|
221
|
+
buildTime: Date.now() - entryStart,
|
|
222
|
+
format: "copy",
|
|
223
|
+
logs: []
|
|
224
|
+
};
|
|
225
|
+
buildStats.files.push(entryStats);
|
|
226
|
+
buildStats.size = buildStats.size + stats.size;
|
|
227
|
+
logEntryStats(entryStats);
|
|
228
|
+
}
|
|
229
|
+
if (entry.template && entry.output) {
|
|
230
|
+
const outputRawPath = parseOutputPath(entry.output);
|
|
231
|
+
const outputResolvePath = resolve(cwdir, outputRawPath);
|
|
232
|
+
await write(outputResolvePath, entry.template);
|
|
233
|
+
const stats = await stat(outputResolvePath);
|
|
234
|
+
const entryStats = {
|
|
235
|
+
cwd: cwdir,
|
|
236
|
+
path: outputRawPath,
|
|
237
|
+
size: stats.size,
|
|
238
|
+
buildTime: Date.now() - entryStart,
|
|
239
|
+
format: "tmp",
|
|
240
|
+
logs: []
|
|
241
|
+
};
|
|
242
|
+
buildStats.files.push(entryStats);
|
|
243
|
+
buildStats.size = buildStats.size + stats.size;
|
|
244
|
+
logEntryStats(entryStats);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
buildStats.buildTime = Date.now() - start;
|
|
248
|
+
}
|
|
249
|
+
await hooks?.["build:end"]?.(options, buildStats);
|
|
250
|
+
return buildStats;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
//#endregion
|
|
254
|
+
export { build };
|