@hyperfrontend/builder 0.1.0 → 0.1.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/_dependencies/@hyperfrontend/project-scope/core/fs/index.cjs.js +10 -3
  3. package/_dependencies/@hyperfrontend/project-scope/core/fs/index.esm.js +10 -3
  4. package/_dependencies/@hyperfrontend/project-scope/core/index.cjs.js +16 -6
  5. package/_dependencies/@hyperfrontend/project-scope/core/index.esm.js +16 -6
  6. package/_dependencies/@hyperfrontend/project-scope/core/path/index.cjs.js +4 -5
  7. package/_dependencies/@hyperfrontend/project-scope/core/path/index.esm.js +5 -4
  8. package/_dependencies/@hyperfrontend/project-scope/project/root/index.cjs.js +5 -1
  9. package/_dependencies/@hyperfrontend/project-scope/project/root/index.esm.js +5 -1
  10. package/bin/hf-build.js +110 -82
  11. package/bin/hf-build.linux-x64 +0 -0
  12. package/bin/index.cjs.js +82 -36
  13. package/bin/index.esm.js +82 -36
  14. package/bin/script/index.cjs.js +91 -45
  15. package/bin/script/index.esm.js +81 -35
  16. package/bundle/declarations/dts-per-entry.d.ts.map +1 -1
  17. package/bundle/declarations/dts-pre-pass.d.ts.map +1 -1
  18. package/bundle/declarations/index.cjs.js +118 -72
  19. package/bundle/declarations/index.esm.js +83 -37
  20. package/bundle/dependencies/index.cjs.js +95 -49
  21. package/bundle/dependencies/index.d.ts +13 -24
  22. package/bundle/dependencies/index.esm.js +79 -33
  23. package/bundle/dependencies/pre-pass.d.ts +13 -24
  24. package/bundle/dependencies/pre-pass.d.ts.map +1 -1
  25. package/bundle/index.cjs.js +203 -175
  26. package/bundle/index.esm.js +107 -79
  27. package/bundle/rollup/dispatch.d.ts +12 -14
  28. package/bundle/rollup/dispatch.d.ts.map +1 -1
  29. package/bundle/rollup/index.cjs.js +75 -29
  30. package/bundle/rollup/index.d.ts +14 -16
  31. package/bundle/rollup/index.esm.js +76 -30
  32. package/bundle/worker-locator.d.ts +47 -0
  33. package/bundle/worker-locator.d.ts.map +1 -0
  34. package/index.cjs.js +112 -84
  35. package/index.esm.js +113 -85
  36. package/package.json +31 -3
@@ -1,10 +1,10 @@
1
1
  'use strict';
2
2
 
3
3
  const index_cjs_js$3 = require('../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/array/index.cjs.js');
4
- const index_cjs_js$7 = require('../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/error/index.cjs.js');
4
+ const index_cjs_js$4 = require('../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/error/index.cjs.js');
5
5
  const index_cjs_js$2 = require('../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/set/index.cjs.js');
6
- const index_cjs_js$4 = require('../_dependencies/@hyperfrontend/logging/index.cjs.js');
7
- const index_cjs_js$5 = require('../_dependencies/@hyperfrontend/project-scope/core/index.cjs.js');
6
+ const index_cjs_js$5 = require('../_dependencies/@hyperfrontend/logging/index.cjs.js');
7
+ const index_cjs_js$6 = require('../_dependencies/@hyperfrontend/project-scope/core/index.cjs.js');
8
8
  const index_cjs_js = require('../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/promise/index.cjs.js');
9
9
  const index_cjs_js$1 = require('../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/timers/index.cjs.js');
10
10
  const node_module = require('node:module');
@@ -12,7 +12,7 @@ const node_path = require('node:path');
12
12
  const node_child_process = require('node:child_process');
13
13
  const node_fs = require('node:fs');
14
14
  const node_os = require('node:os');
15
- const index_cjs_js$6 = require('../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/json/index.cjs.js');
15
+ const index_cjs_js$7 = require('../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/json/index.cjs.js');
16
16
  const index_cjs_js$8 = require('../_dependencies/@hyperfrontend/project-scope/core/fs/index.cjs.js');
17
17
  const index_cjs_js$9 = require('../_dependencies/@hyperfrontend/project-scope/core/path/index.cjs.js');
18
18
  const index_cjs_js$a = require('../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/date/index.cjs.js');
@@ -37,13 +37,77 @@ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'defau
37
37
 
38
38
  const ts__default = /*#__PURE__*/_interopDefaultCompat(ts);
39
39
 
40
- const log$b = index_cjs_js$4.logger.channel('builder:bundle:dependencies:pre-pass');
40
+ const SWC_NODE_REGISTER = '@swc-node/register';
41
+ const probeDir = (dir, offset) => {
42
+ const compiled = node_path.join(dir, ...offset, 'index.cjs.js');
43
+ if (node_fs.existsSync(compiled))
44
+ return { path: compiled, execArgv: [] };
45
+ const source = node_path.join(dir, ...offset, 'index.ts');
46
+ if (node_fs.existsSync(source))
47
+ return { path: source, execArgv: ['--require', SWC_NODE_REGISTER] };
48
+ return undefined;
49
+ };
50
+ /**
51
+ * Directory of the currently-executing builder module, read from `__dirname`.
52
+ * It is present in the shipped CommonJS build, in the `@swc-node/register` source
53
+ * bootstrap, and under the test runner, so callers get their own on-disk location
54
+ * and can find the worker beside them however the builder was packaged.
55
+ *
56
+ * @returns Absolute directory path of the running module.
57
+ *
58
+ * @example Anchoring a lookup beside the running builder
59
+ * ```typescript
60
+ * const invocation = ascendForWorker(['bundle', 'rollup', 'worker'], currentModuleDir())
61
+ * ```
62
+ */
63
+ const currentModuleDir = () => {
64
+ /* istanbul ignore if -- @preserve the ESM build has no __dirname; the shipped CommonJS build and the test runner always define it, so this guard is unreachable under test */
65
+ if (typeof __dirname === 'undefined') {
66
+ throw index_cjs_js$4.createError('@hyperfrontend/builder self-location requires the CommonJS build; drive build() from the CommonJS entry point');
67
+ }
68
+ return __dirname;
69
+ };
70
+ /**
71
+ * Locate a builder worker entry by ascending from a start directory toward the
72
+ * filesystem root, returning the first ancestor at which the worker exists at the
73
+ * given in-package offset. The compiled `index.cjs.js` is preferred; an `index.ts`
74
+ * sibling (source-mode bootstrap) resolves with the swc loader attached.
75
+ *
76
+ * The worker ships inside the builder's own package, so resolving relative to the
77
+ * running module finds it wherever the package lives — built dist, an installed
78
+ * `node_modules` copy, or melded into a host bundle under `_dependencies/`.
79
+ *
80
+ * @param offset - In-package path segments to the worker directory (e.g. `['bundle', 'rollup', 'worker']`).
81
+ * @param startDir - Directory to begin the ascent from. Defaults to the running module's directory; pass an explicit value to resolve from another anchor or under test.
82
+ * @returns The resolved worker invocation, or `undefined` if no worker exists at the offset under any ancestor.
83
+ *
84
+ * @example Resolving the rollup worker from the running module
85
+ * ```typescript
86
+ * const invocation = ascendForWorker(['bundle', 'rollup', 'worker'])
87
+ * if (!invocation) throw new Error('builder rollup worker not found beside the builder module')
88
+ * ```
89
+ */
90
+ const ascendForWorker = (offset, startDir = currentModuleDir()) => {
91
+ let dir = startDir;
92
+ let parent = node_path.dirname(dir);
93
+ // how: probe each level then step up; the final probe covers the filesystem root, where parent === dir
94
+ while (parent !== dir) {
95
+ const found = probeDir(dir, offset);
96
+ if (found)
97
+ return found;
98
+ dir = parent;
99
+ parent = node_path.dirname(dir);
100
+ }
101
+ return probeDir(dir, offset);
102
+ };
103
+
104
+ const log$b = index_cjs_js$5.logger.channel('builder:bundle:dependencies:pre-pass');
41
105
  const REPORT_DIR_PREFIX$1 = 'hf-builder-prepass-';
42
- const createReportDir$1 = () => node_fs.mkdtempSync(index_cjs_js$5.join(node_os.tmpdir(), REPORT_DIR_PREFIX$1));
43
- const reportPathFor$1 = (reportDir, job, index) => index_cjs_js$5.join(reportDir, `${index}-${job.dep.replace(/\//g, '__')}-${job.kind}-${job.format}.json`);
106
+ const createReportDir$1 = () => node_fs.mkdtempSync(index_cjs_js$6.join(node_os.tmpdir(), REPORT_DIR_PREFIX$1));
107
+ const reportPathFor$1 = (reportDir, job, index) => index_cjs_js$6.join(reportDir, `${index}-${job.dep.replace(/\//g, '__')}-${job.kind}-${job.format}.json`);
44
108
  const runOne$1 = (job, reportPath, options) => index_cjs_js.createPromise((resolve, reject) => {
45
109
  const execPath = options.execPath ?? process.execPath;
46
- const argv = [...(options.execArgv ?? []), options.workerPath, index_cjs_js$6.stringify({ ...job, reportPath })];
110
+ const argv = [...(options.execArgv ?? []), options.workerPath, index_cjs_js$7.stringify({ ...job, reportPath })];
47
111
  const child = node_child_process.spawn(execPath, argv, { stdio: ['ignore', 'pipe', 'pipe'] });
48
112
  let capturedStderr = '';
49
113
  child.stdout?.on('data', (chunk) => {
@@ -55,12 +119,12 @@ const runOne$1 = (job, reportPath, options) => index_cjs_js.createPromise((resol
55
119
  process.stderr.write(text);
56
120
  });
57
121
  child.on('error', (error) => {
58
- reject(index_cjs_js$7.createError(`pre-pass worker for ${job.dep} (${job.kind}/${job.format}) failed to spawn: ${error.message}`));
122
+ reject(index_cjs_js$4.createError(`pre-pass worker for ${job.dep} (${job.kind}/${job.format}) failed to spawn: ${error.message}`));
59
123
  });
60
124
  child.on('exit', (code) => {
61
125
  if (code !== 0) {
62
126
  const tail = capturedStderr.trim().split('\n').slice(-10).join('\n');
63
- reject(index_cjs_js$7.createError(`pre-pass worker for ${job.dep} (${job.kind}/${job.format}) exited with code ${code}\n${tail}`));
127
+ reject(index_cjs_js$4.createError(`pre-pass worker for ${job.dep} (${job.kind}/${job.format}) exited with code ${code}\n${tail}`));
64
128
  return;
65
129
  }
66
130
  resolve();
@@ -68,48 +132,30 @@ const runOne$1 = (job, reportPath, options) => index_cjs_js.createPromise((resol
68
132
  });
69
133
  const readReport$1 = (reportPath, job) => {
70
134
  if (!node_fs.existsSync(reportPath)) {
71
- throw index_cjs_js$7.createError(`pre-pass worker for ${job.dep} (${job.kind}/${job.format}) did not write a report at ${reportPath}`);
135
+ throw index_cjs_js$4.createError(`pre-pass worker for ${job.dep} (${job.kind}/${job.format}) did not write a report at ${reportPath}`);
72
136
  }
73
- const data = index_cjs_js$6.parse(node_fs.readFileSync(reportPath, 'utf8'));
137
+ const data = index_cjs_js$7.parse(node_fs.readFileSync(reportPath, 'utf8'));
74
138
  return { job, outputSize: data.outputSize, endHeapMB: data.endHeapMB, endRssMB: data.endRssMB, durationMs: data.durationMs };
75
139
  };
76
- const SWC_NODE_REGISTER$1 = '@swc-node/register';
77
- const swcNodeAvailable$1 = (workspaceRoot) => node_fs.existsSync(index_cjs_js$5.join(workspaceRoot, 'node_modules', '@swc-node', 'register', 'index.js'));
78
140
  /**
79
- * Default worker-path resolution: prefers the built-and-published artifact, falls
80
- * back to the workspace dist path, and finally to the in-source TypeScript file
81
- * via `@swc-node/register` (bootstrap case where builder is building itself for
82
- * the first time and the dist worker doesn't exist yet).
83
- *
84
- * Looks at, in order:
85
- * 1. `<workspaceRoot>/dist/libs/builder/bundle/dependencies/worker/index.cjs.js`
86
- * 2. `<workspaceRoot>/node_modules/@hyperfrontend/builder/bundle/dependencies/worker/index.cjs.js`
87
- * 3. `<workspaceRoot>/libs/builder/src/bundle/dependencies/worker/index.ts` (with `--require \@swc-node/register`)
88
- *
89
- * @param workspaceRoot - Absolute workspace root.
90
- * @returns Worker invocation descriptor, or `undefined` if no candidate exists.
91
- *
92
- * @example Locating the worker for an in-workspace consumer
141
+ * Resolves the dependency pre-pass worker by self-locating it beside the running
142
+ * builder module: ascends from the module's own directory to the builder package
143
+ * root and returns the worker at `bundle/dependencies/worker`. This works whether
144
+ * the builder runs from its built dist, an installed `node_modules` copy, or
145
+ * melded into a host bundle under `_dependencies/`. The compiled `index.cjs.js`
146
+ * is preferred; an `index.ts` sibling resolves with the `@swc-node/register`
147
+ * loader for source-mode bootstrap.
148
+ *
149
+ * @param startDir - Directory to begin the ascent from. Defaults to the running module's directory; pass an explicit value to resolve from another anchor or under test.
150
+ * @returns Worker invocation descriptor, or `undefined` if no worker is found under any ancestor.
151
+ *
152
+ * @example Locating the worker beside the builder
93
153
  * ```typescript
94
- * const invocation = resolveDefaultWorkerPath('/abs/repo')
154
+ * const invocation = resolveDefaultWorkerPath()
95
155
  * if (!invocation) throw new Error('builder worker artifact not found')
96
156
  * ```
97
157
  */
98
- const resolveDefaultWorkerPath = (workspaceRoot) => {
99
- const distCandidates = [
100
- index_cjs_js$5.join(workspaceRoot, 'dist', 'libs', 'builder', 'bundle', 'dependencies', 'worker', 'index.cjs.js'),
101
- index_cjs_js$5.join(workspaceRoot, 'node_modules', '@hyperfrontend', 'builder', 'bundle', 'dependencies', 'worker', 'index.cjs.js'),
102
- ];
103
- for (const path of distCandidates) {
104
- if (node_fs.existsSync(path))
105
- return { path, execArgv: [] };
106
- }
107
- const sourcePath = index_cjs_js$5.join(workspaceRoot, 'libs', 'builder', 'src', 'bundle', 'dependencies', 'worker', 'index.ts');
108
- if (node_fs.existsSync(sourcePath) && swcNodeAvailable$1(workspaceRoot)) {
109
- return { path: sourcePath, execArgv: ['--require', SWC_NODE_REGISTER$1] };
110
- }
111
- return undefined;
112
- };
158
+ const resolveDefaultWorkerPath = (startDir) => ascendForWorker(['bundle', 'dependencies', 'worker'], startDir);
113
159
  /**
114
160
  * Sequentially runs the supplied pre-pass jobs by forking a fresh Node child
115
161
  * per invocation. Strict sequential execution is mandatory — concurrent
@@ -170,14 +216,14 @@ const runPrePass = async (jobs, options) => {
170
216
  */
171
217
  const dtsPathFor = (outputPath, srcPath) => srcPath ? join(outputPath, srcPath, 'index.d.ts') : join(outputPath, 'index.d.ts');
172
218
 
173
- const log$a = index_cjs_js$4.logger.channel('builder:bundle:declarations:dts-per-entry');
219
+ const log$a = index_cjs_js$5.logger.channel('builder:bundle:declarations:dts-per-entry');
174
220
  const buildSiblingDescriptors = (entries, context, currentSrcPath) => {
175
221
  const descriptors = [];
176
222
  for (const entry of entries) {
177
223
  if (entry.srcPath === currentSrcPath)
178
224
  continue;
179
225
  const indexDtsPath = dtsPathFor(context.outputPath, entry.srcPath);
180
- if (!index_cjs_js$5.exists(indexDtsPath))
226
+ if (!index_cjs_js$6.exists(indexDtsPath))
181
227
  continue;
182
228
  descriptors.push({ srcPath: entry.srcPath, indexDtsPath });
183
229
  }
@@ -191,7 +237,7 @@ const buildJobs$1 = (entries, context) => {
191
237
  const depsRoot = depsRootOf(context);
192
238
  for (const entry of entries) {
193
239
  const inputPath = dtsPathFor(context.outputPath, entry.srcPath);
194
- if (!index_cjs_js$5.exists(inputPath))
240
+ if (!index_cjs_js$6.exists(inputPath))
195
241
  continue;
196
242
  const siblingEntries = buildSiblingDescriptors(entries, context, entry.srcPath);
197
243
  jobs.push({
@@ -238,9 +284,9 @@ const buildJobs$1 = (entries, context) => {
238
284
  const runDtsPerEntry = async (context, monitor) => {
239
285
  if (context.bundledDeps.length === 0 && context.workspaceBundledDeps.length === 0)
240
286
  return;
241
- const invocation = resolveDefaultWorkerPath(context.workspaceRoot);
287
+ const invocation = resolveDefaultWorkerPath();
242
288
  if (!invocation) {
243
- throw index_cjs_js$7.createError('bundleAllDeps is enabled but the pre-pass worker artifact was not found for the per-entry d.ts pass.');
289
+ throw index_cjs_js$4.createError('bundleAllDeps is enabled but the pre-pass worker could not be located beside the builder module for the per-entry d.ts pass.');
244
290
  }
245
291
  const jobs = buildJobs$1(context.entryPointDiscovery.entryPoints, context);
246
292
  if (jobs.length === 0) {
@@ -334,17 +380,17 @@ const resolveDepEntry = (options) => {
334
380
  const { dep, projectRoot, workspaceRoot, kind } = options;
335
381
  const pkgPath = findPackageJsonViaRequire(dep, ROOTS(projectRoot, workspaceRoot));
336
382
  if (!pkgPath)
337
- throw index_cjs_js$7.createError(`pre-pass: cannot locate package.json for dep "${dep}"`);
383
+ throw index_cjs_js$4.createError(`pre-pass: cannot locate package.json for dep "${dep}"`);
338
384
  const pkg = index_cjs_js$8.readJsonFileIfExists(pkgPath);
339
385
  if (!pkg)
340
- throw index_cjs_js$7.createError(`pre-pass: package.json for dep "${dep}" could not be read at ${pkgPath}`);
386
+ throw index_cjs_js$4.createError(`pre-pass: package.json for dep "${dep}" could not be read at ${pkgPath}`);
341
387
  const relative = kind === 'js' ? ensureJsEntry(pkg) : ensureDtsEntry(pkg);
342
388
  if (!relative)
343
- throw index_cjs_js$7.createError(`pre-pass: dep "${dep}" has no ${kind === 'js' ? 'main/module' : 'types/typings'} entry`);
389
+ throw index_cjs_js$4.createError(`pre-pass: dep "${dep}" has no ${kind === 'js' ? 'main/module' : 'types/typings'} entry`);
344
390
  return absolutize(node_path.dirname(pkgPath), relative);
345
391
  };
346
392
 
347
- const log$9 = index_cjs_js$4.logger.channel('builder:bundle:declarations:dts-pre-pass');
393
+ const log$9 = index_cjs_js$5.logger.channel('builder:bundle:declarations:dts-pre-pass');
348
394
  const workspaceDtsOutputFile = (entry) => entry.subPath ? `${entry.specifier}/index.d.ts` : `${entry.packageName}/index.d.ts`;
349
395
  const filterRouteEntries$1 = (entry, all) => all.filter((other) => (entry.policy === 'sub-path' ? other.specifier !== entry.specifier : other.packageName !== entry.packageName));
350
396
  const buildJobs = (deps, context) => {
@@ -368,7 +414,7 @@ const buildJobs = (deps, context) => {
368
414
  dep,
369
415
  inputPath,
370
416
  format: 'esm',
371
- outputPath: index_cjs_js$5.join(depsRoot, dep, 'index.d.ts'),
417
+ outputPath: index_cjs_js$6.join(depsRoot, dep, 'index.d.ts'),
372
418
  otherDeps: [...otherNpmDeps, ...workspacePrefixDeps],
373
419
  otherWorkspaceSpecifiers: workspaceExactSpecifiers,
374
420
  npmDeps: otherNpmDeps,
@@ -394,7 +440,7 @@ const buildWorkspaceJobs = (context, npmDeps) => {
394
440
  dep: entry.specifier,
395
441
  inputPath: entry.inputPath,
396
442
  format: 'esm',
397
- outputPath: index_cjs_js$5.join(depsRoot, workspaceDtsOutputFile(entry)),
443
+ outputPath: index_cjs_js$6.join(depsRoot, workspaceDtsOutputFile(entry)),
398
444
  otherDeps: [...npmDeps, ...otherWorkspacePackages],
399
445
  otherWorkspaceSpecifiers: otherSubPathSpecifiers,
400
446
  tsConfigPath: entry.tsConfigPath,
@@ -423,9 +469,9 @@ const buildWorkspaceJobs = (context, npmDeps) => {
423
469
  const runDtsPrePass = async (context, monitor) => {
424
470
  if (context.bundledDeps.length === 0 && context.workspaceBundledDeps.length === 0)
425
471
  return;
426
- const invocation = resolveDefaultWorkerPath(context.workspaceRoot);
472
+ const invocation = resolveDefaultWorkerPath();
427
473
  if (!invocation) {
428
- throw index_cjs_js$7.createError('bundleAllDeps is enabled but the pre-pass worker artifact was not found for the d.ts pre-pass.');
474
+ throw index_cjs_js$4.createError('bundleAllDeps is enabled but the pre-pass worker could not be located beside the builder module for the d.ts pre-pass.');
429
475
  }
430
476
  const npmJobs = buildJobs(context.bundledDeps, context);
431
477
  const workspaceJobs = buildWorkspaceJobs(context, context.bundledDeps);
@@ -440,7 +486,7 @@ const runDtsPrePass = async (context, monitor) => {
440
486
  monitor?.check('bundle:declarations:dts-prepass:end');
441
487
  };
442
488
 
443
- const log$8 = index_cjs_js$4.logger.channel('builder:bundle:declarations');
489
+ const log$8 = index_cjs_js$5.logger.channel('builder:bundle:declarations');
444
490
  const HEARTBEAT_INTERVAL_MS = 5000;
445
491
  const BYTES_PER_MB = 1024 * 1024;
446
492
  const formatMB = (bytes) => (bytes / BYTES_PER_MB).toFixed(1);
@@ -477,7 +523,7 @@ const runTsc = (tscPath, args, cwd) => index_cjs_js.createPromise((resolve, reje
477
523
  const durationMs = index_cjs_js$a.dateNow() - startedAt;
478
524
  if (code !== 0) {
479
525
  log$8.error(`tsc failed with exit code ${code} after ${durationMs}ms`);
480
- reject(index_cjs_js$7.createError(`tsc failed with exit code ${code}`));
526
+ reject(index_cjs_js$4.createError(`tsc failed with exit code ${code}`));
481
527
  return;
482
528
  }
483
529
  log$8.info(`tsc exited 0 in ${durationMs}ms`);
@@ -527,7 +573,7 @@ const generateDeclarations = async (context) => {
527
573
  return result;
528
574
  };
529
575
 
530
- const log$7 = index_cjs_js$4.logger.channel('builder:bundle:declarations:prune-orphans');
576
+ const log$7 = index_cjs_js$5.logger.channel('builder:bundle:declarations:prune-orphans');
531
577
  const ORPHAN_DTS_RE = /\.d\.ts$|\.d\.ts\.map$/;
532
578
  const INDEX_DTS_NAME = 'index.d.ts';
533
579
  /**
@@ -548,13 +594,13 @@ const INDEX_DTS_NAME = 'index.d.ts';
548
594
  * @returns Absolute `.d.ts` path of the referenced sibling, or `null`.
549
595
  */
550
596
  const toDtsTarget$1 = (dir, spec, depsRoot) => {
551
- const abs = index_cjs_js$5.join(dir, spec);
597
+ const abs = index_cjs_js$6.join(dir, spec);
552
598
  // why: a `.js` specifier is the bundled-dep routing shape; map it onto its declaration sibling.
553
- const candidates = spec.endsWith('.js') ? [`${abs.slice(0, -3)}.d.ts`] : [`${abs}.d.ts`, index_cjs_js$5.join(abs, INDEX_DTS_NAME)];
599
+ const candidates = spec.endsWith('.js') ? [`${abs.slice(0, -3)}.d.ts`] : [`${abs}.d.ts`, index_cjs_js$6.join(abs, INDEX_DTS_NAME)];
554
600
  for (const candidate of candidates) {
555
601
  if (isUnderDir(candidate, depsRoot))
556
602
  return null;
557
- if (index_cjs_js$5.exists(candidate))
603
+ if (index_cjs_js$6.exists(candidate))
558
604
  return candidate;
559
605
  }
560
606
  return null;
@@ -582,7 +628,7 @@ const computeReachableDeclarations = (roots, depsRoot) => {
582
628
  const reachable = index_cjs_js$2.createSet([]);
583
629
  const queue = [];
584
630
  for (const root of roots) {
585
- if (index_cjs_js$5.exists(root) && !reachable.has(root)) {
631
+ if (index_cjs_js$6.exists(root) && !reachable.has(root)) {
586
632
  reachable.add(root);
587
633
  queue.push(root);
588
634
  }
@@ -592,12 +638,12 @@ const computeReachableDeclarations = (roots, depsRoot) => {
592
638
  const file = queue[head];
593
639
  head += 1;
594
640
  // why: every queued path was `exists`-checked before enqueue (roots and `toDtsTarget` targets), so a direct read is safe.
595
- const source = index_cjs_js$5.readFileContent(file);
641
+ const source = index_cjs_js$6.readFileContent(file);
596
642
  if (hasDynamicSpecifier(source)) {
597
643
  log$7.warn(`dynamic import/require in ${file}; keeping all orphan declarations for safety`);
598
644
  return null;
599
645
  }
600
- const dir = index_cjs_js$5.getDirname(file);
646
+ const dir = index_cjs_js$6.getDirname(file);
601
647
  for (const spec of collectChunkSpecifiers(source)) {
602
648
  const target = toDtsTarget$1(dir, spec, depsRoot);
603
649
  if (target !== null && !reachable.has(target)) {
@@ -619,10 +665,10 @@ const computeReachableDeclarations = (roots, depsRoot) => {
619
665
  */
620
666
  const collectDeclarationFiles = (root, depsRoot) => {
621
667
  const files = [];
622
- if (!index_cjs_js$5.exists(root))
668
+ if (!index_cjs_js$6.exists(root))
623
669
  return files;
624
670
  const visit = (dir) => {
625
- for (const entry of index_cjs_js$5.readDirectory(dir)) {
671
+ for (const entry of index_cjs_js$6.readDirectory(dir)) {
626
672
  if (entry.isDirectory) {
627
673
  if (isUnderDir(entry.path, depsRoot))
628
674
  continue;
@@ -673,7 +719,7 @@ const pruneOrphanDeclarations = (context) => {
673
719
  const dir = entryDirOf(entry, context);
674
720
  if (isUnderDir(dir, depsRoot))
675
721
  continue;
676
- roots.push(index_cjs_js$5.join(dir, INDEX_DTS_NAME));
722
+ roots.push(index_cjs_js$6.join(dir, INDEX_DTS_NAME));
677
723
  }
678
724
  const reachable = computeReachableDeclarations(roots, depsRoot);
679
725
  if (reachable === null)
@@ -726,7 +772,7 @@ const parseChunk = (source) => ts__default.default.createSourceFile('chunk.js',
726
772
  * // => '/dist/libs/foo/_dependencies/b/index.esm.js'
727
773
  * ```
728
774
  */
729
- const resolveRelativeTarget = (importerDir, specifier) => specifier.startsWith('.') ? index_cjs_js$5.join(importerDir, specifier) : null;
775
+ const resolveRelativeTarget = (importerDir, specifier) => specifier.startsWith('.') ? index_cjs_js$6.join(importerDir, specifier) : null;
730
776
  /**
731
777
  * Returns the literal specifier of a `require('…')` call expression, or `null`
732
778
  * when the node is not a single-string-literal `require` call.
@@ -1025,7 +1071,7 @@ const ownersFromSource = (source) => {
1025
1071
  return names;
1026
1072
  };
1027
1073
  const walkTsFiles = (dir, acc) => {
1028
- for (const entry of index_cjs_js$5.readDirectory(dir)) {
1074
+ for (const entry of index_cjs_js$6.readDirectory(dir)) {
1029
1075
  if (entry.isDirectory)
1030
1076
  walkTsFiles(entry.path, acc);
1031
1077
  else if (entry.name.endsWith('.ts') && !entry.name.endsWith('.d.ts') && !entry.name.endsWith('.spec.ts'))
@@ -1058,7 +1104,7 @@ const indexOwners = (srcRoot) => {
1058
1104
  const ownerOf = index_cjs_js$b.createMap();
1059
1105
  for (const file of files) {
1060
1106
  const moduleKey = toModuleKey(srcRoot, file);
1061
- for (const name of ownersFromSource(index_cjs_js$5.readFileContent(file))) {
1107
+ for (const name of ownersFromSource(index_cjs_js$6.readFileContent(file))) {
1062
1108
  if (ambiguous.has(name))
1063
1109
  continue;
1064
1110
  const prior = firstOwner.get(name);
@@ -1746,28 +1792,28 @@ const rewriteEntry = (parsed, hoists, format) => {
1746
1792
  return applyEdits$1(parsed.sourceFile.text, [...deletions, { start: parsed.headerEnd, end: parsed.headerEnd, text: insertion }]);
1747
1793
  };
1748
1794
 
1749
- const log$6 = index_cjs_js$4.logger.channel('builder:bundle:dedupe');
1795
+ const log$6 = index_cjs_js$5.logger.channel('builder:bundle:dedupe');
1750
1796
  const FORMATS = ['esm', 'cjs'];
1751
1797
  const toSpecifier = (relative) => (relative.startsWith('.') ? relative : `./${relative}`);
1752
1798
  const recomputeSpecifier = (specifier, fromDir, baseDir) =>
1753
1799
  // why: relative `_dependencies`/`_shared` edges move with the chunk; bare and node-builtin specifiers resolve identically from anywhere, so they pass through verbatim.
1754
- specifier.startsWith('.') ? toSpecifier(index_cjs_js$5.relativePath(fromDir, index_cjs_js$5.join(baseDir, specifier))) : specifier;
1800
+ specifier.startsWith('.') ? toSpecifier(index_cjs_js$6.relativePath(fromDir, index_cjs_js$6.join(baseDir, specifier))) : specifier;
1755
1801
  const locateEntries = (context, format) => {
1756
1802
  const locations = [];
1757
1803
  for (const entry of context.entryPointDiscovery.entryPoints) {
1758
1804
  const dir = entryDirOf(entry, context);
1759
- const file = index_cjs_js$5.join(dir, chunkFileName(format));
1760
- if (index_cjs_js$5.exists(file))
1805
+ const file = index_cjs_js$6.join(dir, chunkFileName(format));
1806
+ if (index_cjs_js$6.exists(file))
1761
1807
  locations.push({ dir, file });
1762
1808
  }
1763
1809
  return locations;
1764
1810
  };
1765
- const chunkFileFor = (context, moduleKey, format) => index_cjs_js$5.join(context.outputPath, sharedDirFor(moduleKey), chunkFileName(format));
1811
+ const chunkFileFor = (context, moduleKey, format) => index_cjs_js$6.join(context.outputPath, sharedDirFor(moduleKey), chunkFileName(format));
1766
1812
  const buildChunkPlan = (planned, context, chunkDir, canonicalDir, format) => {
1767
1813
  const crossImports = planned.resolution.crossModule.map((ref) => ({
1768
1814
  ref: ref.ref,
1769
1815
  exported: ref.base,
1770
- specifier: toSpecifier(index_cjs_js$5.relativePath(chunkDir, chunkFileFor(context, ref.moduleKey, format))),
1816
+ specifier: toSpecifier(index_cjs_js$6.relativePath(chunkDir, chunkFileFor(context, ref.moduleKey, format))),
1771
1817
  }));
1772
1818
  const depImports = planned.resolution.depImports.map((dep) => ({
1773
1819
  ref: dep.ref,
@@ -1779,11 +1825,11 @@ const buildChunkPlan = (planned, context, chunkDir, canonicalDir, format) => {
1779
1825
  };
1780
1826
  const writeChunks = (context, plan, locations, format, report) => {
1781
1827
  for (const [moduleKey, planned] of plan) {
1782
- const chunkDir = index_cjs_js$5.join(context.outputPath, sharedDirFor(moduleKey));
1828
+ const chunkDir = index_cjs_js$6.join(context.outputPath, sharedDirFor(moduleKey));
1783
1829
  const chunkPlan = buildChunkPlan(planned, context, chunkDir, locations[planned.canonicalEntryIndex].dir, format);
1784
1830
  const source = renderChunk(chunkPlan, format);
1785
- index_cjs_js$5.ensureDir(chunkDir);
1786
- index_cjs_js$5.writeFileContent(chunkFileFor(context, moduleKey, format), source);
1831
+ index_cjs_js$6.ensureDir(chunkDir);
1832
+ index_cjs_js$6.writeFileContent(chunkFileFor(context, moduleKey, format), source);
1787
1833
  report.chunksWritten += 1;
1788
1834
  report.bytesReclaimed -= Buffer.byteLength(source);
1789
1835
  }
@@ -1797,13 +1843,13 @@ const rewriteEntries = (context, plan, entries, locations, format, report) => {
1797
1843
  continue;
1798
1844
  hoists.push({
1799
1845
  decls,
1800
- specifier: toSpecifier(index_cjs_js$5.relativePath(locations[index].dir, chunkFileFor(context, moduleKey, format))),
1846
+ specifier: toSpecifier(index_cjs_js$6.relativePath(locations[index].dir, chunkFileFor(context, moduleKey, format))),
1801
1847
  });
1802
1848
  for (const decl of decls)
1803
1849
  report.bytesReclaimed += Buffer.byteLength(decl.text);
1804
1850
  }
1805
1851
  if (hoists.length > 0)
1806
- index_cjs_js$5.writeFileContent(locations[index].file, rewriteEntry(entry.parsed, hoists, format));
1852
+ index_cjs_js$6.writeFileContent(locations[index].file, rewriteEntry(entry.parsed, hoists, format));
1807
1853
  }
1808
1854
  };
1809
1855
  const processFormat$2 = (context, owners, format, report) => {
@@ -1811,7 +1857,7 @@ const processFormat$2 = (context, owners, format, report) => {
1811
1857
  if (locations.length < 2)
1812
1858
  return;
1813
1859
  const entries = locations.map((location) => {
1814
- const parsed = parseEntry(index_cjs_js$5.readFileContent(location.file), format);
1860
+ const parsed = parseEntry(index_cjs_js$6.readFileContent(location.file), format);
1815
1861
  return { parsed, byModule: attribute(parsed, owners) };
1816
1862
  });
1817
1863
  const plan = planHoists(entries, owners);
@@ -1846,8 +1892,8 @@ const processFormat$2 = (context, owners, format, report) => {
1846
1892
  */
1847
1893
  const hoistSharedFirstParty = (context, monitor) => {
1848
1894
  const report = { chunksWritten: 0, bytesReclaimed: 0 };
1849
- const srcRoot = index_cjs_js$5.join(context.projectRoot, 'src');
1850
- if (!index_cjs_js$5.exists(srcRoot))
1895
+ const srcRoot = index_cjs_js$6.join(context.projectRoot, 'src');
1896
+ if (!index_cjs_js$6.exists(srcRoot))
1851
1897
  return report;
1852
1898
  const owners = indexOwners(srcRoot);
1853
1899
  for (const format of FORMATS) {
@@ -1996,7 +2042,7 @@ const stripDeadExports = (source, format, keep) => {
1996
2042
  return { code: applyEdits(source, edits, true), removedNames: index_cjs_js$3.from(removedNames) };
1997
2043
  };
1998
2044
 
1999
- const log$5 = index_cjs_js$4.logger.channel('builder:bundle:dependencies:prune');
2045
+ const log$5 = index_cjs_js$5.logger.channel('builder:bundle:dependencies:prune');
2000
2046
  /**
2001
2047
  * Computes the set of files reachable from a set of root files by following
2002
2048
  * literal relative specifiers, restricted to targets under `depsRoot`.
@@ -2035,7 +2081,7 @@ const computeReachable = (roots, depsRoot, resolveTarget = (target) => target) =
2035
2081
  const reachable = index_cjs_js$2.createSet([]);
2036
2082
  const queue = [];
2037
2083
  for (const root of roots) {
2038
- if (index_cjs_js$5.exists(root) && !reachable.has(root)) {
2084
+ if (index_cjs_js$6.exists(root) && !reachable.has(root)) {
2039
2085
  reachable.add(root);
2040
2086
  queue.push(root);
2041
2087
  }
@@ -2044,16 +2090,16 @@ const computeReachable = (roots, depsRoot, resolveTarget = (target) => target) =
2044
2090
  while (head < queue.length) {
2045
2091
  const file = queue[head];
2046
2092
  head += 1;
2047
- const source = index_cjs_js$5.readFileContent(file);
2093
+ const source = index_cjs_js$6.readFileContent(file);
2048
2094
  // why: a dynamic specifier only threatens the sweep when it sits in a `_dependencies/` chunk, where it can hide an intra-deps edge to a sibling chunk we'd otherwise delete. First-party entry roots legitimately carry dynamic `import(<expr>)` (e.g. runtime config loading) whose targets are always external user paths — never bundled dep chunks — so bailing on those needlessly disables the entire sweep and strands emptied dep chunks. Roots are never under `depsRoot` (collectEntryFiles excludes them), so this scopes the bail to dep chunks only.
2049
2095
  if (isUnderDir(file, depsRoot) && hasDynamicSpecifier(source)) {
2050
2096
  log$5.warn(`dynamic import/require in ${file}; skipping dependency orphan prune for safety`);
2051
2097
  return null;
2052
2098
  }
2053
- const dir = index_cjs_js$5.getDirname(file);
2099
+ const dir = index_cjs_js$6.getDirname(file);
2054
2100
  for (const spec of collectChunkSpecifiers(source)) {
2055
- const target = resolveTarget(index_cjs_js$5.join(dir, spec));
2056
- if (isUnderDir(target, depsRoot) && index_cjs_js$5.exists(target) && !reachable.has(target)) {
2101
+ const target = resolveTarget(index_cjs_js$6.join(dir, spec));
2102
+ if (isUnderDir(target, depsRoot) && index_cjs_js$6.exists(target) && !reachable.has(target)) {
2057
2103
  reachable.add(target);
2058
2104
  queue.push(target);
2059
2105
  }
@@ -2087,8 +2133,8 @@ const collectEntryFiles = (context, depsRoot, fileNames) => {
2087
2133
  if (isUnderDir(dir, depsRoot))
2088
2134
  continue;
2089
2135
  for (const name of fileNames) {
2090
- const candidate = index_cjs_js$5.join(dir, name);
2091
- if (index_cjs_js$5.exists(candidate))
2136
+ const candidate = index_cjs_js$6.join(dir, name);
2137
+ if (index_cjs_js$6.exists(candidate))
2092
2138
  files.push(candidate);
2093
2139
  }
2094
2140
  }
@@ -2111,7 +2157,7 @@ const collectEntryFiles = (context, depsRoot, fileNames) => {
2111
2157
  */
2112
2158
  const walkFiles = (dir, matches, acc) => {
2113
2159
  // why: only ever called on the validated `_dependencies/` root or a directory from `readDirectory`, so the target always exists — no existence guard needed.
2114
- for (const entry of index_cjs_js$5.readDirectory(dir)) {
2160
+ for (const entry of index_cjs_js$6.readDirectory(dir)) {
2115
2161
  if (entry.isDirectory)
2116
2162
  walkFiles(entry.path, matches, acc);
2117
2163
  else if (matches(entry.name))
@@ -2124,7 +2170,7 @@ const unlinkWithMap = (path) => {
2124
2170
  let orphanFilesRemoved = 1;
2125
2171
  node_fs.unlinkSync(path);
2126
2172
  const mapPath = `${path}.map`;
2127
- if (index_cjs_js$5.exists(mapPath)) {
2173
+ if (index_cjs_js$6.exists(mapPath)) {
2128
2174
  bytesRemoved += node_fs.statSync(mapPath).size;
2129
2175
  node_fs.unlinkSync(mapPath);
2130
2176
  orphanFilesRemoved += 1;
@@ -2195,7 +2241,7 @@ const pruneDtsOrphans = (context, depsRoot) => {
2195
2241
  * ```
2196
2242
  */
2197
2243
  const pruneOrphanChunks = (context, depsRoot) => {
2198
- if (!index_cjs_js$5.exists(depsRoot) || !index_cjs_js$5.isDirectory(depsRoot))
2244
+ if (!index_cjs_js$6.exists(depsRoot) || !index_cjs_js$6.isDirectory(depsRoot))
2199
2245
  return { orphanFilesRemoved: 0, bytesRemoved: 0 };
2200
2246
  const js = pruneJsOrphans(context, depsRoot);
2201
2247
  const dts = pruneDtsOrphans(context, depsRoot);
@@ -2373,7 +2419,7 @@ const collectImportEdges = (source, importerDir, format) => {
2373
2419
  return edges;
2374
2420
  };
2375
2421
 
2376
- const log$4 = index_cjs_js$4.logger.channel('builder:bundle:dependencies:prune');
2422
+ const log$4 = index_cjs_js$5.logger.channel('builder:bundle:dependencies:prune');
2377
2423
  // why: the strip → re-derive → strip cycle converges in passes bounded by the chunk-import depth; this cap is a runaway guard, logged if ever reached.
2378
2424
  const MAX_ITERATIONS = 50;
2379
2425
  const FORMAT_FILES$1 = [
@@ -2398,7 +2444,7 @@ const buildUsageMap = (importers, chunks, format) => {
2398
2444
  usageMap.set(chunk, index_cjs_js$2.createSet([]));
2399
2445
  // why: every importer is either a validated entry file or a chunk just walked off disk, so all are present — no existence guard needed.
2400
2446
  for (const importer of importers) {
2401
- for (const [target, usage] of collectImportEdges(index_cjs_js$5.readFileContent(importer), index_cjs_js$5.getDirname(importer), format))
2447
+ for (const [target, usage] of collectImportEdges(index_cjs_js$6.readFileContent(importer), index_cjs_js$6.getDirname(importer), format))
2402
2448
  mergeUsage(usageMap, target, usage);
2403
2449
  }
2404
2450
  return usageMap;
@@ -2406,11 +2452,11 @@ const buildUsageMap = (importers, chunks, format) => {
2406
2452
  const stripChunks = (usageMap, format, result) => {
2407
2453
  let changed = false;
2408
2454
  for (const [chunk, keep] of usageMap) {
2409
- const source = index_cjs_js$5.readFileContent(chunk);
2455
+ const source = index_cjs_js$6.readFileContent(chunk);
2410
2456
  const stripped = stripDeadExports(source, format, keep);
2411
2457
  if (!stripped)
2412
2458
  continue;
2413
- index_cjs_js$5.writeFileContent(chunk, stripped.code);
2459
+ index_cjs_js$6.writeFileContent(chunk, stripped.code);
2414
2460
  result.deadExportsRemoved += stripped.removedNames.length;
2415
2461
  result.bytesRemoved += Buffer.byteLength(source) - Buffer.byteLength(stripped.code);
2416
2462
  changed = true;
@@ -2454,7 +2500,7 @@ const processFormat$1 = (context, depsRoot, format, fileName, result) => {
2454
2500
  */
2455
2501
  const stripDeadExportsPass = (context, depsRoot) => {
2456
2502
  const result = { deadExportsRemoved: 0, bytesRemoved: 0 };
2457
- if (!index_cjs_js$5.exists(depsRoot))
2503
+ if (!index_cjs_js$6.exists(depsRoot))
2458
2504
  return result;
2459
2505
  for (const { format, fileName } of FORMAT_FILES$1)
2460
2506
  processFormat$1(context, depsRoot, format, fileName, result);
@@ -2868,7 +2914,7 @@ const destructureRequires = (source, chunkDir, isSafeTarget) => {
2868
2914
  return { code: applyEdits(source, edits), rewrittenBindings: qualified.length };
2869
2915
  };
2870
2916
 
2871
- const log$3 = index_cjs_js$4.logger.channel('builder:bundle:dependencies:prune');
2917
+ const log$3 = index_cjs_js$5.logger.channel('builder:bundle:dependencies:prune');
2872
2918
  const CJS_CHUNK = 'index.cjs.js';
2873
2919
  const collectRequireTargets = (source, chunkDir, chunkSet) => {
2874
2920
  const sourceFile = parseChunk(source);
@@ -2888,7 +2934,7 @@ const collectRequireTargets = (source, chunkDir, chunkSet) => {
2888
2934
  const buildRequireGraph = (chunks, chunkSet) => {
2889
2935
  const graph = index_cjs_js$b.createMap();
2890
2936
  for (const chunk of chunks)
2891
- graph.set(chunk, collectRequireTargets(index_cjs_js$5.readFileContent(chunk), index_cjs_js$5.getDirname(chunk), chunkSet));
2937
+ graph.set(chunk, collectRequireTargets(index_cjs_js$6.readFileContent(chunk), index_cjs_js$6.getDirname(chunk), chunkSet));
2892
2938
  return graph;
2893
2939
  };
2894
2940
  /**
@@ -2982,7 +3028,7 @@ const computeSccIds = (nodes, graph) => {
2982
3028
  */
2983
3029
  const destructureRequiresPass = (depsRoot) => {
2984
3030
  const result = { requireBindingsDestructured: 0 };
2985
- if (!index_cjs_js$5.exists(depsRoot))
3031
+ if (!index_cjs_js$6.exists(depsRoot))
2986
3032
  return result;
2987
3033
  const chunks = [];
2988
3034
  walkFiles(depsRoot, (name) => name === CJS_CHUNK, chunks);
@@ -2990,7 +3036,7 @@ const destructureRequiresPass = (depsRoot) => {
2990
3036
  return result;
2991
3037
  const sources = index_cjs_js$b.createMap();
2992
3038
  for (const chunk of chunks) {
2993
- const source = index_cjs_js$5.readFileContent(chunk);
3039
+ const source = index_cjs_js$6.readFileContent(chunk);
2994
3040
  // why: a dynamic specifier could hide a require cycle the static graph misses; bail the whole pass, mirroring the orphan sweep's safety posture.
2995
3041
  if (hasDynamicSpecifier(source)) {
2996
3042
  log$3.warn(`dynamic import/require in ${chunk}; skipping require-destructure pass for safety`);
@@ -3006,10 +3052,10 @@ const destructureRequiresPass = (depsRoot) => {
3006
3052
  const source = sources.get(chunk);
3007
3053
  const myComponent = componentOf.get(chunk);
3008
3054
  const isSafeTarget = (target) => chunkSet.has(target) && componentOf.get(target) !== myComponent;
3009
- const rewritten = destructureRequires(source, index_cjs_js$5.getDirname(chunk), isSafeTarget);
3055
+ const rewritten = destructureRequires(source, index_cjs_js$6.getDirname(chunk), isSafeTarget);
3010
3056
  if (!rewritten)
3011
3057
  continue;
3012
- index_cjs_js$5.writeFileContent(chunk, rewritten.code);
3058
+ index_cjs_js$6.writeFileContent(chunk, rewritten.code);
3013
3059
  result.requireBindingsDestructured += rewritten.rewrittenBindings;
3014
3060
  }
3015
3061
  return result;
@@ -3173,11 +3219,11 @@ const FORMAT_FILES = [
3173
3219
  { format: 'cjs', fileName: 'index.cjs.js' },
3174
3220
  ];
3175
3221
  // why: a dynamic, non-literal `import(`/`require(` anywhere in the consumer graph means a consumer we cannot resolve might read a namespace wholesale — disable property-strip for the format (guaranteed-safe fallback, mirroring the orphan sweep).
3176
- const graphHasDynamicSpecifier = (importers) => importers.some((importer) => hasDynamicSpecifier(index_cjs_js$5.readFileContent(importer)));
3222
+ const graphHasDynamicSpecifier = (importers) => importers.some((importer) => hasDynamicSpecifier(index_cjs_js$6.readFileContent(importer)));
3177
3223
  const collectChunkNamespaces = (chunks, format) => {
3178
3224
  const byChunk = index_cjs_js$b.createMap();
3179
3225
  for (const chunk of chunks) {
3180
- const { namespaces } = analyzeChunkNamespaces(index_cjs_js$5.readFileContent(chunk), format);
3226
+ const { namespaces } = analyzeChunkNamespaces(index_cjs_js$6.readFileContent(chunk), format);
3181
3227
  if (namespaces.length > 0)
3182
3228
  byChunk.set(chunk, namespaces);
3183
3229
  }
@@ -3189,14 +3235,14 @@ const seedSelfDemand = (chunks, namespacesByChunk, format) => {
3189
3235
  for (const chunk of chunks) {
3190
3236
  if (!namespacesByChunk.has(chunk))
3191
3237
  continue;
3192
- const { selfDemand } = analyzeChunkNamespaces(index_cjs_js$5.readFileContent(chunk), format);
3238
+ const { selfDemand } = analyzeChunkNamespaces(index_cjs_js$6.readFileContent(chunk), format);
3193
3239
  demand.set(chunk, selfDemand);
3194
3240
  }
3195
3241
  return demand;
3196
3242
  };
3197
3243
  const accumulateImporterDemand = (importers, namespacesByChunk, demand, format) => {
3198
3244
  for (const importer of importers) {
3199
- const edges = collectNamespaceUsage(index_cjs_js$5.readFileContent(importer), index_cjs_js$5.getDirname(importer), format);
3245
+ const edges = collectNamespaceUsage(index_cjs_js$6.readFileContent(importer), index_cjs_js$6.getDirname(importer), format);
3200
3246
  for (const [target, usage] of edges) {
3201
3247
  const chunkDemand = demand.get(target);
3202
3248
  const namespaces = namespacesByChunk.get(target);
@@ -3234,11 +3280,11 @@ const rewriteChunks = (namespacesByChunk, demand, format, result) => {
3234
3280
  const keepByExport = keepSetsForChunk(namespaces, chunkDemand);
3235
3281
  if (keepByExport.size === 0)
3236
3282
  continue;
3237
- const source = index_cjs_js$5.readFileContent(chunk);
3283
+ const source = index_cjs_js$6.readFileContent(chunk);
3238
3284
  const stripped = stripDeadProperties(source, format, keepByExport);
3239
3285
  if (!stripped)
3240
3286
  continue;
3241
- index_cjs_js$5.writeFileContent(chunk, stripped.code);
3287
+ index_cjs_js$6.writeFileContent(chunk, stripped.code);
3242
3288
  result.deadPropertiesRemoved += stripped.removedProperties;
3243
3289
  result.bytesRemoved += Buffer.byteLength(source) - Buffer.byteLength(stripped.code);
3244
3290
  }
@@ -3286,7 +3332,7 @@ const processFormat = (context, depsRoot, format, fileName, result) => {
3286
3332
  */
3287
3333
  const stripDeadPropertiesPass = (context, depsRoot) => {
3288
3334
  const result = { deadPropertiesRemoved: 0, bytesRemoved: 0 };
3289
- if (!index_cjs_js$5.exists(depsRoot))
3335
+ if (!index_cjs_js$6.exists(depsRoot))
3290
3336
  return result;
3291
3337
  for (const { format, fileName } of FORMAT_FILES)
3292
3338
  processFormat(context, depsRoot, format, fileName, result);
@@ -3413,22 +3459,22 @@ const stripComments = (source) => {
3413
3459
 
3414
3460
  const stripCommentsPass = (depsRoot) => {
3415
3461
  const result = { commentBytesRemoved: 0 };
3416
- if (!index_cjs_js$5.exists(depsRoot))
3462
+ if (!index_cjs_js$6.exists(depsRoot))
3417
3463
  return result;
3418
3464
  const chunks = [];
3419
3465
  walkFiles(depsRoot, (name) => name === 'index.esm.js' || name === 'index.cjs.js', chunks);
3420
3466
  for (const chunk of chunks) {
3421
- const source = index_cjs_js$5.readFileContent(chunk);
3467
+ const source = index_cjs_js$6.readFileContent(chunk);
3422
3468
  const stripped = stripComments(source);
3423
3469
  if (stripped === null)
3424
3470
  continue;
3425
- index_cjs_js$5.writeFileContent(chunk, stripped);
3471
+ index_cjs_js$6.writeFileContent(chunk, stripped);
3426
3472
  result.commentBytesRemoved += Buffer.byteLength(source) - Buffer.byteLength(stripped);
3427
3473
  }
3428
3474
  return result;
3429
3475
  };
3430
3476
 
3431
- const log$2 = index_cjs_js$4.logger.channel('builder:bundle:dependencies:prune');
3477
+ const log$2 = index_cjs_js$5.logger.channel('builder:bundle:dependencies:prune');
3432
3478
 
3433
3479
  const pruneDependencies = (context, monitor) => {
3434
3480
  const depsRoot = depsRootOf(context);
@@ -3694,53 +3740,35 @@ const toUmdBuildDescriptor = (entry, config, context, reportPath) => {
3694
3740
  };
3695
3741
  };
3696
3742
 
3697
- const log$1 = index_cjs_js$4.logger.channel('builder:bundle:rollup:dispatch');
3743
+ const log$1 = index_cjs_js$5.logger.channel('builder:bundle:rollup:dispatch');
3698
3744
  const REPORT_DIR_PREFIX = 'hf-builder-rollup-';
3699
- const SWC_NODE_REGISTER = '@swc-node/register';
3700
- const swcNodeAvailable = (workspaceRoot) => node_fs.existsSync(index_cjs_js$5.join(workspaceRoot, 'node_modules', '@swc-node', 'register', 'index.js'));
3701
3745
  /**
3702
- * Default worker-path resolution: prefers the built-and-published artifact, falls
3703
- * back to the workspace dist path, and finally to the in-source TypeScript file
3704
- * via `@swc-node/register` (bootstrap case where builder is building itself for
3705
- * the first time and the dist worker doesn't exist yet).
3706
- *
3707
- * Looks at, in order:
3708
- * 1. `<workspaceRoot>/dist/libs/builder/bundle/rollup/worker/index.cjs.js`
3709
- * 2. `<workspaceRoot>/node_modules/@hyperfrontend/builder/bundle/rollup/worker/index.cjs.js`
3710
- * 3. `<workspaceRoot>/libs/builder/src/bundle/rollup/worker/index.ts` (with `--require \@swc-node/register`)
3711
- *
3712
- * @param workspaceRoot - Absolute workspace root.
3713
- * @returns Worker invocation descriptor, or `undefined` if no candidate exists.
3714
- *
3715
- * @example Locating the worker for an in-workspace consumer
3746
+ * Resolves the rollup worker by self-locating it beside the running builder
3747
+ * module: ascends from the module's own directory to the builder package root
3748
+ * and returns the worker at `bundle/rollup/worker`. This works whether the
3749
+ * builder runs from its built dist, an installed `node_modules` copy, or melded
3750
+ * into a host bundle under `_dependencies/`. The compiled `index.cjs.js` is
3751
+ * preferred; an `index.ts` sibling resolves with the `@swc-node/register` loader
3752
+ * for source-mode bootstrap.
3753
+ *
3754
+ * @param startDir - Directory to begin the ascent from. Defaults to the running module's directory; pass an explicit value to resolve from another anchor or under test.
3755
+ * @returns Worker invocation descriptor, or `undefined` if no worker is found under any ancestor.
3756
+ *
3757
+ * @example Locating the worker beside the builder
3716
3758
  * ```typescript
3717
- * const invocation = resolveDefaultRollupWorkerPath('/abs/repo')
3759
+ * const invocation = resolveDefaultRollupWorkerPath()
3718
3760
  * if (!invocation) throw new Error('builder rollup worker artifact not found')
3719
3761
  * ```
3720
3762
  */
3721
- const resolveDefaultRollupWorkerPath = (workspaceRoot) => {
3722
- const distCandidates = [
3723
- index_cjs_js$5.join(workspaceRoot, 'dist', 'libs', 'builder', 'bundle', 'rollup', 'worker', 'index.cjs.js'),
3724
- index_cjs_js$5.join(workspaceRoot, 'node_modules', '@hyperfrontend', 'builder', 'bundle', 'rollup', 'worker', 'index.cjs.js'),
3725
- ];
3726
- for (const path of distCandidates) {
3727
- if (node_fs.existsSync(path))
3728
- return { path, execArgv: [] };
3729
- }
3730
- const sourcePath = index_cjs_js$5.join(workspaceRoot, 'libs', 'builder', 'src', 'bundle', 'rollup', 'worker', 'index.ts');
3731
- if (node_fs.existsSync(sourcePath) && swcNodeAvailable(workspaceRoot)) {
3732
- return { path: sourcePath, execArgv: ['--require', SWC_NODE_REGISTER] };
3733
- }
3734
- return undefined;
3735
- };
3736
- const createReportDir = () => node_fs.mkdtempSync(index_cjs_js$5.join(node_os.tmpdir(), REPORT_DIR_PREFIX));
3763
+ const resolveDefaultRollupWorkerPath = (startDir) => ascendForWorker(['bundle', 'rollup', 'worker'], startDir);
3764
+ const createReportDir = () => node_fs.mkdtempSync(index_cjs_js$6.join(node_os.tmpdir(), REPORT_DIR_PREFIX));
3737
3765
  const reportPathFor = (reportDir, descriptor) => {
3738
3766
  const safeLabel = descriptor.inputFile.replace(/[^a-zA-Z0-9_-]+/g, '_');
3739
- return index_cjs_js$5.join(reportDir, `${descriptor.format}-${safeLabel}.json`);
3767
+ return index_cjs_js$6.join(reportDir, `${descriptor.format}-${safeLabel}.json`);
3740
3768
  };
3741
3769
  const runOne = (descriptor, options, label) => index_cjs_js.createPromise((resolve, reject) => {
3742
3770
  const execPath = options.execPath ?? process.execPath;
3743
- const argv = [...(options.execArgv ?? []), options.workerPath, index_cjs_js$6.stringify(descriptor)];
3771
+ const argv = [...(options.execArgv ?? []), options.workerPath, index_cjs_js$7.stringify(descriptor)];
3744
3772
  const child = node_child_process.spawn(execPath, argv, { stdio: ['ignore', 'pipe', 'pipe'] });
3745
3773
  let capturedStderr = '';
3746
3774
  child.stdout?.on('data', (chunk) => {
@@ -3752,12 +3780,12 @@ const runOne = (descriptor, options, label) => index_cjs_js.createPromise((resol
3752
3780
  process.stderr.write(text);
3753
3781
  });
3754
3782
  child.on('error', (error) => {
3755
- reject(index_cjs_js$7.createError(`rollup worker for ${label} failed to spawn: ${error.message}`));
3783
+ reject(index_cjs_js$4.createError(`rollup worker for ${label} failed to spawn: ${error.message}`));
3756
3784
  });
3757
3785
  child.on('exit', (code) => {
3758
3786
  if (code !== 0) {
3759
3787
  const tail = capturedStderr.trim().split('\n').slice(-10).join('\n');
3760
- reject(index_cjs_js$7.createError(`rollup worker for ${label} exited with code ${code}\n${tail}`));
3788
+ reject(index_cjs_js$4.createError(`rollup worker for ${label} exited with code ${code}\n${tail}`));
3761
3789
  return;
3762
3790
  }
3763
3791
  resolve();
@@ -3765,9 +3793,9 @@ const runOne = (descriptor, options, label) => index_cjs_js.createPromise((resol
3765
3793
  });
3766
3794
  const readReport = (reportPath, label) => {
3767
3795
  if (!node_fs.existsSync(reportPath)) {
3768
- throw index_cjs_js$7.createError(`rollup worker for ${label} did not write a report at ${reportPath}`);
3796
+ throw index_cjs_js$4.createError(`rollup worker for ${label} did not write a report at ${reportPath}`);
3769
3797
  }
3770
- const data = index_cjs_js$6.parse(node_fs.readFileSync(reportPath, 'utf8'));
3798
+ const data = index_cjs_js$7.parse(node_fs.readFileSync(reportPath, 'utf8'));
3771
3799
  return data;
3772
3800
  };
3773
3801
  /**
@@ -3811,7 +3839,7 @@ const dispatchRollupWorker = async (descriptor, options) => {
3811
3839
  }
3812
3840
  };
3813
3841
 
3814
- const log = index_cjs_js$4.logger.channel('builder:bundle');
3842
+ const log = index_cjs_js$5.logger.channel('builder:bundle');
3815
3843
  const toArray = (value) => (value === undefined ? [] : index_cjs_js$3.isArray(value) ? value : [value]);
3816
3844
  const collectFormatsRequestingPrePass = (config) => {
3817
3845
  const formats = index_cjs_js$2.createSet([]);
@@ -3838,7 +3866,7 @@ const buildJsPrePassJobs = (deps, formats, context) => {
3838
3866
  dep,
3839
3867
  inputPath: entry,
3840
3868
  format,
3841
- outputPath: index_cjs_js$5.join(depsRoot, dep, chunkFileName(format)),
3869
+ outputPath: index_cjs_js$6.join(depsRoot, dep, chunkFileName(format)),
3842
3870
  otherDeps: [...otherNpmDeps, ...workspacePrefixDeps],
3843
3871
  otherWorkspaceSpecifiers: workspaceExactSpecifiers,
3844
3872
  npmDeps: otherNpmDeps,
@@ -3871,7 +3899,7 @@ const buildWorkspaceJsPrePassJobs = (npmDeps, formats, context) => {
3871
3899
  dep: entry.specifier,
3872
3900
  inputPath: entry.inputPath,
3873
3901
  format,
3874
- outputPath: index_cjs_js$5.join(depsRoot, workspaceOutputFile(entry, format)),
3902
+ outputPath: index_cjs_js$6.join(depsRoot, workspaceOutputFile(entry, format)),
3875
3903
  otherDeps: [...npmDeps, ...otherWorkspacePackages],
3876
3904
  otherWorkspaceSpecifiers: otherSubPathSpecifiers,
3877
3905
  tsConfigPath: entry.tsConfigPath,
@@ -3884,25 +3912,25 @@ const buildWorkspaceJsPrePassJobs = (npmDeps, formats, context) => {
3884
3912
  }
3885
3913
  return jobs;
3886
3914
  };
3887
- const resolvePrePassWorkerOrThrow = (workspaceRoot) => {
3888
- const invocation = resolveDefaultWorkerPath(workspaceRoot);
3915
+ const resolvePrePassWorkerOrThrow = () => {
3916
+ const invocation = resolveDefaultWorkerPath();
3889
3917
  if (!invocation) {
3890
- throw index_cjs_js$7.createError('bundleAllDeps is enabled but the pre-pass worker could not be resolved. Build @hyperfrontend/builder once with bundleAllDeps disabled, or ensure @swc-node/register is installed for source-mode bootstrap.');
3918
+ throw index_cjs_js$4.createError('bundleAllDeps is enabled but the pre-pass worker could not be located beside the builder module. The @hyperfrontend/builder package appears incomplete, or @swc-node/register is missing for source-mode bootstrap.');
3891
3919
  }
3892
3920
  return invocation;
3893
3921
  };
3894
- const resolveRollupWorkerOrThrow = (workspaceRoot) => {
3895
- const invocation = resolveDefaultRollupWorkerPath(workspaceRoot);
3922
+ const resolveRollupWorkerOrThrow = () => {
3923
+ const invocation = resolveDefaultRollupWorkerPath();
3896
3924
  if (!invocation) {
3897
- throw index_cjs_js$7.createError('rollup worker could not be resolved. Build @hyperfrontend/builder at least once before invoking the bundle phase, or ensure @swc-node/register is installed for source-mode bootstrap.');
3925
+ throw index_cjs_js$4.createError('rollup worker could not be located beside the builder module. The @hyperfrontend/builder package appears incomplete, or @swc-node/register is missing for source-mode bootstrap.');
3898
3926
  }
3899
3927
  return invocation;
3900
3928
  };
3901
- const createLazyDispatchResolver = (workspaceRoot) => {
3929
+ const createLazyDispatchResolver = () => {
3902
3930
  let cached = null;
3903
3931
  return () => {
3904
3932
  if (!cached) {
3905
- const invocation = resolveRollupWorkerOrThrow(workspaceRoot);
3933
+ const invocation = resolveRollupWorkerOrThrow();
3906
3934
  cached = { workerPath: invocation.path, execArgv: invocation.execArgv };
3907
3935
  }
3908
3936
  return cached;
@@ -3946,7 +3974,7 @@ const runIifeFormats = async (config, context, outputs, resolveDispatch, monitor
3946
3974
  const entries = resolveEntries(iifeConfig, context.entryPointDiscovery.entryPoints);
3947
3975
  if (entries.length === 0)
3948
3976
  continue;
3949
- index_cjs_js$5.ensureDir(index_cjs_js$5.join(context.outputPath, iifeConfig.output ?? 'bundle'));
3977
+ index_cjs_js$6.ensureDir(index_cjs_js$6.join(context.outputPath, iifeConfig.output ?? 'bundle'));
3950
3978
  for (const [i, entry] of entries.entries()) {
3951
3979
  const label = `iife:${i}/${entries.length}:${entry.exportPath}`;
3952
3980
  monitor?.check(`bundle:${label}:start`);
@@ -3962,7 +3990,7 @@ const runUmdFormats = async (config, context, outputs, resolveDispatch, monitor)
3962
3990
  const entries = resolveEntries(umdConfig, context.entryPointDiscovery.entryPoints);
3963
3991
  if (entries.length === 0)
3964
3992
  continue;
3965
- index_cjs_js$5.ensureDir(index_cjs_js$5.join(context.outputPath, umdConfig.output ?? 'bundle'));
3993
+ index_cjs_js$6.ensureDir(index_cjs_js$6.join(context.outputPath, umdConfig.output ?? 'bundle'));
3966
3994
  for (const [i, entry] of entries.entries()) {
3967
3995
  const label = `umd:${i}/${entries.length}:${entry.exportPath}`;
3968
3996
  monitor?.check(`bundle:${label}:start`);
@@ -3996,7 +4024,7 @@ const runBundlePhase = async (context, config, monitor) => {
3996
4024
  const outputs = { esm: [], cjs: [], iife: [], umd: [] };
3997
4025
  const requestedPrePassFormats = collectFormatsRequestingPrePass(config);
3998
4026
  if (requestedPrePassFormats.length > 0 && (context.bundledDeps.length > 0 || context.workspaceBundledDeps.length > 0)) {
3999
- const invocation = resolvePrePassWorkerOrThrow(context.workspaceRoot);
4027
+ const invocation = resolvePrePassWorkerOrThrow();
4000
4028
  const npmJobs = buildJsPrePassJobs(context.bundledDeps, requestedPrePassFormats, context);
4001
4029
  const workspaceJobs = buildWorkspaceJsPrePassJobs(context.bundledDeps, requestedPrePassFormats, context);
4002
4030
  const jobs = [...npmJobs, ...workspaceJobs];
@@ -4005,7 +4033,7 @@ const runBundlePhase = async (context, config, monitor) => {
4005
4033
  await runPrePass(jobs, { workerPath: invocation.path, execArgv: invocation.execArgv, monitor });
4006
4034
  monitor?.check('bundle:dependencies:prepass:end');
4007
4035
  }
4008
- const resolveDispatch = createLazyDispatchResolver(context.workspaceRoot);
4036
+ const resolveDispatch = createLazyDispatchResolver();
4009
4037
  await runEsmFormats(config, context, outputs, resolveDispatch, monitor);
4010
4038
  await recover();
4011
4039
  monitor?.check('bundle:esm:end:post-recover');
@@ -4034,7 +4062,7 @@ const runBundlePhase = async (context, config, monitor) => {
4034
4062
  monitor?.check('bundle:dedupe:shared-first-party:end');
4035
4063
  }
4036
4064
  // why: runs last (after the final file-producing pass) so no later pass re-creates a file under a removed directory; sweeps the per-source dirs left empty by the orphan-d.ts prune across the whole package, not just `_dependencies/`. Guarded for the degenerate case where no format produced an output tree.
4037
- if (index_cjs_js$5.exists(context.outputPath)) {
4065
+ if (index_cjs_js$6.exists(context.outputPath)) {
4038
4066
  const emptyDirsRemoved = removeEmptyDirs(context.outputPath);
4039
4067
  if (emptyDirsRemoved > 0)
4040
4068
  log.info(`removed ${emptyDirsRemoved} empty director${emptyDirsRemoved === 1 ? 'y' : 'ies'}`);