@hypernym/bundler 0.13.1 → 0.14.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/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 Ivo Dolenc, Hypernym Studio
3
+ Copyright (c) 2025 Ivo Dolenc, Hypernym Studio
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,22 +1,20 @@
1
- <h1 align="center">Hyperbundler</h1>
1
+ <h1 align="center">Bundler</h1>
2
2
 
3
3
  <p align="center">ESM & TS module bundler.</p>
4
4
 
5
5
  <p align="center">
6
6
  <a href="https://github.com/hypernym-studio/bundler">Repository</a>
7
- <span>+</span>
7
+ <span>✦</span>
8
8
  <a href="https://www.npmjs.com/package/@hypernym/bundler">Package</a>
9
- <span>+</span>
9
+ <span>✦</span>
10
10
  <a href="https://github.com/hypernym-studio/bundler/releases">Releases</a>
11
- <span>+</span>
11
+ <span>✦</span>
12
12
  <a href="https://github.com/hypernym-studio/bundler/discussions">Discussions</a>
13
13
  </p>
14
14
 
15
- <pre align="center">pnpm add -D @hypernym/bundler</pre>
15
+ <br>
16
16
 
17
- <p align="center">
18
- <strong>Hypernym Studio</strong>
19
- </p>
17
+ <pre align="center">pnpm add -D @hypernym/bundler</pre>
20
18
 
21
19
  <br>
22
20
 
@@ -24,13 +22,13 @@
24
22
 
25
23
  - Powered by Rollup
26
24
  - Written in TypeScript
27
- - Allows advanced customization
28
- - Provides a powerful hooking system
29
- - Supports all TS module resolutions
30
- - Exports fully optimized code
31
- - Follows modern practice
32
- - Super easy to use
33
- - API friendly
25
+ - Allows Advanced Customization
26
+ - Provides a Powerful Hooking System
27
+ - Supports All TS Module Resolutions
28
+ - Exports Fully Optimized Code
29
+ - Follows Modern Practice
30
+ - Super Easy to Use
31
+ - API-Friendly
34
32
 
35
33
  ## Quick Start
36
34
 
@@ -58,7 +56,7 @@ import { defineConfig } from '@hypernym/bundler'
58
56
  export default defineConfig({
59
57
  entries: [
60
58
  { input: './src/index.ts' },
61
- { declaration: './src/types/index.ts' },
59
+ { dts: './src/types/index.ts' },
62
60
  {
63
61
  input: './src/utils/index.ts',
64
62
  output: './dist/utils/utils.min.mjs',
@@ -99,11 +97,34 @@ Set a custom config path via the CLI command:
99
97
  npx hyperbundler --config hyper.config.ts
100
98
  ```
101
99
 
102
- ## Options
100
+ ## Formats
101
+
102
+ During transformation, file formats are automatically resolved and in most cases there is no need for additional configuration.
103
+
104
+ `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`.
103
105
 
104
- All options are documented with descriptions and examples so auto-completion will be offered as you type.
106
+ Formats can also be explicitly specified for each entry, if necessary.
107
+
108
+ ### Inputs
109
+
110
+ Default transformation behaviour for all `chunk` entries:
111
+
112
+ - `./srcDir/file.js` resolves to `./outDir/file.mjs`
113
+ - `./srcDir/file.mjs` resolves to `./outDir/file.mjs`
114
+ - `./srcDir/file.cjs` resolves to `./outDir/file.cjs`
115
+ - `./srcDir/file.ts` resolves to `./outDir/file.mjs`
116
+ - `./srcDir/file.mts` resolves to `./outDir/file.mjs`
117
+ - `./srcDir/file.cts` resolves to `./outDir/file.cjs`
118
+
119
+ ### Declarations
120
+
121
+ Default transformation behaviour for all `dts` entries:
122
+
123
+ - `./srcDir/file.ts` resolves to `./outDir/file.d.mts`
124
+
125
+ ## Options
105
126
 
106
- Simply hover over the property and see what it does in the `quickinfo`.
127
+ 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
128
 
108
129
  ### entries
109
130
 
@@ -121,7 +142,7 @@ import { defineConfig } from '@hypernym/bundler'
121
142
  export default defineConfig({
122
143
  entries: [
123
144
  { input: './src/index.ts' }, // => './dist/index.mjs'
124
- { declaration: './src/types.ts' }, // => './dist/types.d.ts'
145
+ { dts: './src/types.ts' }, // => './dist/types.d.mts'
125
146
  // ...
126
147
  ],
127
148
  })
@@ -140,9 +161,7 @@ import { defineConfig } from '@hypernym/bundler'
140
161
 
141
162
  export default defineConfig({
142
163
  entries: [
143
- {
144
- input: './src/index.ts', // => './dist/index.mjs'
145
- },
164
+ { input: './src/index.ts' }, // => './dist/index.mjs'
146
165
  ],
147
166
  })
148
167
  ```
@@ -160,9 +179,19 @@ import { defineConfig } from '@hypernym/bundler'
160
179
 
161
180
  export default defineConfig({
162
181
  entries: [
163
- {
164
- { declaration: './src/types.ts' }, // => './dist/types.d.ts'
165
- },
182
+ { declaration: './src/types.ts' }, // => './dist/types.d.mts'
183
+ ],
184
+ })
185
+ ```
186
+
187
+ Also, it is possible to use `dts` alias.
188
+
189
+ ```ts
190
+ import { defineConfig } from '@hypernym/bundler'
191
+
192
+ export default defineConfig({
193
+ entries: [
194
+ { dts: './src/types.ts' }, // => './dist/types.d.mts'
166
195
  ],
167
196
  })
168
197
  ```
@@ -373,7 +402,7 @@ export default defineConfig({
373
402
 
374
403
  ### build:entry:start
375
404
 
376
- - Type: `(options: BuildEntryOptions, stats: BuildStats) => void | Promise<void>`
405
+ - Type: `(entry: BuildEntryOptions, stats: BuildEntryStats) => void | Promise<void>`
377
406
  - Default: `undefined`
378
407
 
379
408
  Called on each entry just before the build process.
@@ -388,12 +417,12 @@ import { plugin1, plugin2 } from './src/utils/plugins.js'
388
417
 
389
418
  export default defineConfig({
390
419
  hooks: {
391
- 'build:entry:start': async (options, stats) => {
420
+ 'build:entry:start': async (entry, stats) => {
392
421
  // adds custom plugins for a specific entry only
393
- if (options.input?.includes('./src/index.ts')) {
394
- options.defaultPlugins = [
422
+ if (entry.input?.includes('./src/index.ts')) {
423
+ entry.defaultPlugins = [
395
424
  plugin1(), // adds a custom plugin before the default bundler plugins
396
- ...options.defaultPlugins, // list of default bundler plugins
425
+ ...entry.defaultPlugins, // list of default bundler plugins
397
426
  plugin2(), // adds a custom plugin after the default bundler plugins
398
427
  ]
399
428
  }
@@ -404,7 +433,7 @@ export default defineConfig({
404
433
 
405
434
  ### build:entry:end
406
435
 
407
- - Type: `(options: BuildEntryOptions, stats: BuildStats) => void | Promise<void>`
436
+ - Type: `(entry: BuildEntryOptions, stats: BuildEntryStats) => void | Promise<void>`
408
437
  - Default: `undefined`
409
438
 
410
439
  Called on each entry right after the build process is completed.
@@ -416,7 +445,7 @@ import { defineConfig } from '@hypernym/bundler'
416
445
 
417
446
  export default defineConfig({
418
447
  hooks: {
419
- 'build:entry:end': async (options, stats) => {
448
+ 'build:entry:end': async (entry, stats) => {
420
449
  // ...
421
450
  },
422
451
  },
@@ -24,23 +24,23 @@ const externals = [
24
24
  /^rollup/
25
25
  ];
26
26
 
27
- const logo = `\u2726\u2726`;
28
- const version = `0.13.1`;
27
+ const name = `Hyperbundler`;
28
+ const version = `0.14.1`;
29
29
 
30
30
  const cl = console.log;
31
31
  const separator = `/`;
32
32
  const logger = {
33
33
  info: (...args) => {
34
- cl(logo, dim(separator), ...args);
34
+ cl(name, dim(separator), ...args);
35
35
  },
36
36
  error: (...args) => {
37
37
  cl();
38
- cl(logo, dim(separator), ...args);
38
+ cl(name, dim(separator), ...args);
39
39
  cl();
40
40
  },
41
41
  exit: (message) => {
42
42
  cl();
43
- cl(logo, dim(separator), message);
43
+ cl(name, dim(separator), message);
44
44
  cl();
45
45
  return process.exit();
46
46
  }
@@ -73,37 +73,33 @@ function formatBytes(bytes) {
73
73
  return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${units[i]}`;
74
74
  }
75
75
 
76
- function getOutputPath(outDir, input, types = false) {
76
+ function getOutputPath(outDir, input, dts) {
77
77
  const _input = input.startsWith("./") ? input.slice(2) : input;
78
78
  let output = _input.replace(_input.split("/")[0], outDir);
79
- const ts = types ? "d.ts" : "mjs";
80
- const mts = types ? "d.mts" : "mjs";
81
- const cts = types ? "d.cts" : "cjs";
82
- if (output.endsWith(".ts")) output = `${output.slice(0, -2)}${ts}`;
83
- if (output.endsWith(".mts")) output = `${output.slice(0, -3)}${mts}`;
84
- 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}`;
85
85
  if (outDir.startsWith("./") || outDir.startsWith("../")) return output;
86
- return `./${output}`;
86
+ else return `./${output}`;
87
87
  }
88
88
 
89
89
  function getLongestOutput(outDir, entries) {
90
90
  const outputs = [];
91
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) {
92
+ if (entry.copy) outputs.push(entry.copy.output);
93
+ if (entry.input) {
97
94
  const out = entry.output || getOutputPath(outDir, entry.input);
98
95
  outputs.push(out);
99
96
  }
100
- if ("declaration" in entry && entry.declaration) {
101
- const out = entry.output || getOutputPath(outDir, entry.declaration, true);
97
+ if (entry.declaration || entry.dts) {
98
+ const dts = entry.declaration || entry.dts;
99
+ const out = entry.output || getOutputPath(outDir, dts, true);
102
100
  outputs.push(out);
103
101
  }
104
- if ("template" in entry && entry.template) {
105
- outputs.push(entry.output);
106
- }
102
+ if (entry.template) outputs.push(entry.output);
107
103
  }
108
104
  return Math.max(...outputs.map((v) => v.length));
109
105
  }
@@ -301,6 +297,7 @@ async function build(cwd, options) {
301
297
  else return `./${path}`;
302
298
  };
303
299
  const fileStats = {
300
+ cwd,
304
301
  path: `${parseOutput(_entry.output)}/${parseInput(copyInput)}`,
305
302
  size: totalSize,
306
303
  buildTime: Date.now() - entryStart,
@@ -314,31 +311,22 @@ async function build(cwd, options) {
314
311
  }
315
312
  if (entry.input) {
316
313
  const logFilter = getLogFilter(entry.logFilter || []);
317
- const _output = getOutputPath(outDir, entry.input);
314
+ const _output = entry.output || getOutputPath(outDir, entry.input);
318
315
  let _format = "esm";
319
316
  if (_output.endsWith(".cjs")) _format = "cjs";
320
317
  const buildLogs = [];
321
318
  const _entry = {
322
319
  input: entry.input,
323
- output: entry.output || _output,
320
+ output: _output,
324
321
  externals: entry.externals || options.externals,
325
322
  format: entry.format || _format,
326
- transformers: entry.transformers,
323
+ ...entry,
327
324
  defaultPlugins: [
328
325
  esbuild({
329
326
  minify: !isUndefined(entry.minify) ? entry.minify : options.minify,
330
327
  ...entry.transformers?.esbuild
331
328
  })
332
- ],
333
- plugins: entry.plugins,
334
- banner: entry.banner,
335
- footer: entry.footer,
336
- intro: entry.intro,
337
- outro: entry.outro,
338
- paths: entry.paths,
339
- name: entry.name,
340
- globals: entry.globals,
341
- extend: entry.extend
329
+ ]
342
330
  };
343
331
  if (!entry.plugins) {
344
332
  if (_entry.transformers?.json) {
@@ -348,7 +336,7 @@ async function build(cwd, options) {
348
336
  if (_entry.transformers?.replace) {
349
337
  _entry.defaultPlugins.unshift(
350
338
  replacePlugin({
351
- true: true,
339
+ preventAssignment: true,
352
340
  ..._entry.transformers.replace
353
341
  })
354
342
  );
@@ -361,7 +349,15 @@ async function build(cwd, options) {
361
349
  aliasPlugin(_entry.transformers?.alias || aliasOptions)
362
350
  );
363
351
  }
364
- 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);
365
361
  const _build = await rollup({
366
362
  input: resolve(cwd, _entry.input),
367
363
  external: _entry.externals,
@@ -383,46 +379,42 @@ async function build(cwd, options) {
383
379
  extend: _entry.extend
384
380
  });
385
381
  const stats = await stat(resolve(cwd, _entry.output));
386
- const file = {
387
- path: _entry.output,
388
- size: stats.size,
389
- buildTime: Date.now() - entryStart,
390
- format: _entry.format,
391
- logs: buildLogs
392
- };
393
- buildStats.files.push(file);
382
+ fileStats.size = stats.size;
383
+ fileStats.buildTime = Date.now() - entryStart;
384
+ fileStats.logs = buildLogs;
385
+ buildStats.files.push(fileStats);
394
386
  buildStats.size = buildStats.size + stats.size;
395
- logModuleStats(file, longestOutput);
396
- await hooks?.["build:entry:end"]?.(_entry, buildStats);
387
+ logModuleStats(fileStats, longestOutput);
388
+ await hooks?.["build:entry:end"]?.(_entry, fileStats);
397
389
  }
398
- if (entry.declaration) {
390
+ if (entry.dts || entry.declaration) {
399
391
  const logFilter = getLogFilter(entry.logFilter || []);
400
- const _output = getOutputPath(outDir, entry.declaration, true);
401
- let _format = "esm";
402
- if (_output.endsWith(".d.cts")) _format = "cjs";
403
392
  const buildLogs = [];
393
+ const dts$1 = entry.dts || entry.declaration;
404
394
  const _entry = {
405
- input: entry.declaration,
406
- output: entry.output || _output,
395
+ dts: dts$1,
396
+ output: entry.output || getOutputPath(outDir, dts$1, true),
407
397
  externals: entry.externals || options.externals,
408
- format: entry.format || _format,
409
- transformers: entry.transformers,
410
- defaultPlugins: [dts(entry.transformers?.dts)],
411
- plugins: entry.plugins,
412
- banner: entry.banner,
413
- footer: entry.footer,
414
- intro: entry.intro,
415
- outro: entry.outro,
416
- paths: entry.paths
398
+ format: entry.format || "esm",
399
+ ...entry,
400
+ defaultPlugins: [dts(entry.transformers?.dts)]
417
401
  };
418
402
  if (!entry.plugins) {
419
403
  _entry.defaultPlugins.unshift(
420
404
  aliasPlugin(_entry.transformers?.alias || aliasOptions)
421
405
  );
422
406
  }
423
- 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);
424
416
  const _build = await rollup({
425
- input: resolve(cwd, _entry.input),
417
+ input: resolve(cwd, _entry.dts),
426
418
  external: _entry.externals,
427
419
  plugins: _entry.plugins || _entry.defaultPlugins,
428
420
  onLog: (level, log) => {
@@ -439,28 +431,21 @@ async function build(cwd, options) {
439
431
  paths: _entry.paths
440
432
  });
441
433
  const stats = await stat(resolve(cwd, _entry.output));
442
- const fileStats = {
443
- path: _entry.output,
444
- size: stats.size,
445
- buildTime: Date.now() - entryStart,
446
- format: "dts",
447
- logs: buildLogs
448
- };
434
+ fileStats.size = stats.size;
435
+ fileStats.buildTime = Date.now() - entryStart;
436
+ fileStats.logs = buildLogs;
449
437
  buildStats.files.push(fileStats);
450
438
  buildStats.size = buildStats.size + stats.size;
451
439
  logModuleStats(fileStats, longestOutput);
452
- await hooks?.["build:entry:end"]?.(_entry, buildStats);
440
+ await hooks?.["build:entry:end"]?.(_entry, fileStats);
453
441
  }
454
442
  if (entry.template && entry.output) {
455
443
  const buildLogs = [];
456
- const _entry = {
457
- template: entry.template,
458
- output: entry.output
459
- };
460
- await write(_entry.output, _entry.template);
461
- const stats = await stat(resolve(cwd, _entry.output));
444
+ await write(entry.output, entry.template);
445
+ const stats = await stat(resolve(cwd, entry.output));
462
446
  const fileStats = {
463
- path: _entry.output,
447
+ cwd,
448
+ path: entry.output,
464
449
  size: stats.size,
465
450
  buildTime: Date.now() - entryStart,
466
451
  format: "tmp",
@@ -484,6 +469,7 @@ async function createBuilder(cwd, config) {
484
469
  await hooks?.["bundle:start"]?.(options);
485
470
  logger.info(dim(`v${version}`));
486
471
  cl("Config", dim(configPath));
472
+ cl();
487
473
  cl("Bundling started...");
488
474
  cl(
489
475
  "Processing",
@@ -503,8 +489,9 @@ async function createBuilder(cwd, config) {
503
489
  "Module transformation is done"
504
490
  );
505
491
  cl(`Bundling fully completed in ${buildTime}`);
492
+ cl();
506
493
  cl(`${modules} transformed. Total size is ${buildSize}`);
507
- logger.info(`Bundle is generated and ready for production`);
494
+ cl(`Bundle is generated and ready for production`);
508
495
  cl();
509
496
  }).catch(error);
510
497
  await hooks?.["bundle:end"]?.(options);
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;