@trebired/bundler 2.0.0 → 3.1.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.
Files changed (310) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +286 -283
  3. package/dist/backend/utils/normalize.d.ts +2 -0
  4. package/dist/backend/utils/normalize.d.ts.map +1 -0
  5. package/dist/backend/utils/normalize.js +4 -0
  6. package/dist/backend/utils/normalize.js.map +1 -0
  7. package/dist/backend/utils/object.d.ts +3 -0
  8. package/dist/backend/utils/object.d.ts.map +1 -0
  9. package/dist/backend/utils/object.js +12 -0
  10. package/dist/backend/utils/object.js.map +1 -0
  11. package/dist/backend/utils/time.d.ts +3 -0
  12. package/dist/backend/utils/time.d.ts.map +1 -0
  13. package/dist/backend/utils/time.js +7 -0
  14. package/dist/backend/utils/time.js.map +1 -0
  15. package/dist/cli/run-cli.d.ts +1 -13
  16. package/dist/cli/run-cli.d.ts.map +1 -1
  17. package/dist/cli/run-cli.js +1 -103
  18. package/dist/cli/run-cli.js.map +1 -1
  19. package/dist/cli.d.ts.map +1 -1
  20. package/dist/cli.js.map +1 -1
  21. package/dist/config/index.d.ts +1 -1
  22. package/dist/config/index.d.ts.map +1 -1
  23. package/dist/config/index.js.map +1 -1
  24. package/dist/constants.d.ts.map +1 -1
  25. package/dist/constants.js.map +1 -1
  26. package/dist/core/asset-manifest.d.ts +1 -4
  27. package/dist/core/asset-manifest.d.ts.map +1 -1
  28. package/dist/core/asset-manifest.js +1 -256
  29. package/dist/core/asset-manifest.js.map +1 -1
  30. package/dist/core/build.d.ts +1 -3
  31. package/dist/core/build.d.ts.map +1 -1
  32. package/dist/core/build.js +1 -53
  33. package/dist/core/build.js.map +1 -1
  34. package/dist/core/derive-manifest.d.ts +1 -9
  35. package/dist/core/derive-manifest.d.ts.map +1 -1
  36. package/dist/core/derive-manifest.js +1 -149
  37. package/dist/core/derive-manifest.js.map +1 -1
  38. package/dist/core/discovery-watch.d.ts +1 -8
  39. package/dist/core/discovery-watch.d.ts.map +1 -1
  40. package/dist/core/discovery-watch.js +1 -100
  41. package/dist/core/discovery-watch.js.map +1 -1
  42. package/dist/core/discovery.d.ts +1 -35
  43. package/dist/core/discovery.d.ts.map +1 -1
  44. package/dist/core/discovery.js +1 -469
  45. package/dist/core/discovery.js.map +1 -1
  46. package/dist/core/esbuild-options.d.ts +1 -31
  47. package/dist/core/esbuild-options.d.ts.map +1 -1
  48. package/dist/core/esbuild-options.js +1 -109
  49. package/dist/core/esbuild-options.js.map +1 -1
  50. package/dist/core/import-graph.d.ts +1 -3
  51. package/dist/core/import-graph.d.ts.map +1 -1
  52. package/dist/core/import-graph.js +1 -409
  53. package/dist/core/import-graph.js.map +1 -1
  54. package/dist/core/manifest.d.ts +1 -14
  55. package/dist/core/manifest.d.ts.map +1 -1
  56. package/dist/core/manifest.js +1 -37
  57. package/dist/core/manifest.js.map +1 -1
  58. package/dist/core/shared.d.ts +1 -21
  59. package/dist/core/shared.d.ts.map +1 -1
  60. package/dist/core/shared.js +1 -79
  61. package/dist/core/shared.js.map +1 -1
  62. package/dist/core/watch.d.ts +1 -3
  63. package/dist/core/watch.d.ts.map +1 -1
  64. package/dist/core/watch.js +1 -188
  65. package/dist/core/watch.js.map +1 -1
  66. package/dist/frontend/js/utils/text.d.ts +2 -0
  67. package/dist/frontend/js/utils/text.d.ts.map +1 -0
  68. package/dist/frontend/js/utils/text.js +4 -0
  69. package/dist/frontend/js/utils/text.js.map +1 -0
  70. package/dist/index.d.ts +1 -2
  71. package/dist/index.d.ts.map +1 -1
  72. package/dist/index.js +0 -1
  73. package/dist/index.js.map +1 -1
  74. package/dist/internal/cli/run-cli.d.ts +14 -0
  75. package/dist/internal/cli/run-cli.d.ts.map +1 -0
  76. package/dist/internal/cli/run-cli.js +108 -0
  77. package/dist/internal/cli/run-cli.js.map +1 -0
  78. package/dist/internal/core/asset-manifest.d.ts +2 -0
  79. package/dist/internal/core/asset-manifest.d.ts.map +1 -0
  80. package/dist/internal/core/asset-manifest.js +2 -0
  81. package/dist/internal/core/asset-manifest.js.map +1 -0
  82. package/dist/internal/core/asset_manifest/runtime.d.ts +5 -0
  83. package/dist/internal/core/asset_manifest/runtime.d.ts.map +1 -0
  84. package/dist/internal/core/asset_manifest/runtime.js +252 -0
  85. package/dist/internal/core/asset_manifest/runtime.js.map +1 -0
  86. package/dist/internal/core/build.d.ts +4 -0
  87. package/dist/internal/core/build.d.ts.map +1 -0
  88. package/dist/internal/core/build.js +49 -0
  89. package/dist/internal/core/build.js.map +1 -0
  90. package/dist/internal/core/derive-manifest.d.ts +3 -0
  91. package/dist/internal/core/derive-manifest.d.ts.map +1 -0
  92. package/dist/internal/core/derive-manifest.js +2 -0
  93. package/dist/internal/core/derive-manifest.js.map +1 -0
  94. package/dist/internal/core/derive_manifest/runtime.d.ts +10 -0
  95. package/dist/internal/core/derive_manifest/runtime.d.ts.map +1 -0
  96. package/dist/internal/core/derive_manifest/runtime.js +133 -0
  97. package/dist/internal/core/derive_manifest/runtime.js.map +1 -0
  98. package/dist/internal/core/discovery/aggregate.d.ts +32 -0
  99. package/dist/internal/core/discovery/aggregate.d.ts.map +1 -0
  100. package/dist/internal/core/discovery/aggregate.js +124 -0
  101. package/dist/internal/core/discovery/aggregate.js.map +1 -0
  102. package/dist/internal/core/discovery/emit.d.ts +22 -0
  103. package/dist/internal/core/discovery/emit.d.ts.map +1 -0
  104. package/dist/internal/core/discovery/emit.js +37 -0
  105. package/dist/internal/core/discovery/emit.js.map +1 -0
  106. package/dist/internal/core/discovery/normalize.d.ts +8 -0
  107. package/dist/internal/core/discovery/normalize.d.ts.map +1 -0
  108. package/dist/internal/core/discovery/normalize.js +130 -0
  109. package/dist/internal/core/discovery/normalize.js.map +1 -0
  110. package/dist/internal/core/discovery/public.d.ts +5 -0
  111. package/dist/internal/core/discovery/public.d.ts.map +1 -0
  112. package/dist/internal/core/discovery/public.js +25 -0
  113. package/dist/internal/core/discovery/public.js.map +1 -0
  114. package/dist/internal/core/discovery/resolve.d.ts +9 -0
  115. package/dist/internal/core/discovery/resolve.d.ts.map +1 -0
  116. package/dist/internal/core/discovery/resolve.js +235 -0
  117. package/dist/internal/core/discovery/resolve.js.map +1 -0
  118. package/dist/internal/core/discovery/scan.d.ts +29 -0
  119. package/dist/internal/core/discovery/scan.d.ts.map +1 -0
  120. package/dist/internal/core/discovery/scan.js +105 -0
  121. package/dist/internal/core/discovery/scan.js.map +1 -0
  122. package/dist/internal/core/discovery/shared.d.ts +100 -0
  123. package/dist/internal/core/discovery/shared.d.ts.map +1 -0
  124. package/dist/internal/core/discovery/shared.js +187 -0
  125. package/dist/internal/core/discovery/shared.js.map +1 -0
  126. package/dist/internal/core/discovery-watch.d.ts +2 -0
  127. package/dist/internal/core/discovery-watch.d.ts.map +1 -0
  128. package/dist/internal/core/discovery-watch.js +2 -0
  129. package/dist/internal/core/discovery-watch.js.map +1 -0
  130. package/dist/internal/core/discovery.d.ts +5 -0
  131. package/dist/internal/core/discovery.d.ts.map +1 -0
  132. package/dist/internal/core/discovery.js +4 -0
  133. package/dist/internal/core/discovery.js.map +1 -0
  134. package/dist/internal/core/discovery_watch/runtime.d.ts +9 -0
  135. package/dist/internal/core/discovery_watch/runtime.d.ts.map +1 -0
  136. package/dist/internal/core/discovery_watch/runtime.js +127 -0
  137. package/dist/internal/core/discovery_watch/runtime.js.map +1 -0
  138. package/dist/internal/core/esbuild-options.d.ts +30 -0
  139. package/dist/internal/core/esbuild-options.d.ts.map +1 -0
  140. package/dist/internal/core/esbuild-options.js +93 -0
  141. package/dist/internal/core/esbuild-options.js.map +1 -0
  142. package/dist/internal/core/import-graph.d.ts +2 -0
  143. package/dist/internal/core/import-graph.d.ts.map +1 -0
  144. package/dist/internal/core/import-graph.js +2 -0
  145. package/dist/internal/core/import-graph.js.map +1 -0
  146. package/dist/internal/core/import_graph/parse.d.ts +6 -0
  147. package/dist/internal/core/import_graph/parse.d.ts.map +1 -0
  148. package/dist/internal/core/import_graph/parse.js +134 -0
  149. package/dist/internal/core/import_graph/parse.js.map +1 -0
  150. package/dist/internal/core/import_graph/resolve.d.ts +4 -0
  151. package/dist/internal/core/import_graph/resolve.d.ts.map +1 -0
  152. package/dist/internal/core/import_graph/resolve.js +105 -0
  153. package/dist/internal/core/import_graph/resolve.js.map +1 -0
  154. package/dist/internal/core/import_graph/shared.d.ts +21 -0
  155. package/dist/internal/core/import_graph/shared.d.ts.map +1 -0
  156. package/dist/internal/core/import_graph/shared.js +27 -0
  157. package/dist/internal/core/import_graph/shared.js.map +1 -0
  158. package/dist/internal/core/import_graph/tsconfig.d.ts +7 -0
  159. package/dist/internal/core/import_graph/tsconfig.d.ts.map +1 -0
  160. package/dist/internal/core/import_graph/tsconfig.js +111 -0
  161. package/dist/internal/core/import_graph/tsconfig.js.map +1 -0
  162. package/dist/internal/core/manifest.d.ts +15 -0
  163. package/dist/internal/core/manifest.d.ts.map +1 -0
  164. package/dist/internal/core/manifest.js +29 -0
  165. package/dist/internal/core/manifest.js.map +1 -0
  166. package/dist/internal/core/shared.d.ts +17 -0
  167. package/dist/internal/core/shared.d.ts.map +1 -0
  168. package/dist/internal/core/shared.js +63 -0
  169. package/dist/internal/core/shared.js.map +1 -0
  170. package/dist/internal/core/watch.d.ts +4 -0
  171. package/dist/internal/core/watch.d.ts.map +1 -0
  172. package/dist/internal/core/watch.js +185 -0
  173. package/dist/internal/core/watch.js.map +1 -0
  174. package/dist/internal/types/discovery.d.ts +91 -0
  175. package/dist/internal/types/discovery.d.ts.map +1 -0
  176. package/dist/internal/types/discovery.js +2 -0
  177. package/dist/internal/types/discovery.js.map +1 -0
  178. package/dist/internal/types/import_graph.d.ts +29 -0
  179. package/dist/internal/types/import_graph.d.ts.map +1 -0
  180. package/dist/internal/types/import_graph.js +2 -0
  181. package/dist/internal/types/import_graph.js.map +1 -0
  182. package/dist/internal/types/logging.d.ts +9 -0
  183. package/dist/internal/types/logging.d.ts.map +1 -0
  184. package/dist/internal/types/logging.js +2 -0
  185. package/dist/internal/types/logging.js.map +1 -0
  186. package/dist/internal/types/manifest.d.ts +106 -0
  187. package/dist/internal/types/manifest.d.ts.map +1 -0
  188. package/dist/internal/types/manifest.js +2 -0
  189. package/dist/internal/types/manifest.js.map +1 -0
  190. package/dist/internal/types/runtime.d.ts +47 -0
  191. package/dist/internal/types/runtime.d.ts.map +1 -0
  192. package/dist/internal/types/runtime.js +2 -0
  193. package/dist/internal/types/runtime.js.map +1 -0
  194. package/dist/internal/types.d.ts +6 -0
  195. package/dist/internal/types.d.ts.map +1 -0
  196. package/dist/internal/types.js +2 -0
  197. package/dist/internal/types.js.map +1 -0
  198. package/dist/logging.d.ts.map +1 -1
  199. package/dist/logging.js.map +1 -1
  200. package/dist/plugins/scss.d.ts +1 -1
  201. package/dist/plugins/scss.d.ts.map +1 -1
  202. package/dist/plugins/scss.js.map +1 -1
  203. package/dist/plugins/source-annotations.d.ts +1 -1
  204. package/dist/plugins/source-annotations.d.ts.map +1 -1
  205. package/dist/plugins/source-annotations.js.map +1 -1
  206. package/dist/plugins/virtual-entries.d.ts +1 -1
  207. package/dist/plugins/virtual-entries.d.ts.map +1 -1
  208. package/dist/plugins/virtual-entries.js +2 -2
  209. package/dist/plugins/virtual-entries.js.map +1 -1
  210. package/dist/src/backend/utils/normalize.d.ts +2 -0
  211. package/dist/src/backend/utils/normalize.d.ts.map +1 -0
  212. package/dist/src/backend/utils/normalize.js +4 -0
  213. package/dist/src/backend/utils/normalize.js.map +1 -0
  214. package/dist/src/backend/utils/object.d.ts +3 -0
  215. package/dist/src/backend/utils/object.d.ts.map +1 -0
  216. package/dist/src/backend/utils/object.js +12 -0
  217. package/dist/src/backend/utils/object.js.map +1 -0
  218. package/dist/src/backend/utils/time.d.ts +3 -0
  219. package/dist/src/backend/utils/time.d.ts.map +1 -0
  220. package/dist/src/backend/utils/time.js +7 -0
  221. package/dist/src/backend/utils/time.js.map +1 -0
  222. package/dist/src/cli/run-cli.d.ts +2 -0
  223. package/dist/src/cli/run-cli.d.ts.map +1 -0
  224. package/dist/src/cli/run-cli.js +2 -0
  225. package/dist/src/cli/run-cli.js.map +1 -0
  226. package/dist/src/cli.d.ts +5 -0
  227. package/dist/src/cli.d.ts.map +1 -0
  228. package/dist/src/cli.js +10 -0
  229. package/dist/src/cli.js.map +1 -0
  230. package/dist/src/config/index.d.ts +5 -0
  231. package/dist/src/config/index.d.ts.map +1 -0
  232. package/dist/src/config/index.js +32 -0
  233. package/dist/src/config/index.js.map +1 -0
  234. package/dist/src/constants.d.ts +4 -0
  235. package/dist/src/constants.d.ts.map +1 -0
  236. package/dist/src/constants.js +4 -0
  237. package/dist/src/constants.js.map +1 -0
  238. package/dist/src/core/asset-manifest.d.ts +2 -0
  239. package/dist/src/core/asset-manifest.d.ts.map +1 -0
  240. package/dist/src/core/asset-manifest.js +2 -0
  241. package/dist/src/core/asset-manifest.js.map +1 -0
  242. package/dist/src/core/build.d.ts +2 -0
  243. package/dist/src/core/build.d.ts.map +1 -0
  244. package/dist/src/core/build.js +2 -0
  245. package/dist/src/core/build.js.map +1 -0
  246. package/dist/src/core/derive-manifest.d.ts +2 -0
  247. package/dist/src/core/derive-manifest.d.ts.map +1 -0
  248. package/dist/src/core/derive-manifest.js +2 -0
  249. package/dist/src/core/derive-manifest.js.map +1 -0
  250. package/dist/src/core/discovery-watch.d.ts +2 -0
  251. package/dist/src/core/discovery-watch.d.ts.map +1 -0
  252. package/dist/src/core/discovery-watch.js +2 -0
  253. package/dist/src/core/discovery-watch.js.map +1 -0
  254. package/dist/src/core/discovery.d.ts +2 -0
  255. package/dist/src/core/discovery.d.ts.map +1 -0
  256. package/dist/src/core/discovery.js +2 -0
  257. package/dist/src/core/discovery.js.map +1 -0
  258. package/dist/src/core/esbuild-options.d.ts +2 -0
  259. package/dist/src/core/esbuild-options.d.ts.map +1 -0
  260. package/dist/src/core/esbuild-options.js +2 -0
  261. package/dist/src/core/esbuild-options.js.map +1 -0
  262. package/dist/src/core/import-graph.d.ts +2 -0
  263. package/dist/src/core/import-graph.d.ts.map +1 -0
  264. package/dist/src/core/import-graph.js +2 -0
  265. package/dist/src/core/import-graph.js.map +1 -0
  266. package/dist/src/core/manifest.d.ts +2 -0
  267. package/dist/src/core/manifest.d.ts.map +1 -0
  268. package/dist/src/core/manifest.js +2 -0
  269. package/dist/src/core/manifest.js.map +1 -0
  270. package/dist/src/core/shared.d.ts +2 -0
  271. package/dist/src/core/shared.d.ts.map +1 -0
  272. package/dist/src/core/shared.js +2 -0
  273. package/dist/src/core/shared.js.map +1 -0
  274. package/dist/src/core/watch.d.ts +2 -0
  275. package/dist/src/core/watch.d.ts.map +1 -0
  276. package/dist/src/core/watch.js +2 -0
  277. package/dist/src/core/watch.js.map +1 -0
  278. package/dist/src/frontend/js/utils/text.d.ts +2 -0
  279. package/dist/src/frontend/js/utils/text.d.ts.map +1 -0
  280. package/dist/src/frontend/js/utils/text.js +4 -0
  281. package/dist/src/frontend/js/utils/text.js.map +1 -0
  282. package/dist/src/index.d.ts +14 -0
  283. package/dist/src/index.d.ts.map +1 -0
  284. package/dist/src/index.js +13 -0
  285. package/dist/src/index.js.map +1 -0
  286. package/dist/src/logging.d.ts +5 -0
  287. package/dist/src/logging.d.ts.map +1 -0
  288. package/dist/src/logging.js +35 -0
  289. package/dist/src/logging.js.map +1 -0
  290. package/dist/src/plugins/scss.d.ts +11 -0
  291. package/dist/src/plugins/scss.d.ts.map +1 -0
  292. package/dist/src/plugins/scss.js +44 -0
  293. package/dist/src/plugins/scss.js.map +1 -0
  294. package/dist/src/plugins/source-annotations.d.ts +17 -0
  295. package/dist/src/plugins/source-annotations.d.ts.map +1 -0
  296. package/dist/src/plugins/source-annotations.js +78 -0
  297. package/dist/src/plugins/source-annotations.js.map +1 -0
  298. package/dist/src/plugins/virtual-entries.d.ts +11 -0
  299. package/dist/src/plugins/virtual-entries.d.ts.map +1 -0
  300. package/dist/src/plugins/virtual-entries.js +39 -0
  301. package/dist/src/plugins/virtual-entries.js.map +1 -0
  302. package/dist/src/types.d.ts +2 -0
  303. package/dist/src/types.d.ts.map +1 -0
  304. package/dist/src/types.js +2 -0
  305. package/dist/src/types.js.map +1 -0
  306. package/dist/types.d.ts +1 -181
  307. package/dist/types.d.ts.map +1 -1
  308. package/dist/types.js +1 -1
  309. package/dist/types.js.map +1 -1
  310. package/package.json +108 -41
package/README.md CHANGED
@@ -1,10 +1,8 @@
1
1
  # @trebired/bundler
2
2
 
3
- Fast bundler wrapper around `esbuild` with SCSS support, compact build modes, watch mode, and inline source path annotations.
3
+ Discover-only bundler wrapper around `esbuild` with SCSS support, watch mode, source annotations, and a runtime-friendly asset manifest.
4
4
 
5
- `@trebired/bundler` is not a full custom bundler. It keeps the package-owned API small and lets `esbuild` do the heavy lifting, while adding logging aligned with other packages published by Trebired, SCSS compilation through `sass-embedded`, built-in source walking, config-driven CLI commands, virtual entry modules, derived manifest helpers, and inline source path comments in generated output.
6
-
7
- The default build mode is `compact`. It enables minification and comment stripping unless you turn on source annotations.
5
+ `@trebired/bundler` now has one public entry model: discovery rules. You describe what the bundler should find, whether each matched file should stay isolated, join a grouped bundle, or be ignored, and the package handles the rest.
8
6
 
9
7
  ## Install
10
8
 
@@ -14,38 +12,6 @@ Runtime support: Bun 1+ and Node.js 18+.
14
12
  npm install @trebired/bundler
15
13
  ```
16
14
 
17
- ## What It Is For
18
-
19
- Use this when:
20
-
21
- - you want a bundling package that fits alongside other packages published by Trebired instead of wiring `esbuild` directly in every project
22
- - you need one package that handles `tsx`, `jsx`, `ts`, `js`, `scss`, and `css`
23
- - you want the package to discover entry files by walking your source tree
24
- - you want in-memory generated entry modules without writing temp files
25
- - you want watch mode and config-driven CLI commands without building a separate toolchain wrapper
26
- - you want newly created matching files to join the build without external entry regeneration code
27
- - you want a manifest describing resolved entries and generated outputs
28
- - you want a stable helper for turning esbuild metafiles into runtime asset graphs
29
- - you want a runtime-friendly asset manifest keyed by entry names and source paths
30
- - you want a package-owned helper for collecting script and stylesheet links for selected entries
31
- - you want a generic import graph walker with tsconfig path resolution for higher-level presets
32
- - you want rebuild hooks instead of scraping logger text
33
- - you want generated bundles to optionally include inline comments that point back to the original source file path
34
- - you want production-lean defaults with minified output and stripped comments
35
- - you want a stronger `extreme` mode for the most aggressive package-owned compacting defaults
36
- - you want package-owned logs routed through `@trebired/logger-adapter`
37
-
38
- ## What It Does Not Do
39
-
40
- This package does not:
41
-
42
- - replace `esbuild`
43
- - provide a dev server or HMR
44
- - invent a separate package-specific module graph format
45
- - manage HTML templates or deployment assets for you
46
-
47
- If you want a fast bundling wrapper from the Trebired package ecosystem, use this package. If you want a fully custom bundler runtime, this package is intentionally not that.
48
-
49
15
  ## Quick Start
50
16
 
51
17
  ```ts
@@ -53,14 +19,37 @@ import { bundle } from "@trebired/bundler";
53
19
 
54
20
  await bundle({
55
21
  discover: {
56
- dir: "./src",
57
- include: ["app.tsx", "theme.css"],
58
- },
59
- virtualEntries: {
60
- "entry-server": `
61
- import { message } from "./src/lib/message";
62
- export const rendered = message.toUpperCase();
63
- `,
22
+ dir: "./src/frontend",
23
+ rules: [
24
+ {
25
+ key: "client",
26
+ include: ["**/*.client.ts", "**/*.client.tsx"],
27
+ strategy: "entry",
28
+ },
29
+ {
30
+ key: "defer",
31
+ include: ["**/*.defer.ts"],
32
+ strategy: "entry",
33
+ },
34
+ {
35
+ key: "global-style",
36
+ include: ["css/**/*.css", "css/**/*.scss"],
37
+ strategy: "bundle",
38
+ maxBundleSize: "50mb",
39
+ },
40
+ {
41
+ key: "shared-script",
42
+ include: ["**/*.ts", "**/*.js"],
43
+ exclude: ["**/*.client.ts", "**/*.client.tsx", "**/*.defer.ts"],
44
+ strategy: "bundle",
45
+ maxBundleSize: "50mb",
46
+ },
47
+ {
48
+ key: "ignored-tests",
49
+ include: ["**/*.test.*", "**/*.spec.*"],
50
+ strategy: "ignore",
51
+ },
52
+ ],
64
53
  },
65
54
  outDir: "./dist",
66
55
  sourcemap: "external",
@@ -79,10 +68,25 @@ import { defineBundlerConfig } from "@trebired/bundler";
79
68
  export default defineBundlerConfig({
80
69
  discover: {
81
70
  dir: "./src/frontend",
82
- include: ["**/*.tsx", "**/*.scss", "**/*.css"],
71
+ rules: [
72
+ {
73
+ key: "client",
74
+ include: ["**/*.client.ts", "**/*.client.tsx"],
75
+ strategy: "entry",
76
+ },
77
+ {
78
+ key: "global-style",
79
+ include: ["css/**/*.css", "css/**/*.scss"],
80
+ strategy: "bundle",
81
+ },
82
+ {
83
+ key: "shared-script",
84
+ include: ["shared/**/*.ts", "shared/**/*.js"],
85
+ strategy: "bundle",
86
+ },
87
+ ],
83
88
  },
84
89
  outDir: "./dist",
85
- annotateSources: true,
86
90
  manifest: true,
87
91
  });
88
92
  ```
@@ -94,81 +98,132 @@ trebired-bundler build --config ./bundler.config.mjs
94
98
  trebired-bundler watch --config ./bundler.config.mjs
95
99
  ```
96
100
 
97
- ## Discovery And Walking
101
+ ## Discover Rules
102
+
103
+ Rules are ordered. First match wins.
104
+
105
+ - `entry`: keep one output entry per matched file
106
+ - `bundle`: group all matched files together, then split only when the whole group exceeds `maxBundleSize`
107
+ - `aggregate`: synthesize one internal entry module in memory from many discovered modules
108
+ - `ignore`: track the file as intentionally ignored and exclude it from outputs
98
109
 
99
- Set `discover` when you want `@trebired/bundler` to walk the source tree and build the entry list itself.
110
+ Every discovered file must match exactly one rule. If a file is in scope and matches nothing, the build fails.
111
+
112
+ ### `maxBundleSize`
113
+
114
+ - only valid on `bundle` rules
115
+ - defaults to `50mb`
116
+ - accepts bytes or strings like `"512kb"`, `"50mb"`, or `"1gb"`
117
+ - splits by summed source-file size before handing grouped parts to `esbuild`
118
+ - fails the build if a single grouped file is larger than the configured limit
119
+
120
+ ### Bundle Naming
121
+
122
+ Grouped outputs always use package-owned names:
123
+
124
+ - `bundle-<stable-id>.js`
125
+ - `bundle-<stable-id>-2.js`
126
+ - `bundle-<stable-id>.css`
127
+ - `bundle-<stable-id>-2.css`
128
+
129
+ Callers do not provide custom grouped bundle names.
130
+
131
+ ### Aggregate Rules
132
+
133
+ Use `strategy: "aggregate"` when you need one generated entry module without writing any temporary source file to disk.
134
+
135
+ The first built-in aggregate kind is `module-map`. It:
136
+
137
+ - optionally imports one configured root module
138
+ - imports every matched module with namespace imports
139
+ - resolves a configured export from each matched module
140
+ - builds a map object keyed by normalized discovered path
141
+ - exports the map, a resolver function, and optionally the root module binding
142
+ - can also export a default object containing the same fields
143
+
144
+ Example:
100
145
 
101
146
  ```ts
102
147
  await bundle({
103
148
  discover: {
104
149
  dir: "./src/frontend",
105
- include: ["**/*.tsx", "**/*.js", "**/*.ts", "**/*.css", "**/*.scss"],
106
- exclude: ["**/*.test.tsx"],
107
- maxBundleSize: "50mb",
150
+ rules: [
151
+ {
152
+ key: "ssr-pages",
153
+ include: ["pages/**/*.tsx"],
154
+ exclude: ["**/*.client.tsx", "**/*.defer.tsx", "**/*.spec.tsx", "**/*.test.tsx"],
155
+ strategy: "aggregate",
156
+ aggregate: {
157
+ kind: "module-map",
158
+ rootModule: "layouts/root_document.tsx",
159
+ collapseIndex: true,
160
+ exports: {
161
+ root: "rootDocument",
162
+ map: "pages",
163
+ resolver: "getPageComponent",
164
+ default: true,
165
+ },
166
+ },
167
+ },
168
+ ],
108
169
  },
109
170
  outDir: "./dist",
110
171
  });
111
172
  ```
112
173
 
113
- The package:
114
-
115
- - walks the configured directory recursively
116
- - matches files by extension plus optional include and exclude patterns
117
- - groups discovered `.js` and `.ts` files into auto-named script bundles
118
- - groups discovered `.css` and `.scss` files into auto-named style bundles
119
- - leaves discovered `.jsx` and `.tsx` files as normal per-file entries
120
- - rebuilds the entry list during watch mode when matching files are added or removed
121
-
122
- - grouped bundles are auto-named like `bundle-abc123.js` and `bundle-abc123-2.css`
123
- - `maxBundleSize` defaults to `50mb`
124
- - `maxBundleSize` accepts bytes or strings like `"50mb"` and splits bundles by summed discovered source-file size before handing each group to `esbuild`
125
- - if one discovered grouped file is larger than `maxBundleSize`, the build fails
126
-
127
- You can combine manual `entries` with `discover`. If both resolve the same entry name to different files, the build fails so the collision is explicit.
174
+ Path keys default to the matched module path relative to the aggregate rule root, without the file extension:
128
175
 
129
- ## Manifest
176
+ - `pages/home.tsx` -> `home`
177
+ - `pages/blog/post.tsx` -> `blog/post`
178
+ - `pages/settings/index.tsx` -> `settings` when `collapseIndex: true`
130
179
 
131
- Set `manifest: true` to write `dist/bundler-manifest.json`, or pass `manifest: { file: "custom-name.json" }` to choose a different path inside `outDir`.
180
+ ## Frontend Conventions
132
181
 
133
- The manifest contains:
182
+ This API is meant for conventions like:
134
183
 
135
- - resolved entries
136
- - whether each entry came from `manual` config or `discover`
137
- - generated output files
138
- - a runtime-friendly `assetManifest` keyed by entry source path, with lookup maps for entry names and emitted outputs
184
+ - `*.client.ts`
185
+ - `*.client.tsx`
186
+ - `*.defer.ts`
187
+ - global `css/**/*.css`
188
+ - global `css/**/*.scss`
139
189
 
140
- If you want a runtime-friendly asset graph directly in app code, call `deriveManifest()` on the returned `metafile`:
190
+ Typical setup:
141
191
 
142
- ```ts
143
- import { bundle, deriveManifest } from "@trebired/bundler";
192
+ - client boot files use `strategy: "entry"`
193
+ - defer boot files use `strategy: "entry"`
194
+ - shared JS/TS helpers use `strategy: "bundle"`
195
+ - global CSS/SCSS uses `strategy: "bundle"`
196
+ - tests and non-runtime files use `strategy: "ignore"`
144
197
 
145
- const result = await bundle({
146
- entries: {
147
- app: "./src/app.tsx",
148
- },
149
- outDir: "./dist",
150
- });
198
+ Important behavior:
151
199
 
152
- const manifest = deriveManifest(result.metafile!, {
153
- rootDir: process.cwd(),
154
- outDir: "./dist",
155
- });
156
- ```
200
+ - grouped `bundle` rules must stay style-only or script-only; mixing CSS/SCSS with JS/TS in one rule fails
201
+ - `*.client.*` and `*.defer.*` entries may not import JS/TS files owned by a grouped bundle rule; that fails the build because those files are treated as shared standalone bundles, not implicit app-entry dependencies
157
202
 
158
- The helper returns:
203
+ ## Manifest
159
204
 
160
- - `entries`: entry output -> JS/CSS/import graph
161
- - `chunks`: shared output -> import/CSS graph
162
- - `allOutputs`: flat normalized output index
205
+ Set `manifest: true` to write `dist/bundler-manifest.json`, or pass `manifest: { file: "custom-name.json" }`.
163
206
 
164
- If you want a manifest ready for runtime asset selection, use `buildAssetManifest()`:
207
+ The build result also exposes `assetManifest` directly.
165
208
 
166
209
  ```ts
167
210
  import { buildAssetManifest, bundle, collectAssetLinks } from "@trebired/bundler";
168
211
 
169
212
  const result = await bundle({
170
- entries: {
171
- app: "./src/app.tsx",
213
+ discover: {
214
+ dir: "./src/frontend",
215
+ rules: [
216
+ {
217
+ key: "client",
218
+ include: ["**/*.client.ts", "**/*.client.tsx"],
219
+ strategy: "entry",
220
+ },
221
+ {
222
+ key: "global-style",
223
+ include: ["css/**/*.css", "css/**/*.scss"],
224
+ strategy: "bundle",
225
+ },
226
+ ],
172
227
  },
173
228
  outDir: "./dist",
174
229
  });
@@ -177,55 +232,80 @@ const assetManifest = result.assetManifest || buildAssetManifest({
177
232
  metafile: result.metafile!,
178
233
  outDir: "./dist",
179
234
  rootDir: process.cwd(),
180
- resolvedEntries: result.entries,
235
+ resolvedDiscovery: result.resolvedDiscovery,
181
236
  });
182
237
 
183
- const assets = collectAssetLinks(assetManifest, ["app"], {
238
+ const assets = collectAssetLinks(assetManifest, [
239
+ "src/frontend/home.client.tsx",
240
+ ], {
241
+ from: "source",
184
242
  publicPath: "/",
185
243
  });
186
244
  ```
187
245
 
188
- The runtime asset manifest exposes:
189
-
190
- - `entries`: entry source path -> primary file, reachable JS, reachable CSS, and other emitted assets
191
- - `entryNames`: logical entry name -> entry source path
192
- - `entryOutputs`: emitted entry file -> entry source path
193
- - `outputs`: emitted output index relative to `outDir`
194
-
195
- ## Virtual Entries
246
+ ### Asset Manifest Shape
196
247
 
197
- Use `virtualEntries` when you want generated entry modules without writing temporary files:
248
+ `result.entries` is a source ownership map:
198
249
 
199
250
  ```ts
200
- await bundle({
201
- entries: {
202
- app: "./src/app.tsx",
203
- },
204
- virtualEntries: {
205
- "entry-server": `
206
- import { message } from "./src/lib/message";
207
- export const rendered = message.toUpperCase();
208
- `,
209
- "global.client": `
210
- import "./src/styles/site.scss";
211
- console.log("global-client");
212
- `,
213
- },
214
- outDir: "./dist",
215
- });
251
+ Record<string, string>
252
+ // source path -> owning entry key
216
253
  ```
217
254
 
218
- Virtual entries are loaded as TypeScript/ESM modules and resolve relative imports from `rootDir`.
255
+ `assetManifest` exposes:
256
+
257
+ - `sources[sourcePath]`: source file -> owning entry key, rule key, strategy, outputs
258
+ - `entries[entryKey]`: entry or grouped bundle -> owned sources, outputs, JS, CSS, assets, plus generated/aggregate metadata when applicable
259
+ - `entryOutputs[emittedFile]`: emitted entry output -> entry key
260
+ - `outputs[outputFile]`: normalized output metadata
261
+ - `rules[ruleKey]`: grouped entry keys plus ignored sources for that rule, plus aggregate metadata when applicable
262
+
263
+ This lets runtime code resolve either:
219
264
 
220
- ## Watch Hooks
265
+ - a source path to its owning entry key
266
+ - an entry key to the emitted scripts/styles/assets
267
+ - a grouped bundle back to the exact source files it owns
221
268
 
222
- Use watch hooks when app code needs clean lifecycle points after rebuilds:
269
+ ### Collecting Runtime Links
270
+
271
+ Use `collectAssetLinks()` when app code needs scripts and styles for one or more sources or entry keys.
272
+
273
+ Supported lookup modes:
274
+
275
+ - `from: "source"`
276
+ - `from: "entryKey"`
277
+ - `from: "entryOutput"`
278
+ - `from: "ruleKey"`
279
+ - `from: "auto"` (default)
280
+
281
+ ## Watch Mode
282
+
283
+ `watch()` stays discover-driven.
284
+
285
+ - added or removed matching files trigger a discovery rescan
286
+ - if source ownership changes, the bundler rebuilds the esbuild context
287
+ - `onEntrySetChanged()` receives the new source ownership map
288
+ - `onRebuilt()` receives the full `BundlerBuildResult`
289
+ - invalid intermediate states still surface failures, but the watcher keeps running and recovers on the next valid filesystem change
223
290
 
224
291
  ```ts
225
- await watch({
292
+ import { watch } from "@trebired/bundler";
293
+
294
+ const session = await watch({
226
295
  discover: {
227
- dir: "./src/pages",
228
- include: ["**/*.tsx"],
296
+ dir: "./src/frontend",
297
+ rules: [
298
+ {
299
+ key: "client",
300
+ include: ["**/*.client.ts", "**/*.client.tsx"],
301
+ strategy: "entry",
302
+ },
303
+ {
304
+ key: "shared-script",
305
+ include: ["shared/**/*.ts", "shared/**/*.js"],
306
+ strategy: "bundle",
307
+ },
308
+ ],
229
309
  },
230
310
  outDir: "./dist",
231
311
  async onEntrySetChanged(entries) {
@@ -235,13 +315,13 @@ await watch({
235
315
  console.log(result.outputs);
236
316
  },
237
317
  });
238
- ```
239
318
 
240
- `onEntrySetChanged()` runs only when the resolved entry set changes. `onRebuilt()` runs after a successful rebuild result is assembled.
319
+ await session.dispose();
320
+ ```
241
321
 
242
322
  ## Import Graph Walking
243
323
 
244
- Use `walkImportGraph()` when a higher-level preset needs to inspect internal source dependencies without reimplementing relative import or tsconfig-path resolution:
324
+ Use `walkImportGraph()` when a higher-level tool needs to inspect internal source dependencies without bundling:
245
325
 
246
326
  ```ts
247
327
  import { walkImportGraph } from "@trebired/bundler";
@@ -252,131 +332,70 @@ const graph = await walkImportGraph({
252
332
  });
253
333
  ```
254
334
 
255
- The helper:
256
-
257
- - walks static imports, re-exports, and string-literal dynamic imports
258
- - resolves relative imports and tsconfig `paths`
259
- - returns a root-relative file graph with resolved internal imports marked explicitly
260
-
261
- ## Optimization Defaults
262
-
263
- `@trebired/bundler` now defaults to production-lean output through `mode: "compact"`:
264
-
265
- - `mode` defaults to `"compact"`
266
- - `minify` defaults to `true`
267
- - `stripComments` defaults to `true`
268
- - source annotations stay opt-in through `annotateSources: true`
269
-
270
- Available modes:
335
+ It resolves:
271
336
 
272
- - `debug`: readable output, no minification, no comment stripping by default
273
- - `compact`: minified output with stripped preserved comments by default
274
- - `extreme`: compact mode with the strongest package-owned compacting profile, without renaming classes or artifacts
337
+ - relative imports
338
+ - re-exports
339
+ - string-literal dynamic imports
340
+ - tsconfig `paths`
275
341
 
276
- If you want a more readable debug build:
342
+ ## Public Config Shape
277
343
 
278
344
  ```ts
279
- await bundle({
280
- entries: {
281
- app: "./src/app.tsx",
282
- },
283
- mode: "debug",
284
- minify: false,
285
- outDir: "./dist",
286
- stripComments: false,
287
- });
288
- ```
289
-
290
- ## Extreme Mode
291
-
292
- Use `mode: "extreme"` when you want the package to apply its strongest built-in compacting profile:
293
-
294
- ```ts
295
- await bundle({
296
- entries: {
297
- app: "./src/app.tsx",
298
- },
299
- mode: "extreme",
300
- outDir: "./dist",
301
- });
302
- ```
303
-
304
- This mode enables:
305
-
306
- - minification
307
- - stripped preserved comments
308
- - stable entry, chunk, and asset naming
309
-
310
- Today `extreme` intentionally keeps the same readable artifact and class names as other modes. The difference is its production-lean compacting profile, not obfuscation.
311
-
312
- ## Source Annotation Comments
313
-
314
- Set `annotateSources: true` to inject preserved inline comments into bundled output.
315
-
316
- JavaScript and TypeScript modules are annotated like this:
317
-
318
- ```js
319
- /*! source: src/app.tsx */
320
- ```
321
-
322
- CSS and SCSS sources are annotated like this:
323
-
324
- ```css
325
- /*! source: src/styles/site.scss */
326
- ```
327
-
328
- These comments are emitted with project-relative POSIX-style paths so the generated bundle still points back to the original source file that contributed that segment.
329
-
330
- ## Supported File Types
331
-
332
- The package supports:
333
-
334
- - `js`
335
- - `jsx`
336
- - `ts`
337
- - `tsx`
338
- - `css`
339
- - `scss`
340
-
341
- Plain JS, TS, JSX, TSX, and CSS are handled directly by `esbuild`. SCSS is compiled with `sass-embedded` and then passed back into the bundle pipeline as CSS.
342
-
343
- ## Logging
344
-
345
- Package-owned logs are normalized through `@trebired/logger-adapter`, the same way other packages published by Trebired do it.
346
-
347
- You can pass:
348
-
349
- - a logger using the same call shape as other Trebired packages
350
- - an event sink logger
351
- - a common logger object
352
- - a custom `loggerAdapter(logger, event)` for exact output control
353
-
354
- ## Public API
345
+ type BundlerDiscoverRule =
346
+ | {
347
+ key: string;
348
+ include: string[];
349
+ exclude?: string[];
350
+ strategy: "entry";
351
+ }
352
+ | {
353
+ key: string;
354
+ include: string[];
355
+ exclude?: string[];
356
+ strategy: "bundle";
357
+ maxBundleSize?: number | string;
358
+ }
359
+ | {
360
+ key: string;
361
+ include: string[];
362
+ exclude?: string[];
363
+ strategy: "ignore";
364
+ }
365
+ | {
366
+ key: string;
367
+ include: string[];
368
+ exclude?: string[];
369
+ strategy: "aggregate";
370
+ aggregate: {
371
+ kind: "module-map";
372
+ rootModule?: string;
373
+ rootModuleExportName?: string;
374
+ matchedModuleExportName?: string;
375
+ keyFromPath?: "relative-path";
376
+ collapseIndex?: boolean;
377
+ allowEmpty?: boolean;
378
+ exports?: {
379
+ root?: string;
380
+ map: string;
381
+ resolver: string;
382
+ default?: boolean;
383
+ };
384
+ };
385
+ };
386
+
387
+ type BundlerDiscoverOptions = {
388
+ dir: string;
389
+ rules: BundlerDiscoverRule[];
390
+ ignoreDirs?: string[];
391
+ };
355
392
 
356
- ```ts
357
393
  type BundlerOptions = {
358
- entries?: string[] | Record<string, string>;
359
- discover?: {
360
- dir: string;
361
- include?: string[];
362
- exclude?: string[];
363
- extensions?: string[];
364
- ignoreDirs?: string[];
365
- namePrefix?: string;
366
- } | Array<{
367
- dir: string;
368
- include?: string[];
369
- exclude?: string[];
370
- extensions?: string[];
371
- ignoreDirs?: string[];
372
- namePrefix?: string;
373
- }>;
374
- virtualEntries?: Record<string, string>;
394
+ discover: BundlerDiscoverOptions | BundlerDiscoverOptions[];
375
395
  outDir: string;
376
396
  rootDir?: string;
377
- mode?: "debug" | "compact" | "extreme";
378
397
  environment?: "browser" | "node" | "neutral";
379
- format?: "esm" | "cjs" | "iife";
398
+ format?: Format;
380
399
  target?: string | string[];
381
400
  minify?: boolean;
382
401
  stripComments?: boolean;
@@ -387,45 +406,29 @@ type BundlerOptions = {
387
406
  define?: Record<string, string>;
388
407
  clean?: boolean;
389
408
  annotateSources?: boolean;
390
- manifest?: boolean | {
391
- file?: string;
392
- };
409
+ manifest?: boolean | { file?: string };
393
410
  onRebuilt?: (result: BundlerBuildResult) => void | Promise<void>;
394
411
  onEntrySetChanged?: (entries: Record<string, string>) => void | Promise<void>;
395
- logger?: unknown;
396
- loggerAdapter?: (logger: unknown, event: unknown) => unknown;
412
+ logger?: BundlerLogger;
413
+ loggerAdapter?: BundlerLoggerAdapter;
397
414
  };
415
+ ```
398
416
 
399
- declare function bundle(options: BundlerOptions): Promise<{
400
- entries: Record<string, string>;
401
- outputs: string[];
402
- warnings: number;
403
- metafile?: object;
404
- manifestPath?: string;
405
- durationMs: number;
406
- }>;
407
-
408
- declare function deriveManifest(
409
- metafile: object,
410
- options: {
411
- rootDir: string;
412
- outDir: string;
413
- },
414
- ): {
415
- entries: Record<string, unknown>;
416
- chunks: Record<string, unknown>;
417
- allOutputs: Record<string, unknown>;
418
- };
417
+ ## Migration Notes
419
418
 
420
- declare function watch(options: BundlerOptions): Promise<{
421
- rebuild(): Promise<{
422
- entries: Record<string, string>;
423
- outputs: string[];
424
- warnings: number;
425
- metafile?: object;
426
- manifestPath?: string;
427
- durationMs: number;
428
- }>;
429
- dispose(): Promise<void>;
430
- }>;
431
- ```
419
+ This release removes the old mixed entry model.
420
+
421
+ - `entries` is gone
422
+ - public `virtualEntries` is gone
423
+ - `mode` is gone
424
+ - `discover.include` / `discover.exclude` at the top level is replaced by ordered `discover.rules`
425
+ - runtime code using `entryNames` or `entrySources` should move to `assetManifest.sources` and `assetManifest.entries`
426
+
427
+ ## What It Does Not Do
428
+
429
+ This package does not:
430
+
431
+ - replace `esbuild`
432
+ - provide a dev server or HMR
433
+ - invent a custom runtime module system
434
+ - auto-convert grouped shared JS/TS sources into dependency-safe page entry imports