@hypernym/bundler 0.12.0 → 0.13.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/README.md CHANGED
@@ -36,10 +36,6 @@
36
36
 
37
37
  1. Create a `bundler.config.ts` file at the root of your project:
38
38
 
39
- > [!NOTE]
40
- >
41
- > Configuration also accepts `.js`, `.mjs`, `.ts`, `.mts` formats.
42
-
43
39
  ```ts
44
40
  // bundler.config.ts
45
41
 
@@ -66,9 +62,7 @@ export default defineConfig({
66
62
  {
67
63
  input: './src/utils/index.ts',
68
64
  output: './dist/utils/utils.min.mjs',
69
- transformers: {
70
- esbuild: { minify: true },
71
- },
65
+ minify: true,
72
66
  },
73
67
  // ...
74
68
  ],
@@ -81,35 +75,33 @@ export default defineConfig({
81
75
  npx hyperbundler
82
76
  ```
83
77
 
84
- <details>
85
- <summary>CLI Output</summary>
78
+ ## Config
86
79
 
87
- <br>
88
- <p>Example of CLI Output:</p>
89
-
90
- ```txt
91
- ┌─────────────────┐
92
- ✦✦ HYPERBUNDLER │ v0.11.0
93
- └─────────────────┘
94
- i Config bundler.config.ts
95
- i Bundling started...
96
- * Processing [8:07:26 PM] Transforming files
97
-
98
- ├─ + esm ./dist/index.mjs (50ms) 313 B
99
- ├─ + dts ./dist/types/index.d.ts (1.23s) 13.61 KB
100
- ├─ + esm ./dist/bin/index.mjs (119ms) 16.53 KB
101
-
102
- * Succeeded [8:07:28 PM] Module transformation is done
103
- ✔ Bundling fully completed in 1.40s
104
- ✔ 3 modules transformed. Total size is 30.45 KB
105
- ✦✦ HYPERBUNDLER [8:07:28 PM] Bundle is generated and ready for production
80
+ `Hyperbundler` automatically detects custom configuration from the project root that can override or extend the build behavior.
81
+
82
+ Configuration file also accepts `.js`, `.mjs`, `.ts`, `.mts` formats.
83
+
84
+ ```ts
85
+ // bundler.config.{js,mjs,ts,mts}
86
+
87
+ import { defineConfig } from '@hypernym/bundler'
88
+
89
+ export default defineConfig({
90
+ // ...
91
+ })
106
92
  ```
107
93
 
108
- </details>
94
+ ### Custom path
95
+
96
+ Set a custom config path via the CLI command:
97
+
98
+ ```sh
99
+ npx hyperbundler --config hyper.config.ts
100
+ ```
109
101
 
110
102
  ## Options
111
103
 
112
- All options are documented with descriptions and examples, and auto-completion will be offered as you type.
104
+ All options are documented with descriptions and examples so auto-completion will be offered as you type.
113
105
 
114
106
  Simply hover over the property and see what it does in the `quickinfo`.
115
107
 
@@ -294,6 +286,36 @@ Now imports can be used like this:
294
286
  import { module } from '#/utils' // #
295
287
  ```
296
288
 
289
+ ### minify
290
+
291
+ - Type: `boolean`
292
+ - Default: `undefined`
293
+
294
+ Specifies the minification for all `chunk` entries.
295
+
296
+ ```ts
297
+ // bundler.config.ts
298
+
299
+ import { defineConfig } from '@hypernym/bundler'
300
+
301
+ export default defineConfig({
302
+ minify: true,
303
+ })
304
+ ```
305
+
306
+ It can also be set per entry.
307
+
308
+ ```ts
309
+ export default defineConfig({
310
+ entries: [
311
+ {
312
+ input: './src/index.ts',
313
+ minify: true,
314
+ },
315
+ ],
316
+ })
317
+ ```
318
+
297
319
  ## Hooks
298
320
 
299
321
  List of lifecycle hooks that are called at various phases:
@@ -468,16 +490,6 @@ export default defineConfig({
468
490
  })
469
491
  ```
470
492
 
471
- ## CLI
472
-
473
- ### Custom Config
474
-
475
- Set a custom config path via the CLI command:
476
-
477
- ```sh
478
- npx hyperbundler --config hyper.config.ts
479
- ```
480
-
481
493
  ## Community
482
494
 
483
495
  Feel free to ask questions or share new ideas.
@@ -3,10 +3,10 @@ import process, { cwd } from 'node:process';
3
3
  import { createArgs } from '@hypernym/args';
4
4
  import { resolve, dirname, parse } from 'node:path';
5
5
  import { read, exists, write, copy, readdir } from '@hypernym/utils/fs';
6
- import { dim, cyan, bold, green } from '@hypernym/colors';
6
+ import { dim, cyan } from '@hypernym/colors';
7
7
  import { build as build$1, transform } from 'esbuild';
8
8
  import { stat } from 'node:fs/promises';
9
- import { isString, isObject } from '@hypernym/utils';
9
+ import { isString, isUndefined, isObject } from '@hypernym/utils';
10
10
  import { rollup } from 'rollup';
11
11
  import { getLogFilter } from 'rollup/getLogFilter';
12
12
  import replacePlugin from '@rollup/plugin-replace';
@@ -25,24 +25,23 @@ const externals = [
25
25
  ];
26
26
 
27
27
  const logo = `\u2726\u2726`;
28
- const name$1 = "hyperbundler";
29
- const logoname = `${logo} ${name$1}`;
30
- const version = `0.12.0`;
28
+ const version = `0.13.1`;
31
29
 
32
- const name = logoname.toUpperCase();
33
30
  const cl = console.log;
31
+ const separator = `/`;
34
32
  const logger = {
35
33
  info: (...args) => {
36
- const time = (/* @__PURE__ */ new Date()).toLocaleTimeString();
37
- return cl(name, dim(`[${time}]`), ...args);
34
+ cl(logo, dim(separator), ...args);
38
35
  },
39
36
  error: (...args) => {
40
- const time = (/* @__PURE__ */ new Date()).toLocaleTimeString();
41
- return cl(name, dim(`[${time}]`), ...args);
37
+ cl();
38
+ cl(logo, dim(separator), ...args);
39
+ cl();
42
40
  },
43
41
  exit: (message) => {
44
- const time = (/* @__PURE__ */ new Date()).toLocaleTimeString();
45
- cl(name, dim(`[${time}]`), message);
42
+ cl();
43
+ cl(logo, dim(separator), message);
44
+ cl();
46
45
  return process.exit();
47
46
  }
48
47
  };
@@ -87,6 +86,28 @@ function getOutputPath(outDir, input, types = false) {
87
86
  return `./${output}`;
88
87
  }
89
88
 
89
+ function getLongestOutput(outDir, entries) {
90
+ const outputs = [];
91
+ for (const entry of entries) {
92
+ if ("copy" in entry && entry.copy) {
93
+ const out = entry.copy.output;
94
+ outputs.push(out);
95
+ }
96
+ if ("input" in entry && entry.input) {
97
+ const out = entry.output || getOutputPath(outDir, entry.input);
98
+ outputs.push(out);
99
+ }
100
+ if ("declaration" in entry && entry.declaration) {
101
+ const out = entry.output || getOutputPath(outDir, entry.declaration, true);
102
+ outputs.push(out);
103
+ }
104
+ if ("template" in entry && entry.template) {
105
+ outputs.push(entry.output);
106
+ }
107
+ }
108
+ return Math.max(...outputs.map((v) => v.length));
109
+ }
110
+
90
111
  async function loadConfig(cwd, filePath, defaults) {
91
112
  const result = await build$1({
92
113
  entryPoints: [resolve(cwd, filePath)],
@@ -186,7 +207,7 @@ function esbuild(options) {
186
207
  };
187
208
  }
188
209
 
189
- function logModuleStats(file) {
210
+ function logModuleStats(file, longestOutput) {
190
211
  const cl = console.log;
191
212
  const base = parse(file.path).base;
192
213
  const path = file.path.replace(base, "");
@@ -194,16 +215,30 @@ function logModuleStats(file) {
194
215
  if (format.includes("system")) format = "sys";
195
216
  if (format === "commonjs") format = "cjs";
196
217
  if (format === "module") format = "esm";
218
+ longestOutput = longestOutput + 2;
219
+ const ansiCode = 9;
220
+ const pathDim = dim(path);
221
+ const output = pathDim + base;
222
+ const pathDimNoAnsi = pathDim.length - ansiCode;
223
+ const difference = longestOutput - pathDimNoAnsi - base.length;
224
+ const padLength = output.length + difference;
197
225
  cl(
198
- dim("\u251C\u2500"),
199
- `+ ${format}`,
200
- dim(path) + base,
201
- dim(`(${formatMs(file.buildTime)})`),
226
+ dim("+"),
227
+ format.padEnd(5),
228
+ output.padEnd(padLength),
229
+ dim("time"),
230
+ formatMs(file.buildTime).padEnd(7),
231
+ dim("size"),
202
232
  formatBytes(file.size)
203
233
  );
204
234
  if (file.logs) {
205
235
  for (const log of file.logs) {
206
- cl(dim("\u251C\u2500"), `! ${log.level}`, dim(path) + base, dim(log.log.message));
236
+ cl(
237
+ dim("!"),
238
+ log.level.padEnd(5),
239
+ output.padEnd(padLength),
240
+ dim(log.log.message)
241
+ );
207
242
  }
208
243
  }
209
244
  }
@@ -218,6 +253,7 @@ async function build(cwd, options) {
218
253
  };
219
254
  await hooks?.["build:start"]?.(options, buildStats);
220
255
  if (options.entries) {
256
+ const longestOutput = getLongestOutput(outDir, options.entries);
221
257
  start = Date.now();
222
258
  const aliasDir = resolve(cwd, "./src");
223
259
  let aliasOptions = {
@@ -273,7 +309,7 @@ async function build(cwd, options) {
273
309
  };
274
310
  buildStats.files.push(fileStats);
275
311
  buildStats.size = buildStats.size + stats.size;
276
- logModuleStats(fileStats);
312
+ logModuleStats(fileStats, longestOutput);
277
313
  }
278
314
  }
279
315
  if (entry.input) {
@@ -288,7 +324,12 @@ async function build(cwd, options) {
288
324
  externals: entry.externals || options.externals,
289
325
  format: entry.format || _format,
290
326
  transformers: entry.transformers,
291
- defaultPlugins: [esbuild(entry.transformers?.esbuild)],
327
+ defaultPlugins: [
328
+ esbuild({
329
+ minify: !isUndefined(entry.minify) ? entry.minify : options.minify,
330
+ ...entry.transformers?.esbuild
331
+ })
332
+ ],
292
333
  plugins: entry.plugins,
293
334
  banner: entry.banner,
294
335
  footer: entry.footer,
@@ -351,7 +392,7 @@ async function build(cwd, options) {
351
392
  };
352
393
  buildStats.files.push(file);
353
394
  buildStats.size = buildStats.size + stats.size;
354
- logModuleStats(file);
395
+ logModuleStats(file, longestOutput);
355
396
  await hooks?.["build:entry:end"]?.(_entry, buildStats);
356
397
  }
357
398
  if (entry.declaration) {
@@ -407,7 +448,7 @@ async function build(cwd, options) {
407
448
  };
408
449
  buildStats.files.push(fileStats);
409
450
  buildStats.size = buildStats.size + stats.size;
410
- logModuleStats(fileStats);
451
+ logModuleStats(fileStats, longestOutput);
411
452
  await hooks?.["build:entry:end"]?.(_entry, buildStats);
412
453
  }
413
454
  if (entry.template && entry.output) {
@@ -427,7 +468,7 @@ async function build(cwd, options) {
427
468
  };
428
469
  buildStats.files.push(fileStats);
429
470
  buildStats.size = buildStats.size + stats.size;
430
- logModuleStats(fileStats);
471
+ logModuleStats(fileStats, longestOutput);
431
472
  }
432
473
  }
433
474
  buildStats.buildTime = Date.now() - start;
@@ -441,35 +482,28 @@ async function createBuilder(cwd, config) {
441
482
  const { hooks } = options;
442
483
  const cl = console.log;
443
484
  await hooks?.["bundle:start"]?.(options);
444
- const line = "\u2500".repeat(logoname.length + 2);
445
- cl();
446
- cl(dim(`\u250C${line}\u2510`));
447
- cl(dim("\u2502"), `${logoname.toUpperCase()}`, dim("\u2502"), dim(`v${version}`));
448
- cl(dim(`\u2514${line}\u2518`));
449
- cl(dim(bold("i")), "Config", dim(configPath));
450
- cl(dim(bold("i")), "Bundling started...");
485
+ logger.info(dim(`v${version}`));
486
+ cl("Config", dim(configPath));
487
+ cl("Bundling started...");
451
488
  cl(
452
- dim(bold("*")),
453
489
  "Processing",
454
490
  dim(`[${(/* @__PURE__ */ new Date()).toLocaleTimeString()}]`),
455
491
  "Transforming files"
456
492
  );
457
- cl(dim("\u2502"));
493
+ cl();
458
494
  await build(cwd, options).then((stats) => {
459
- const check = green(bold("\u2714"));
460
- const buildTime = green(formatMs(stats.buildTime));
461
- const buildSize = green(formatBytes(stats.size));
495
+ const buildTime = dim(formatMs(stats.buildTime));
496
+ const buildSize = dim(formatBytes(stats.size));
462
497
  const totalModules = stats.files.length;
463
- const modules = totalModules > 1 ? `${green(totalModules)} modules` : `${green(totalModules)} module`;
464
- cl(dim("\u2502"));
498
+ const modules = totalModules > 1 ? `${totalModules} modules` : `${totalModules} module`;
499
+ cl();
465
500
  cl(
466
- dim(bold("*")),
467
501
  "Succeeded",
468
502
  dim(`[${(/* @__PURE__ */ new Date()).toLocaleTimeString()}]`),
469
503
  "Module transformation is done"
470
504
  );
471
- cl(check, `Bundling fully completed in ${buildTime}`);
472
- cl(check, `${modules} transformed. Total size is ${buildSize}`);
505
+ cl(`Bundling fully completed in ${buildTime}`);
506
+ cl(`${modules} transformed. Total size is ${buildSize}`);
473
507
  logger.info(`Bundle is generated and ready for production`);
474
508
  cl();
475
509
  }).catch(error);
@@ -126,6 +126,12 @@ interface EntryChunk extends EntryBase {
126
126
  * Intended for `umd/iife` formats.
127
127
  */
128
128
  extend?: OutputOptions['extend'];
129
+ /**
130
+ * Minifies the generated code if enabled.
131
+ *
132
+ * @default undefined
133
+ */
134
+ minify?: boolean;
129
135
  declaration?: never;
130
136
  copy?: never;
131
137
  template?: never;
@@ -158,6 +164,7 @@ interface EntryDeclaration extends EntryBase {
158
164
  name?: never;
159
165
  globals?: never;
160
166
  extend?: never;
167
+ minify?: never;
161
168
  }
162
169
  interface CopyOptions {
163
170
  /**
@@ -213,6 +220,7 @@ interface EntryCopy {
213
220
  name?: never;
214
221
  globals?: never;
215
222
  extend?: never;
223
+ minify?: never;
216
224
  }
217
225
  interface EntryTemplate {
218
226
  /**
@@ -244,6 +252,7 @@ interface EntryTemplate {
244
252
  name?: never;
245
253
  globals?: never;
246
254
  extend?: never;
255
+ minify?: never;
247
256
  }
248
257
  type EntryOptions = EntryChunk | EntryDeclaration | EntryCopy | EntryTemplate;
249
258
 
@@ -350,6 +359,33 @@ interface Options {
350
359
  * @default undefined
351
360
  */
352
361
  alias?: Alias[];
362
+ /**
363
+ * Specifies the minification for all `chunk` entries.
364
+ *
365
+ * @example
366
+ *
367
+ * ```ts
368
+ * export default defineConfig({
369
+ * minify: true,
370
+ * })
371
+ * ```
372
+ *
373
+ * It can also be set per entry.
374
+ *
375
+ * ```ts
376
+ * export default defineConfig({
377
+ * entries: [
378
+ * {
379
+ * input: './src/index.ts',
380
+ * minify: true,
381
+ * },
382
+ * ],
383
+ * })
384
+ * ```
385
+ *
386
+ * @default undefined
387
+ */
388
+ minify?: boolean;
353
389
  }
354
390
 
355
391
  interface BuildLogs {
@@ -545,6 +581,21 @@ interface ConfigLoader {
545
581
  * ```
546
582
  */
547
583
  declare const externals: RegExp[];
584
+ /**
585
+ * `Hyperbundler` automatically detects custom configuration from the project root that can override or extend the build behavior.
586
+ *
587
+ * Configuration file also accepts `.js`, `.mjs`, `.ts`, `.mts` formats.
588
+ *
589
+ * @example
590
+ *
591
+ * ```ts
592
+ * import { defineConfig } from '@hypernym/bundler'
593
+ *
594
+ * export default defineConfig({
595
+ * // ...
596
+ * })
597
+ * ```
598
+ */
548
599
  declare function defineConfig(options: Options): Options;
549
600
 
550
601
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hypernym/bundler",
3
- "version": "0.12.0",
3
+ "version": "0.13.1",
4
4
  "author": "Hypernym Studio",
5
5
  "description": "ESM & TS module bundler.",
6
6
  "license": "MIT",
@@ -20,14 +20,13 @@
20
20
  ],
21
21
  "keywords": [
22
22
  "module",
23
- "modules",
24
23
  "bundling",
25
24
  "javascript",
26
25
  "typescript",
27
26
  "hyperbundler",
27
+ "declarations",
28
28
  "bundler",
29
29
  "builder",
30
- "package",
31
30
  "bundle",
32
31
  "types",
33
32
  "build",
@@ -66,13 +65,13 @@
66
65
  "@hypernym/args": "^0.3.0",
67
66
  "@hypernym/colors": "^1.0.1",
68
67
  "@hypernym/utils": "^3.4.0",
69
- "@rollup/plugin-alias": "^5.1.0",
68
+ "@rollup/plugin-alias": "^5.1.1",
70
69
  "@rollup/plugin-json": "^6.1.0",
71
- "@rollup/plugin-node-resolve": "^15.2.3",
70
+ "@rollup/plugin-node-resolve": "^15.2.4",
72
71
  "@rollup/plugin-replace": "^5.0.7",
73
- "@rollup/pluginutils": "^5.1.0",
74
- "esbuild": "^0.23.1",
75
- "rollup": "^4.22.2",
72
+ "@rollup/pluginutils": "^5.1.1",
73
+ "esbuild": "^0.24.0",
74
+ "rollup": "^4.22.4",
76
75
  "rollup-plugin-dts": "^6.1.1"
77
76
  },
78
77
  "devDependencies": {
@@ -80,7 +79,7 @@
80
79
  "@hypernym/prettier-config": "^3.2.0",
81
80
  "@hypernym/tsconfig": "^2.4.0",
82
81
  "@types/node": "^22.5.5",
83
- "eslint": "^9.10.0",
82
+ "eslint": "^9.11.0",
84
83
  "prettier": "^3.3.3",
85
84
  "typescript": "^5.5.4"
86
85
  }