@savvy-web/tsdown-plugins 1.1.4 → 1.1.5

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.
@@ -32,6 +32,13 @@ const STUB_BASE_ENTRY = "index";
32
32
  * build (JS and the dts plugin share it), so a single pass cannot give per-module JS + bundled
33
33
  * dts. Per-module dts breaks type portability (TS2883); bundling the JS re-bundles workspace
34
34
  * consumers. The split keeps per-module JS AND rolled-up, self-contained declarations.
35
+ *
36
+ * **The JS pass's `unbundle` flips to `false` for a `bundleNodeModules` partition** (see
37
+ * `DerivedTsdownOptions` in `target-groups.ts`), so that partition's JS pass ALSO bundles
38
+ * instead of preserving modules — a per-module preserveModules JS pass writes every inlined
39
+ * node_modules dependency to its own sibling file (mirroring its `node_modules/...` path),
40
+ * which `npm pack` then strips, breaking the "self-contained" promise `bundleNodeModules`
41
+ * already makes. Scoped to that flag alone; every other build's JS pass is unaffected.
35
42
  * @public
36
43
  */
37
44
  async function buildTargetGroups(options) {
@@ -45,6 +52,7 @@ async function buildTargetGroups(options) {
45
52
  customLogger: createTsdownLogger(collector, groupId)
46
53
  };
47
54
  const metricsPlugins = (groupId, pass) => collector === void 0 ? [] : [buildMetricsPlugin(collector, groupId, pass, verbose)];
55
+ const timingChecks = { checks: { pluginTimings: verbose } };
48
56
  const timed = async (groupId, pass, run) => {
49
57
  const timer = createTimer();
50
58
  try {
@@ -81,6 +89,7 @@ async function buildTargetGroups(options) {
81
89
  tsconfigPath: dtsEmitTsconfigPath,
82
90
  devManifest: options.devManifest,
83
91
  ...partExternals !== void 0 ? { externals: partExternals } : {},
92
+ ...partBundleNodeModules !== void 0 ? { bundleNodeModules: partBundleNodeModules } : {},
84
93
  ...partBundledPackages !== void 0 ? { bundledPackages: partBundledPackages } : {},
85
94
  ...part.format !== void 0 ? { format: part.format } : {},
86
95
  ...options.minify !== void 0 ? { minify: options.minify } : {},
@@ -126,6 +135,7 @@ async function buildTargetGroups(options) {
126
135
  fixedExtension: js.fixedExtension,
127
136
  dts: js.dts,
128
137
  define: js.define,
138
+ ...timingChecks,
129
139
  ...instrument(group.id),
130
140
  ...part.css !== void 0 ? { css: part.css } : {},
131
141
  ...partExternals?.length || partBundleNodeModules || partBundle?.length ? { deps: {
@@ -218,6 +228,7 @@ async function buildTargetGroups(options) {
218
228
  fixedExtension: dts.fixedExtension,
219
229
  dts: dts.dts,
220
230
  define: dts.define,
231
+ ...timingChecks,
221
232
  ...instrument(group.id),
222
233
  ...dtsDeps,
223
234
  plugins: [
@@ -244,6 +255,7 @@ async function buildTargetGroups(options) {
244
255
  fixedExtension: decl.fixedExtension,
245
256
  dts: decl.dts,
246
257
  define: decl.define,
258
+ ...timingChecks,
247
259
  logLevel: "silent",
248
260
  ...dtsNeverBundle.length > 0 || partBundleNodeModules || decl.bundledPackages ? { deps: {
249
261
  ...dtsNeverBundle.length > 0 ? { neverBundle: dtsNeverBundle } : {},
@@ -292,6 +304,7 @@ async function buildTargetGroups(options) {
292
304
  "process.env.__PACKAGE_VERSION__": JSON.stringify(options.version),
293
305
  ...options.define
294
306
  },
307
+ ...timingChecks,
295
308
  ...instrument(group.id),
296
309
  ...Object.keys(looseDeps).length > 0 ? { deps: looseDeps } : {},
297
310
  ...hasCjs ? { cjsDefault: true } : {},
@@ -23,7 +23,7 @@ function deriveTargetGroupOptions(options) {
23
23
  sourcemap: !isProd,
24
24
  minify: isProd && (options.minify ?? false),
25
25
  format,
26
- unbundle: true,
26
+ unbundle: !(options.bundleNodeModules ?? false),
27
27
  clean: true,
28
28
  platform: options.platform ?? "node",
29
29
  fixedExtension: false,
package/index.d.ts CHANGED
@@ -403,6 +403,13 @@ interface DeriveOptions {
403
403
  * runtime JS bundling is unaffected.
404
404
  */
405
405
  readonly bundledPackages?: ReadonlyArray<string> | undefined;
406
+ /**
407
+ * Force-bundle node_modules (and workspace) JS dependencies into the JS pass (tsdown
408
+ * `deps.skipNodeModulesBundle: false`). Consumed here ONLY to decide the JS pass's
409
+ * `unbundle` posture — see {@link DerivedTsdownOptions.unbundle} — the `deps` shape
410
+ * itself is computed separately in `buildTargetGroups`.
411
+ */
412
+ readonly bundleNodeModules?: boolean | undefined;
406
413
  }
407
414
  /**
408
415
  * The JS pass: per-module JavaScript, no declarations.
@@ -420,6 +427,22 @@ interface DeriveOptions {
420
427
  * the JS re-bundles workspace consumers (e.g. silk re-bundling silk-effects crashes at
421
428
  * runtime). The split keeps per-module JS (no re-bundle hazard) AND bundled, self-contained
422
429
  * declarations (no TS2883).
430
+ *
431
+ * **`unbundle` flips to `false` when `bundleNodeModules` is set.** `bundleNodeModules: true`
432
+ * exists to produce a genuinely self-contained artifact (its own TSDoc already promises this),
433
+ * but `preserveModules` (the per-module JS pass) writes every inlined node_modules dependency
434
+ * out to its OWN sibling file, mirroring its `node_modules/.pnpm/...` (or workspace) path
435
+ * relative to the package root — for BOTH esm and cjs. `npm pack` unconditionally strips any
436
+ * directory literally named `node_modules` from the published tarball, so an esm entry built
437
+ * this way throws `Cannot find module '.../node_modules/.pnpm/.../foo.js'` once packed and
438
+ * installed (the cjs sibling accidentally escapes this: tsdown's own dts pass, which always
439
+ * runs `unbundle: false`, re-emits and overwrites a dual-format build's `.cjs` JS chunk as a
440
+ * side effect of emitting `.d.cts` — see the dts-pass rebuild note in `buildTargetGroups` — so
441
+ * only the esm artifact keeps the broken preserveModules layout). Turning `unbundle` off for
442
+ * the JS pass whenever `bundleNodeModules` is requested makes BOTH formats bundle into one
443
+ * self-contained file, matching what the flag already promises and what the cjs side already
444
+ * does by accident. Scoped to `bundleNodeModules` alone: every other build keeps the default
445
+ * per-module dev-friendly layout unchanged.
423
446
  * @public
424
447
  */
425
448
  interface DerivedTsdownOptions {
@@ -427,7 +450,8 @@ interface DerivedTsdownOptions {
427
450
  readonly sourcemap: boolean;
428
451
  readonly minify: boolean;
429
452
  readonly format: ReadonlyArray<BuildFormat>;
430
- readonly unbundle: true;
453
+ /** `false` only when `bundleNodeModules` is set — see the interface TSDoc above. */
454
+ readonly unbundle: boolean;
431
455
  /** JS pass starts fresh; it owns the outDir before the dts pass appends to it. */
432
456
  readonly clean: true;
433
457
  readonly platform: BuildPlatform;
@@ -700,6 +724,13 @@ interface BuildTargetGroupsOptions {
700
724
  * build (JS and the dts plugin share it), so a single pass cannot give per-module JS + bundled
701
725
  * dts. Per-module dts breaks type portability (TS2883); bundling the JS re-bundles workspace
702
726
  * consumers. The split keeps per-module JS AND rolled-up, self-contained declarations.
727
+ *
728
+ * **The JS pass's `unbundle` flips to `false` for a `bundleNodeModules` partition** (see
729
+ * `DerivedTsdownOptions` in `target-groups.ts`), so that partition's JS pass ALSO bundles
730
+ * instead of preserving modules — a per-module preserveModules JS pass writes every inlined
731
+ * node_modules dependency to its own sibling file (mirroring its `node_modules/...` path),
732
+ * which `npm pack` then strips, breaking the "self-contained" promise `bundleNodeModules`
733
+ * already makes. Scoped to that flag alone; every other build's JS pass is unaffected.
703
734
  * @public
704
735
  */
705
736
  declare function buildTargetGroups(options: BuildTargetGroupsOptions): Promise<void>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@savvy-web/tsdown-plugins",
3
- "version": "1.1.4",
3
+ "version": "1.1.5",
4
4
  "private": false,
5
5
  "description": "Interface-only tsdown/rolldown plugin pack powering @savvy-web/bundler",
6
6
  "homepage": "https://github.com/savvy-web/systems/tree/main/packages/tsdown-plugins",