@hypernym/bundler 0.13.0 → 0.14.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/README.md CHANGED
@@ -58,7 +58,7 @@ import { defineConfig } from '@hypernym/bundler'
58
58
  export default defineConfig({
59
59
  entries: [
60
60
  { input: './src/index.ts' },
61
- { declaration: './src/types/index.ts' },
61
+ { dts: './src/types/index.ts' },
62
62
  {
63
63
  input: './src/utils/index.ts',
64
64
  output: './dist/utils/utils.min.mjs',
@@ -99,11 +99,34 @@ Set a custom config path via the CLI command:
99
99
  npx hyperbundler --config hyper.config.ts
100
100
  ```
101
101
 
102
- ## Options
102
+ ## Formats
103
+
104
+ During transformation, file formats are automatically resolved and in most cases there is no need for additional configuration.
105
+
106
+ `Hyperbundler` module environment for generated files defaults to `esm`, which means the outputs will have a `.mjs` extension unless otherwise specified. For TypeScript declarations, the appropriate extension will be `.d.mts`.
107
+
108
+ Formats can also be explicitly specified for each entry, if necessary.
109
+
110
+ ### Inputs
111
+
112
+ Default transformation behaviour for all `chunk` entries:
113
+
114
+ - `./srcDir/file.js` resolves to `./outDir/file.mjs`
115
+ - `./srcDir/file.mjs` resolves to `./outDir/file.mjs`
116
+ - `./srcDir/file.cjs` resolves to `./outDir/file.cjs`
117
+ - `./srcDir/file.ts` resolves to `./outDir/file.mjs`
118
+ - `./srcDir/file.mts` resolves to `./outDir/file.mjs`
119
+ - `./srcDir/file.cts` resolves to `./outDir/file.cjs`
103
120
 
104
- All options are documented with descriptions and examples so auto-completion will be offered as you type.
121
+ ### Declarations
105
122
 
106
- Simply hover over the property and see what it does in the `quickinfo`.
123
+ Default transformation behaviour for all `dts` entries:
124
+
125
+ - `./srcDir/file.ts` resolves to `./outDir/file.d.mts`
126
+
127
+ ## Options
128
+
129
+ All options are documented with descriptions and examples so auto-completion will be offered as you type. Simply hover over the property and see what it does in the `quickinfo`.
107
130
 
108
131
  ### entries
109
132
 
@@ -121,7 +144,7 @@ import { defineConfig } from '@hypernym/bundler'
121
144
  export default defineConfig({
122
145
  entries: [
123
146
  { input: './src/index.ts' }, // => './dist/index.mjs'
124
- { declaration: './src/types.ts' }, // => './dist/types.d.ts'
147
+ { dts: './src/types.ts' }, // => './dist/types.d.mts'
125
148
  // ...
126
149
  ],
127
150
  })
@@ -140,9 +163,7 @@ import { defineConfig } from '@hypernym/bundler'
140
163
 
141
164
  export default defineConfig({
142
165
  entries: [
143
- {
144
- input: './src/index.ts', // => './dist/index.mjs'
145
- },
166
+ { input: './src/index.ts' }, // => './dist/index.mjs'
146
167
  ],
147
168
  })
148
169
  ```
@@ -160,9 +181,19 @@ import { defineConfig } from '@hypernym/bundler'
160
181
 
161
182
  export default defineConfig({
162
183
  entries: [
163
- {
164
- { declaration: './src/types.ts' }, // => './dist/types.d.ts'
165
- },
184
+ { declaration: './src/types.ts' }, // => './dist/types.d.mts'
185
+ ],
186
+ })
187
+ ```
188
+
189
+ Also, it is possible to use `dts` alias.
190
+
191
+ ```ts
192
+ import { defineConfig } from '@hypernym/bundler'
193
+
194
+ export default defineConfig({
195
+ entries: [
196
+ { dts: './src/types.ts' }, // => './dist/types.d.mts'
166
197
  ],
167
198
  })
168
199
  ```
@@ -373,7 +404,7 @@ export default defineConfig({
373
404
 
374
405
  ### build:entry:start
375
406
 
376
- - Type: `(options: BuildEntryOptions, stats: BuildStats) => void | Promise<void>`
407
+ - Type: `(entry: BuildEntryOptions, stats: BuildEntryStats) => void | Promise<void>`
377
408
  - Default: `undefined`
378
409
 
379
410
  Called on each entry just before the build process.
@@ -388,12 +419,12 @@ import { plugin1, plugin2 } from './src/utils/plugins.js'
388
419
 
389
420
  export default defineConfig({
390
421
  hooks: {
391
- 'build:entry:start': async (options, stats) => {
422
+ 'build:entry:start': async (entry, stats) => {
392
423
  // adds custom plugins for a specific entry only
393
- if (options.input?.includes('./src/index.ts')) {
394
- options.defaultPlugins = [
424
+ if (entry.input?.includes('./src/index.ts')) {
425
+ entry.defaultPlugins = [
395
426
  plugin1(), // adds a custom plugin before the default bundler plugins
396
- ...options.defaultPlugins, // list of default bundler plugins
427
+ ...entry.defaultPlugins, // list of default bundler plugins
397
428
  plugin2(), // adds a custom plugin after the default bundler plugins
398
429
  ]
399
430
  }
@@ -404,7 +435,7 @@ export default defineConfig({
404
435
 
405
436
  ### build:entry:end
406
437
 
407
- - Type: `(options: BuildEntryOptions, stats: BuildStats) => void | Promise<void>`
438
+ - Type: `(entry: BuildEntryOptions, stats: BuildEntryStats) => void | Promise<void>`
408
439
  - Default: `undefined`
409
440
 
410
441
  Called on each entry right after the build process is completed.
@@ -416,7 +447,7 @@ import { defineConfig } from '@hypernym/bundler'
416
447
 
417
448
  export default defineConfig({
418
449
  hooks: {
419
- 'build:entry:end': async (options, stats) => {
450
+ 'build:entry:end': async (entry, stats) => {
420
451
  // ...
421
452
  },
422
453
  },
@@ -3,7 +3,7 @@ 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
9
  import { isString, isUndefined, isObject } from '@hypernym/utils';
@@ -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.13.0`;
28
+ const version = `0.14.0`;
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
  };
@@ -74,17 +73,35 @@ function formatBytes(bytes) {
74
73
  return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${units[i]}`;
75
74
  }
76
75
 
77
- function getOutputPath(outDir, input, types = false) {
76
+ function getOutputPath(outDir, input, dts) {
78
77
  const _input = input.startsWith("./") ? input.slice(2) : input;
79
78
  let output = _input.replace(_input.split("/")[0], outDir);
80
- const ts = types ? "d.ts" : "mjs";
81
- const mts = types ? "d.mts" : "mjs";
82
- const cts = types ? "d.cts" : "cjs";
83
- if (output.endsWith(".ts")) output = `${output.slice(0, -2)}${ts}`;
84
- if (output.endsWith(".mts")) output = `${output.slice(0, -3)}${mts}`;
85
- if (output.endsWith(".cts")) output = `${output.slice(0, -3)}${cts}`;
79
+ const ext = dts ? "d.mts" : "mjs";
80
+ const cts = dts ? "d.cts" : "cjs";
81
+ if (output.endsWith(".js")) output = `${output.slice(0, -2)}${ext}`;
82
+ else if (output.endsWith(".ts")) output = `${output.slice(0, -2)}${ext}`;
83
+ else if (output.endsWith(".mts")) output = `${output.slice(0, -3)}${ext}`;
84
+ else if (output.endsWith(".cts")) output = `${output.slice(0, -3)}${cts}`;
86
85
  if (outDir.startsWith("./") || outDir.startsWith("../")) return output;
87
- return `./${output}`;
86
+ else return `./${output}`;
87
+ }
88
+
89
+ function getLongestOutput(outDir, entries) {
90
+ const outputs = [];
91
+ for (const entry of entries) {
92
+ if (entry.copy) outputs.push(entry.copy.output);
93
+ if (entry.input) {
94
+ const out = entry.output || getOutputPath(outDir, entry.input);
95
+ outputs.push(out);
96
+ }
97
+ if (entry.declaration || entry.dts) {
98
+ const dts = entry.declaration || entry.dts;
99
+ const out = entry.output || getOutputPath(outDir, dts, true);
100
+ outputs.push(out);
101
+ }
102
+ if (entry.template) outputs.push(entry.output);
103
+ }
104
+ return Math.max(...outputs.map((v) => v.length));
88
105
  }
89
106
 
90
107
  async function loadConfig(cwd, filePath, defaults) {
@@ -186,7 +203,7 @@ function esbuild(options) {
186
203
  };
187
204
  }
188
205
 
189
- function logModuleStats(file) {
206
+ function logModuleStats(file, longestOutput) {
190
207
  const cl = console.log;
191
208
  const base = parse(file.path).base;
192
209
  const path = file.path.replace(base, "");
@@ -194,16 +211,30 @@ function logModuleStats(file) {
194
211
  if (format.includes("system")) format = "sys";
195
212
  if (format === "commonjs") format = "cjs";
196
213
  if (format === "module") format = "esm";
214
+ longestOutput = longestOutput + 2;
215
+ const ansiCode = 9;
216
+ const pathDim = dim(path);
217
+ const output = pathDim + base;
218
+ const pathDimNoAnsi = pathDim.length - ansiCode;
219
+ const difference = longestOutput - pathDimNoAnsi - base.length;
220
+ const padLength = output.length + difference;
197
221
  cl(
198
- dim("\u251C\u2500"),
199
- `+ ${format}`,
200
- dim(path) + base,
201
- dim(`(${formatMs(file.buildTime)})`),
222
+ dim("+"),
223
+ format.padEnd(5),
224
+ output.padEnd(padLength),
225
+ dim("time"),
226
+ formatMs(file.buildTime).padEnd(7),
227
+ dim("size"),
202
228
  formatBytes(file.size)
203
229
  );
204
230
  if (file.logs) {
205
231
  for (const log of file.logs) {
206
- cl(dim("\u251C\u2500"), `! ${log.level}`, dim(path) + base, dim(log.log.message));
232
+ cl(
233
+ dim("!"),
234
+ log.level.padEnd(5),
235
+ output.padEnd(padLength),
236
+ dim(log.log.message)
237
+ );
207
238
  }
208
239
  }
209
240
  }
@@ -218,6 +249,7 @@ async function build(cwd, options) {
218
249
  };
219
250
  await hooks?.["build:start"]?.(options, buildStats);
220
251
  if (options.entries) {
252
+ const longestOutput = getLongestOutput(outDir, options.entries);
221
253
  start = Date.now();
222
254
  const aliasDir = resolve(cwd, "./src");
223
255
  let aliasOptions = {
@@ -265,6 +297,7 @@ async function build(cwd, options) {
265
297
  else return `./${path}`;
266
298
  };
267
299
  const fileStats = {
300
+ cwd,
268
301
  path: `${parseOutput(_entry.output)}/${parseInput(copyInput)}`,
269
302
  size: totalSize,
270
303
  buildTime: Date.now() - entryStart,
@@ -273,36 +306,27 @@ async function build(cwd, options) {
273
306
  };
274
307
  buildStats.files.push(fileStats);
275
308
  buildStats.size = buildStats.size + stats.size;
276
- logModuleStats(fileStats);
309
+ logModuleStats(fileStats, longestOutput);
277
310
  }
278
311
  }
279
312
  if (entry.input) {
280
313
  const logFilter = getLogFilter(entry.logFilter || []);
281
- const _output = getOutputPath(outDir, entry.input);
314
+ const _output = entry.output || getOutputPath(outDir, entry.input);
282
315
  let _format = "esm";
283
316
  if (_output.endsWith(".cjs")) _format = "cjs";
284
317
  const buildLogs = [];
285
318
  const _entry = {
286
319
  input: entry.input,
287
- output: entry.output || _output,
320
+ output: _output,
288
321
  externals: entry.externals || options.externals,
289
322
  format: entry.format || _format,
290
- transformers: entry.transformers,
323
+ ...entry,
291
324
  defaultPlugins: [
292
325
  esbuild({
293
326
  minify: !isUndefined(entry.minify) ? entry.minify : options.minify,
294
327
  ...entry.transformers?.esbuild
295
328
  })
296
- ],
297
- plugins: entry.plugins,
298
- banner: entry.banner,
299
- footer: entry.footer,
300
- intro: entry.intro,
301
- outro: entry.outro,
302
- paths: entry.paths,
303
- name: entry.name,
304
- globals: entry.globals,
305
- extend: entry.extend
329
+ ]
306
330
  };
307
331
  if (!entry.plugins) {
308
332
  if (_entry.transformers?.json) {
@@ -312,7 +336,7 @@ async function build(cwd, options) {
312
336
  if (_entry.transformers?.replace) {
313
337
  _entry.defaultPlugins.unshift(
314
338
  replacePlugin({
315
- true: true,
339
+ preventAssignment: true,
316
340
  ..._entry.transformers.replace
317
341
  })
318
342
  );
@@ -325,7 +349,15 @@ async function build(cwd, options) {
325
349
  aliasPlugin(_entry.transformers?.alias || aliasOptions)
326
350
  );
327
351
  }
328
- await hooks?.["build:entry:start"]?.(_entry, buildStats);
352
+ const fileStats = {
353
+ cwd,
354
+ path: _entry.output,
355
+ size: 0,
356
+ buildTime: entryStart,
357
+ format: _entry.format,
358
+ logs: buildLogs
359
+ };
360
+ await hooks?.["build:entry:start"]?.(_entry, fileStats);
329
361
  const _build = await rollup({
330
362
  input: resolve(cwd, _entry.input),
331
363
  external: _entry.externals,
@@ -347,46 +379,42 @@ async function build(cwd, options) {
347
379
  extend: _entry.extend
348
380
  });
349
381
  const stats = await stat(resolve(cwd, _entry.output));
350
- const file = {
351
- path: _entry.output,
352
- size: stats.size,
353
- buildTime: Date.now() - entryStart,
354
- format: _entry.format,
355
- logs: buildLogs
356
- };
357
- buildStats.files.push(file);
382
+ fileStats.size = stats.size;
383
+ fileStats.buildTime = Date.now() - entryStart;
384
+ fileStats.logs = buildLogs;
385
+ buildStats.files.push(fileStats);
358
386
  buildStats.size = buildStats.size + stats.size;
359
- logModuleStats(file);
360
- await hooks?.["build:entry:end"]?.(_entry, buildStats);
387
+ logModuleStats(fileStats, longestOutput);
388
+ await hooks?.["build:entry:end"]?.(_entry, fileStats);
361
389
  }
362
- if (entry.declaration) {
390
+ if (entry.dts || entry.declaration) {
363
391
  const logFilter = getLogFilter(entry.logFilter || []);
364
- const _output = getOutputPath(outDir, entry.declaration, true);
365
- let _format = "esm";
366
- if (_output.endsWith(".d.cts")) _format = "cjs";
367
392
  const buildLogs = [];
393
+ const dts$1 = entry.dts || entry.declaration;
368
394
  const _entry = {
369
- input: entry.declaration,
370
- output: entry.output || _output,
395
+ dts: dts$1,
396
+ output: entry.output || getOutputPath(outDir, dts$1, true),
371
397
  externals: entry.externals || options.externals,
372
- format: entry.format || _format,
373
- transformers: entry.transformers,
374
- defaultPlugins: [dts(entry.transformers?.dts)],
375
- plugins: entry.plugins,
376
- banner: entry.banner,
377
- footer: entry.footer,
378
- intro: entry.intro,
379
- outro: entry.outro,
380
- paths: entry.paths
398
+ format: entry.format || "esm",
399
+ ...entry,
400
+ defaultPlugins: [dts(entry.transformers?.dts)]
381
401
  };
382
402
  if (!entry.plugins) {
383
403
  _entry.defaultPlugins.unshift(
384
404
  aliasPlugin(_entry.transformers?.alias || aliasOptions)
385
405
  );
386
406
  }
387
- await hooks?.["build:entry:start"]?.(_entry, buildStats);
407
+ const fileStats = {
408
+ cwd,
409
+ path: _entry.output,
410
+ size: 0,
411
+ buildTime: entryStart,
412
+ format: "dts",
413
+ logs: buildLogs
414
+ };
415
+ await hooks?.["build:entry:start"]?.(_entry, fileStats);
388
416
  const _build = await rollup({
389
- input: resolve(cwd, _entry.input),
417
+ input: resolve(cwd, _entry.dts),
390
418
  external: _entry.externals,
391
419
  plugins: _entry.plugins || _entry.defaultPlugins,
392
420
  onLog: (level, log) => {
@@ -403,28 +431,21 @@ async function build(cwd, options) {
403
431
  paths: _entry.paths
404
432
  });
405
433
  const stats = await stat(resolve(cwd, _entry.output));
406
- const fileStats = {
407
- path: _entry.output,
408
- size: stats.size,
409
- buildTime: Date.now() - entryStart,
410
- format: "dts",
411
- logs: buildLogs
412
- };
434
+ fileStats.size = stats.size;
435
+ fileStats.buildTime = Date.now() - entryStart;
436
+ fileStats.logs = buildLogs;
413
437
  buildStats.files.push(fileStats);
414
438
  buildStats.size = buildStats.size + stats.size;
415
- logModuleStats(fileStats);
416
- await hooks?.["build:entry:end"]?.(_entry, buildStats);
439
+ logModuleStats(fileStats, longestOutput);
440
+ await hooks?.["build:entry:end"]?.(_entry, fileStats);
417
441
  }
418
442
  if (entry.template && entry.output) {
419
443
  const buildLogs = [];
420
- const _entry = {
421
- template: entry.template,
422
- output: entry.output
423
- };
424
- await write(_entry.output, _entry.template);
425
- const stats = await stat(resolve(cwd, _entry.output));
444
+ await write(entry.output, entry.template);
445
+ const stats = await stat(resolve(cwd, entry.output));
426
446
  const fileStats = {
427
- path: _entry.output,
447
+ cwd,
448
+ path: entry.output,
428
449
  size: stats.size,
429
450
  buildTime: Date.now() - entryStart,
430
451
  format: "tmp",
@@ -432,7 +453,7 @@ async function build(cwd, options) {
432
453
  };
433
454
  buildStats.files.push(fileStats);
434
455
  buildStats.size = buildStats.size + stats.size;
435
- logModuleStats(fileStats);
456
+ logModuleStats(fileStats, longestOutput);
436
457
  }
437
458
  }
438
459
  buildStats.buildTime = Date.now() - start;
@@ -446,35 +467,28 @@ async function createBuilder(cwd, config) {
446
467
  const { hooks } = options;
447
468
  const cl = console.log;
448
469
  await hooks?.["bundle:start"]?.(options);
449
- const line = "\u2500".repeat(logoname.length + 2);
450
- cl();
451
- cl(dim(`\u250C${line}\u2510`));
452
- cl(dim("\u2502"), `${logoname.toUpperCase()}`, dim("\u2502"), dim(`v${version}`));
453
- cl(dim(`\u2514${line}\u2518`));
454
- cl(dim(bold("i")), "Config", dim(configPath));
455
- cl(dim(bold("i")), "Bundling started...");
470
+ logger.info(dim(`v${version}`));
471
+ cl("Config", dim(configPath));
472
+ cl("Bundling started...");
456
473
  cl(
457
- dim(bold("*")),
458
474
  "Processing",
459
475
  dim(`[${(/* @__PURE__ */ new Date()).toLocaleTimeString()}]`),
460
476
  "Transforming files"
461
477
  );
462
- cl(dim("\u2502"));
478
+ cl();
463
479
  await build(cwd, options).then((stats) => {
464
- const check = green(bold("\u2714"));
465
- const buildTime = green(formatMs(stats.buildTime));
466
- const buildSize = green(formatBytes(stats.size));
480
+ const buildTime = dim(formatMs(stats.buildTime));
481
+ const buildSize = dim(formatBytes(stats.size));
467
482
  const totalModules = stats.files.length;
468
- const modules = totalModules > 1 ? `${green(totalModules)} modules` : `${green(totalModules)} module`;
469
- cl(dim("\u2502"));
483
+ const modules = totalModules > 1 ? `${totalModules} modules` : `${totalModules} module`;
484
+ cl();
470
485
  cl(
471
- dim(bold("*")),
472
486
  "Succeeded",
473
487
  dim(`[${(/* @__PURE__ */ new Date()).toLocaleTimeString()}]`),
474
488
  "Module transformation is done"
475
489
  );
476
- cl(check, `Bundling fully completed in ${buildTime}`);
477
- cl(check, `${modules} transformed. Total size is ${buildSize}`);
490
+ cl(`Bundling fully completed in ${buildTime}`);
491
+ cl(`${modules} transformed. Total size is ${buildSize}`);
478
492
  logger.info(`Bundle is generated and ready for production`);
479
493
  cl();
480
494
  }).catch(error);
package/dist/index.cjs ADDED
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+
3
+ const externals = [
4
+ /^node:/,
5
+ /^@types/,
6
+ /^@rollup/,
7
+ /^@hypernym/,
8
+ /^rollup/
9
+ ];
10
+ function defineConfig(options) {
11
+ return options;
12
+ }
13
+
14
+ function resolvePaths(options) {
15
+ return (id) => {
16
+ for (const resolver of options) {
17
+ const { find, replacement } = resolver;
18
+ if (id.match(find)) id = replacement;
19
+ }
20
+ return id;
21
+ };
22
+ }
23
+
24
+ exports.defineConfig = defineConfig;
25
+ exports.externals = externals;
26
+ exports.resolvePaths = resolvePaths;