@package-pal/core 0.0.9 → 0.0.12

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 (63) hide show
  1. package/index.d.ts +4 -0
  2. package/index.d.ts.map +1 -1
  3. package/index.js +452 -439
  4. package/index.js.map +29 -32
  5. package/lib/api.d.ts +1 -1
  6. package/lib/api.d.ts.map +1 -1
  7. package/lib/configuration/functions/load-config.d.ts.map +1 -1
  8. package/lib/configuration/functions/parse-config.d.ts +1 -0
  9. package/lib/configuration/functions/parse-config.d.ts.map +1 -1
  10. package/lib/configuration/schemas/config.d.ts +5 -75
  11. package/lib/configuration/schemas/config.d.ts.map +1 -1
  12. package/lib/graph/functions/dfs-traverse-graph-paths.d.ts +8 -1
  13. package/lib/graph/functions/dfs-traverse-graph-paths.d.ts.map +1 -1
  14. package/lib/graph/functions/extract-subgraph.d.ts.map +1 -1
  15. package/lib/graph/functions/generate-graphs.d.ts.map +1 -1
  16. package/lib/graph/functions/generate-topological-sorted-groups.d.ts +1 -1
  17. package/lib/graph/functions/generate-topological-sorted-groups.d.ts.map +1 -1
  18. package/lib/package/functions/bump-package-version.d.ts +3 -0
  19. package/lib/package/functions/bump-package-version.d.ts.map +1 -0
  20. package/lib/package/functions/load-packages.d.ts +2 -1
  21. package/lib/package/functions/load-packages.d.ts.map +1 -1
  22. package/lib/package/functions/run-for-each-package.d.ts.map +1 -1
  23. package/lib/package/functions/scan-glob-pattern-paths.d.ts.map +1 -1
  24. package/lib/package/types/package-adapter.d.ts +35 -0
  25. package/lib/package/types/package-adapter.d.ts.map +1 -0
  26. package/lib/package/types/package-data.d.ts +1 -0
  27. package/lib/package/types/package-data.d.ts.map +1 -1
  28. package/lib/process/functions/get-commands-for-shell.d.ts +5 -1
  29. package/lib/process/functions/get-commands-for-shell.d.ts.map +1 -1
  30. package/lib/process/functions/get-line-buffered-writer.d.ts +7 -1
  31. package/lib/process/functions/get-line-buffered-writer.d.ts.map +1 -1
  32. package/lib/process/functions/get-shell.d.ts.map +1 -1
  33. package/lib/process/functions/parse-ps-shell-flags.d.ts.map +1 -1
  34. package/lib/process/functions/read-stream.d.ts.map +1 -1
  35. package/lib/process/functions/run-subprocess.d.ts +2 -1
  36. package/lib/process/functions/run-subprocess.d.ts.map +1 -1
  37. package/lib/process/functions/strip-clixml.d.ts +6 -0
  38. package/lib/process/functions/strip-clixml.d.ts.map +1 -0
  39. package/lib/types/bump-package-version-options.d.ts +2 -0
  40. package/lib/types/bump-package-version-options.d.ts.map +1 -1
  41. package/lib/types/get-package-data-options.d.ts +2 -0
  42. package/lib/types/get-package-data-options.d.ts.map +1 -1
  43. package/lib/watch/functions/dedupe-shared-paths.d.ts +3 -0
  44. package/lib/watch/functions/dedupe-shared-paths.d.ts.map +1 -0
  45. package/lib/watch/functions/filter-files-modified-since.d.ts +1 -1
  46. package/lib/watch/functions/filter-files-modified-since.d.ts.map +1 -1
  47. package/lib/watch/functions/get-change-logic.d.ts +1 -1
  48. package/lib/watch/functions/get-change-logic.d.ts.map +1 -1
  49. package/lib/watch/functions/normalise-watched-file-path.d.ts.map +1 -1
  50. package/lib/watch/functions/watch-package-changes.d.ts.map +1 -1
  51. package/lib/watch/types/dedupe-paths-by.d.ts +7 -0
  52. package/lib/watch/types/dedupe-paths-by.d.ts.map +1 -0
  53. package/package.json +9 -11
  54. package/lib/package/functions/parse-package.d.ts +0 -3
  55. package/lib/package/functions/parse-package.d.ts.map +0 -1
  56. package/lib/package/functions/scan-packages.d.ts +0 -4
  57. package/lib/package/functions/scan-packages.d.ts.map +0 -1
  58. package/lib/package/functions/update-package-version.d.ts +0 -5
  59. package/lib/package/functions/update-package-version.d.ts.map +0 -1
  60. package/lib/process/functions/escape-shell-arg.d.ts +0 -8
  61. package/lib/process/functions/escape-shell-arg.d.ts.map +0 -1
  62. package/lib/watch/functions/normalise-pattern-separators.d.ts +0 -2
  63. package/lib/watch/functions/normalise-pattern-separators.d.ts.map +0 -1
package/index.js CHANGED
@@ -9,9 +9,9 @@ var BumpVersionType = {
9
9
  Prepatch: "prepatch",
10
10
  Prerelease: "prerelease"
11
11
  };
12
- // packages/core/src/lib/api.ts
13
- import { isDefined as isDefined5 } from "@package-pal/util";
14
-
12
+ // packages/core/src/lib/package/types/package-adapter.ts
13
+ class PackageAdapter {
14
+ }
15
15
  // packages/core/src/lib/configuration/functions/check-bun.ts
16
16
  var checkBun = () => {
17
17
  if (!Bun) {
@@ -20,9 +20,9 @@ var checkBun = () => {
20
20
  };
21
21
 
22
22
  // packages/core/src/lib/configuration/functions/load-config.ts
23
- import { styleText } from "util";
24
23
  import { dirname as dirname3 } from "path";
25
24
  import { cwd } from "process";
25
+ import { styleText } from "util";
26
26
  import {
27
27
  deepMergeDefined,
28
28
  formatSimpleLogObject,
@@ -85,6 +85,11 @@ var LogLevel = z3.enum([
85
85
  "silent"
86
86
  ]);
87
87
  var Config = z3.object({
88
+ adapter: z3.optional(z3.enum([
89
+ "package-json",
90
+ "msbuild",
91
+ "auto"
92
+ ])),
88
93
  packages: z3.optional(z3.union([z3.string(), z3.array(z3.string())])),
89
94
  version: z3.optional(z3.object({
90
95
  preId: z3.optional(z3.string()),
@@ -210,6 +215,7 @@ var searchConfigPath = async (pathOverride) => {
210
215
 
211
216
  // packages/core/src/lib/configuration/functions/load-config.ts
212
217
  var defaultConfig = {
218
+ adapter: "auto",
213
219
  packages: "packages/*",
214
220
  version: {
215
221
  preId: "",
@@ -241,7 +247,7 @@ var defaultConfig = {
241
247
  var loadConfig = async (overrideConfigPath) => {
242
248
  const path = await searchConfigPath(overrideConfigPath);
243
249
  if (!path) {
244
- defaultConfig.logger.info("No config file found. Defaults will be applied.");
250
+ defaultConfig.logger.debug("No config file found. Defaults will be applied.");
245
251
  return {
246
252
  config: defaultConfig,
247
253
  rootDir: cwd()
@@ -268,39 +274,26 @@ ${styleText("dim", formatSimpleLogObject(activatedConfig))}`);
268
274
  // packages/core/src/lib/graph/functions/generate-graphs.ts
269
275
  import { styleText as styleText2 } from "util";
270
276
  import { assertDefined as assertDefined2 } from "@package-pal/util";
271
-
272
- // packages/core/src/lib/package/types/dependencies-field.ts
273
- var DependenciesField = {
274
- Dependencies: "dependencies",
275
- DevDependencies: "devDependencies",
276
- PeerDependencies: "peerDependencies",
277
- OptionalDependencies: "optionalDependencies"
278
- };
279
-
280
- // packages/core/src/lib/graph/functions/generate-graphs.ts
281
277
  var trackPackageEntryDependencies = ({
282
278
  trackedDependencies,
283
279
  packageNames,
284
280
  packageData
285
281
  }) => {
286
- const iterateEntries = Object.values(DependenciesField).map((field) => packageData[field]);
287
- for (const packageEntries of iterateEntries) {
288
- if (!packageEntries) {
282
+ for (const trackPackageName of packageData.localDependencies ?? []) {
283
+ if (!packageNames.has(trackPackageName)) {
289
284
  continue;
290
285
  }
291
- for (const trackPackageName of Object.keys(packageEntries)) {
292
- if (!packageNames.has(trackPackageName)) {
293
- continue;
294
- }
295
- trackedDependencies.add(trackPackageName);
296
- }
286
+ trackedDependencies.add(trackPackageName);
297
287
  }
298
288
  };
299
289
  var generateReverseGraph = (packages, packageGraph) => {
300
- const reversePackageGraph = new Map(packages.map((packageData) => [packageData.name, {
301
- packageData,
302
- pointsToPackages: new Set
303
- }]));
290
+ const reversePackageGraph = new Map;
291
+ for (const packageData of packages) {
292
+ reversePackageGraph.set(packageData.name, {
293
+ packageData,
294
+ pointsToPackages: new Set
295
+ });
296
+ }
304
297
  for (const packageData of packages) {
305
298
  const packageNode = assertDefined2(packageGraph.get(packageData.name));
306
299
  for (const dependency of packageNode.pointsToPackages) {
@@ -339,7 +332,8 @@ import { assertDefined as assertDefined6 } from "@package-pal/util";
339
332
 
340
333
  // packages/core/src/lib/graph/functions/dfs-traverse-graph-paths.ts
341
334
  import { assertDefined as assertDefined3 } from "@package-pal/util";
342
- var dfsTraverseGraphPaths = function* (graph, traverseFromPackages) {
335
+ var dfsTraverseGraphPaths = function* (graph, traverseFromPackages, options = {}) {
336
+ const { useGlobalVisited = true } = options;
343
337
  const globalVisited = new Set;
344
338
  const startPackages = Array.isArray(traverseFromPackages) ? traverseFromPackages : [traverseFromPackages];
345
339
  for (const start of startPackages) {
@@ -357,14 +351,14 @@ var dfsTraverseGraphPaths = function* (graph, traverseFromPackages) {
357
351
  if (localVisited.has(node)) {
358
352
  const idx = path.indexOf(node);
359
353
  if (idx !== -1) {
360
- yield [...path.slice(idx), node];
354
+ yield path.slice(idx).concat(node);
361
355
  }
362
356
  continue;
363
357
  }
364
- if (globalVisited.has(node)) {
358
+ if (useGlobalVisited && globalVisited.has(node)) {
365
359
  continue;
366
360
  }
367
- const newPath = [...path, node];
361
+ const newPath = path.concat(node);
368
362
  const newLocalVisited = new Set(localVisited);
369
363
  newLocalVisited.add(node);
370
364
  const neighbours = graph.get(node)?.pointsToPackages;
@@ -382,7 +376,9 @@ var dfsTraverseGraphPaths = function* (graph, traverseFromPackages) {
382
376
  if (!pushed) {
383
377
  yield newPath;
384
378
  }
385
- globalVisited.add(node);
379
+ if (useGlobalVisited) {
380
+ globalVisited.add(node);
381
+ }
386
382
  }
387
383
  }
388
384
  };
@@ -394,7 +390,7 @@ import { assertDefined as assertDefined5 } from "@package-pal/util";
394
390
  import { assertDefined as assertDefined4 } from "@package-pal/util";
395
391
  var dfsTraverseGraph = function* (graph, traverseFromPackages) {
396
392
  const visited = new Set;
397
- const stack = Array.isArray(traverseFromPackages) ? [...traverseFromPackages] : [traverseFromPackages];
393
+ const stack = Array.isArray(traverseFromPackages) ? traverseFromPackages.slice() : [traverseFromPackages];
398
394
  while (stack.length) {
399
395
  const activePackage = assertDefined4(stack.pop());
400
396
  if (visited.has(activePackage)) {
@@ -420,7 +416,12 @@ var extractSubgraph = (graph, fromPackages) => {
420
416
  const subgraph = new Map;
421
417
  for (const packageName of reachablePackages) {
422
418
  const node = assertDefined5(graph.get(packageName));
423
- const filteredNeighbours = new Set([...node.pointsToPackages].filter((dep) => reachablePackages.has(dep)));
419
+ const filteredNeighbours = new Set;
420
+ for (const dep of node.pointsToPackages) {
421
+ if (reachablePackages.has(dep)) {
422
+ filteredNeighbours.add(dep);
423
+ }
424
+ }
424
425
  subgraph.set(packageName, {
425
426
  packageData: node.packageData,
426
427
  pointsToPackages: filteredNeighbours
@@ -510,18 +511,28 @@ var getCircularDependencies = (inDegree) => {
510
511
  return Array.from(inDegree.keys()).sort((a, b) => {
511
512
  const degA = assertDefined7(inDegree.get(a));
512
513
  const degB = assertDefined7(inDegree.get(b));
513
- return degB - degA;
514
- }).sort();
514
+ if (degB !== degA) {
515
+ return degB - degA;
516
+ }
517
+ return a.localeCompare(b);
518
+ });
515
519
  };
516
520
  var generateTopologicalSortedGroups = (packageGraph, logger) => {
517
- logger.debug(styleText4("dim", "Generating topological sorted groups..."));
518
- const graphEntries = Array.from(packageGraph.entries());
519
- const inDegree = new Map(graphEntries.map(([packageName]) => [packageName, 0]));
520
- const graph = new Map(graphEntries.map(([packageName]) => [packageName, new Set]));
521
- for (const [packageName, node] of graphEntries) {
521
+ logger?.debug(styleText4("dim", "Generating topological sorted groups..."));
522
+ const inDegree = new Map;
523
+ const graph = new Map;
524
+ for (const [packageName] of packageGraph) {
525
+ inDegree.set(packageName, 0);
526
+ graph.set(packageName, new Set);
527
+ }
528
+ for (const [packageName, node] of packageGraph) {
522
529
  for (const dependencyName of node.pointsToPackages) {
523
- assertDefined7(graph.get(dependencyName)).add(packageName);
524
- inDegree.set(packageName, assertDefined7(inDegree.get(packageName)) + 1);
530
+ const adj = graph.get(dependencyName);
531
+ if (adj) {
532
+ adj.add(packageName);
533
+ }
534
+ const currentDeg = inDegree.get(packageName) ?? 0;
535
+ inDegree.set(packageName, currentDeg + 1);
525
536
  }
526
537
  }
527
538
  const result = [];
@@ -549,10 +560,10 @@ var generateTopologicalSortedGroups = (packageGraph, logger) => {
549
560
  }
550
561
  ready = nextReady;
551
562
  }
552
- logger.debug(styleText4("dim", `Sorted packages into ${result.length.toString()} sequential groups of parallelizable dependencies.`));
563
+ logger?.debug(styleText4("dim", `Sorted packages into ${result.length.toString()} sequential groups of parallelizable dependencies.`));
553
564
  const circular = getCircularDependencies(inDegree);
554
565
  if (circular.length) {
555
- logger.warn(styleText4("yellow", `${circular.length.toString()} packages could not be sorted due to circular dependencies. Correct ordering cannot be guaranteed.`));
566
+ logger?.warn(styleText4("yellow", `${circular.length.toString()} packages could not be sorted due to circular dependencies. Correct ordering cannot be guaranteed.`));
556
567
  }
557
568
  return {
558
569
  groups: result.map((group) => group.sort()),
@@ -560,105 +571,56 @@ var generateTopologicalSortedGroups = (packageGraph, logger) => {
560
571
  };
561
572
  };
562
573
 
563
- // packages/core/src/lib/package/functions/load-packages.ts
564
- import { styleText as styleText6 } from "util";
565
-
566
- // packages/core/src/lib/package/functions/scan-packages.ts
574
+ // packages/core/src/lib/package/functions/bump-package-version.ts
567
575
  import { styleText as styleText5 } from "util";
568
- import {
569
- dirname as dirname5,
570
- join as join2
571
- } from "path";
572
- import { formatUnknownError } from "@package-pal/util";
573
-
574
- // packages/core/src/lib/package/functions/parse-package.ts
575
- import {
576
- dirname as dirname4,
577
- basename as basename2
578
- } from "path";
579
576
  import { isDefined as isDefined2 } from "@package-pal/util";
580
- var parsePackage = (path, text) => {
581
- const base = JSON.parse(text);
582
- if (!isDefined2(base) || typeof base !== "object") {
583
- return;
584
- }
585
- const props = base;
577
+ import { inc } from "semver";
578
+ var bumpPackageVersion = async (options) => {
579
+ const exact = isDefined2(options.exact) ? options.exact : options.config.version.exact;
580
+ const preId = isDefined2(options.preId) ? options.preId : options.config.version.preId;
586
581
  const {
587
- dependencies,
588
- peerDependencies,
589
- devDependencies
590
- } = props;
591
- for (const field of Object.values(DependenciesField)) {
592
- const value = props[field];
593
- if (isDefined2(value) && typeof value !== "object") {
594
- return;
595
- }
582
+ packageName,
583
+ type,
584
+ packageGraphs,
585
+ adapter,
586
+ config: { logger }
587
+ } = options;
588
+ logger.debug(styleText5("dim", `Bumping package '${packageName}'...`));
589
+ const packageNode = packageGraphs.dependencies.get(packageName);
590
+ if (!packageNode) {
591
+ throw new Error(`Package '${packageName}' not found.`);
596
592
  }
597
- return {
598
- rawContent: text,
599
- path,
600
- name: props.name ?? path,
601
- dir: basename2(dirname4(path)),
602
- version: props.version ?? undefined,
603
- dependencies: dependencies ?? undefined,
604
- peerDependencies: peerDependencies ?? undefined,
605
- devDependencies: devDependencies ?? undefined
606
- };
607
- };
608
-
609
- // packages/core/src/lib/package/functions/scan-glob-pattern-paths.ts
610
- import { mergeAsyncIters } from "@package-pal/util";
611
- var {Glob } = globalThis.Bun;
612
- var scanGlobPatternPaths = (patterns, options) => {
613
- return mergeAsyncIters(patterns.map((pattern) => new Glob(pattern).scan(options)));
614
- };
615
-
616
- // packages/core/src/lib/package/functions/scan-package-paths.ts
617
- var scanPackagePaths = (packages, cwd2) => {
618
- const baseOpts = {
619
- absolute: true,
620
- onlyFiles: false
621
- };
622
- const opts = {
623
- ...baseOpts,
624
- ...cwd2 ? { cwd: cwd2 } : {}
625
- };
626
- return scanGlobPatternPaths(packages, opts);
627
- };
628
-
629
- // packages/core/src/lib/package/functions/scan-packages.ts
630
- var scanPackages = async function* (patterns, logger, cwd2) {
631
- for await (const path of scanPackagePaths(patterns, cwd2)) {
632
- const packagePath = join2(path, "package.json");
633
- const dir = dirname5(packagePath);
634
- try {
635
- logger.debug(styleText5("dim", `Trying to read read package.json in '${dir}'.`));
636
- const file = Bun.file(packagePath);
637
- if (!file.size) {
638
- logger.debug(styleText5("dim", `Failed to read package.json in '${dir}' - ${styleText5("red", "File not found")}.`));
639
- continue;
640
- }
641
- const text = await file.text();
642
- const packageData = parsePackage(packagePath, text);
643
- if (!packageData) {
644
- logger.debug(styleText5("dim", `Invalid package.json found in '${dir}'.`));
645
- continue;
593
+ const currentVersion = packageNode.packageData.version ?? "1.0.0";
594
+ const bumpedVersion = inc(currentVersion, type, undefined, preId);
595
+ if (!bumpedVersion) {
596
+ throw new Error(`Package '${packageName}' version '${currentVersion}' is invalid.`);
597
+ }
598
+ logger.info(`Updating '${packageName}' version: ${currentVersion} \u2192 ${bumpedVersion}.`);
599
+ await adapter.bumpOwnVersion(packageNode.packageData, bumpedVersion, logger);
600
+ const dependentWrites = [];
601
+ for (const dependent of dfsTraverseGraph(packageGraphs.dependents, packageName)) {
602
+ dependentWrites.push((async () => {
603
+ const updated = await adapter.bumpDependencyVersion(dependent, packageName, bumpedVersion, exact, logger);
604
+ if (updated) {
605
+ logger.debug(styleText5("dim", `Updated dependency '${packageName}' in '${dependent.name}'.`));
646
606
  }
647
- logger.debug(styleText5("dim", `Successfully read package.json in '${dir}'.`));
648
- yield packageData;
649
- } catch (e) {
650
- logger.debug(styleText5("dim", `Failed to read package.json in '${dir}' - ${styleText5("red", formatUnknownError(e))}.`));
651
- }
607
+ })());
652
608
  }
609
+ await Promise.all(dependentWrites);
653
610
  };
654
611
 
655
612
  // packages/core/src/lib/package/functions/load-packages.ts
656
- var loadPackages = async (rootDir, packagePatterns, logger) => {
657
- const patternContent = packagePatterns.map((pattern) => `'${pattern}'`).join(", ");
613
+ import { styleText as styleText6 } from "util";
614
+ var loadPackages = async (rootDir, packagePatterns, adapter, logger) => {
615
+ let resolvedPatterns = packagePatterns;
616
+ if (packagePatterns.length === 1 && packagePatterns[0] === "packages/*") {
617
+ resolvedPatterns = adapter.defaultPatterns;
618
+ }
619
+ const patternContent = resolvedPatterns.map((pattern) => `'${pattern}'`).join(", ");
658
620
  logger.debug(styleText6("dim", `Loading packages matching pattern/s ${patternContent}...${rootDir ? ` from ${rootDir}` : ""}`));
659
621
  const packages = [];
660
622
  const seen = new Set;
661
- for await (const packageData of scanPackages(Array.from(new Set(packagePatterns)), logger, rootDir)) {
623
+ for await (const packageData of adapter.scanPackages(Array.from(new Set(resolvedPatterns)), logger, rootDir)) {
662
624
  if (seen.has(packageData.name)) {
663
625
  continue;
664
626
  }
@@ -672,9 +634,9 @@ var loadPackages = async (rootDir, packagePatterns, logger) => {
672
634
  };
673
635
 
674
636
  // packages/core/src/lib/package/functions/run-for-each-package.ts
675
- import { dirname as dirname6 } from "path";
637
+ import { dirname as dirname4 } from "path";
676
638
  import {
677
- assertDefined as assertDefined9,
639
+ assertDefined as assertDefined8,
678
640
  runAsync
679
641
  } from "@package-pal/util";
680
642
 
@@ -694,12 +656,95 @@ var StdType = {
694
656
  Err: "Err"
695
657
  };
696
658
 
659
+ // packages/core/src/lib/process/functions/get-commands-for-shell.ts
660
+ import { identity } from "@package-pal/util";
661
+
662
+ // packages/core/src/lib/types/shell.ts
663
+ var Shell = {
664
+ sh: "sh",
665
+ bash: "bash",
666
+ zsh: "zsh",
667
+ pwsh: "pwsh",
668
+ fish: "fish",
669
+ powershell: "powershell",
670
+ cmd: "cmd"
671
+ };
672
+
673
+ // packages/core/src/lib/process/functions/get-shell.ts
674
+ import { userInfo } from "os";
675
+ import { basename as basename2 } from "path";
676
+ import {
677
+ platform,
678
+ env
679
+ } from "process";
680
+ var cachedShell = null;
681
+ var cacheShell = (shell) => {
682
+ cachedShell = shell;
683
+ return shell;
684
+ };
685
+ var mapShell = (shellPath) => {
686
+ if (!shellPath) {
687
+ return Shell.sh;
688
+ }
689
+ const name = basename2(shellPath).replace(/\.exe$/i, "").toLowerCase();
690
+ switch (name) {
691
+ case "bash":
692
+ return Shell.bash;
693
+ case "zsh":
694
+ return Shell.zsh;
695
+ case "fish":
696
+ return Shell.fish;
697
+ case "sh":
698
+ return Shell.sh;
699
+ default:
700
+ return Shell.sh;
701
+ }
702
+ };
703
+ var getShell = () => {
704
+ if (cachedShell !== null) {
705
+ return cachedShell;
706
+ }
707
+ if (env.ZSH_VERSION) {
708
+ return cacheShell(Shell.zsh);
709
+ }
710
+ if (env.BASH_VERSION) {
711
+ return cacheShell(Shell.bash);
712
+ }
713
+ if (env.FISH_VERSION) {
714
+ return cacheShell(Shell.fish);
715
+ }
716
+ const isWindows = platform === "win32";
717
+ if (isWindows) {
718
+ if ((env.MSYSTEM || env.MINGW_PREFIX) && Bun.which(Shell.bash)) {
719
+ return cacheShell(Shell.bash);
720
+ }
721
+ if (Bun.which(Shell.pwsh)) {
722
+ return cacheShell(Shell.pwsh);
723
+ }
724
+ if (Bun.which(Shell.powershell)) {
725
+ return cacheShell(Shell.powershell);
726
+ }
727
+ return cacheShell(Shell.cmd);
728
+ }
729
+ if (env.SHELL) {
730
+ return cacheShell(mapShell(env.SHELL));
731
+ }
732
+ try {
733
+ const userShell = userInfo().shell;
734
+ if (userShell) {
735
+ return cacheShell(mapShell(userShell));
736
+ }
737
+ } catch {}
738
+ return cacheShell(Shell.sh);
739
+ };
740
+
697
741
  // packages/core/src/lib/process/functions/parse-ps-shell-flags.ts
698
- import { assertDefined as assertDefined8 } from "@package-pal/util";
699
742
  var shellFlagsWithParams = new Set([
700
743
  "-executionpolicy",
701
744
  "-windowstyle",
702
- "-version"
745
+ "-version",
746
+ "-encodedcommand",
747
+ "-command"
703
748
  ]);
704
749
  var shellFlagsNoParams = new Set([
705
750
  "-noprofile",
@@ -713,92 +758,68 @@ var shellFlagsNoParams = new Set([
713
758
  "-usewindowspowerShell"
714
759
  ]);
715
760
  var parsePsShellFlags = (input) => {
716
- const isPreEncoded = input.toLowerCase().includes("-encodedcommand");
717
- const tokens = input.match(/"[^"]*"|'[^']*'|\S+/g) ?? [];
718
761
  const flags = new Set;
719
- let i = 0;
720
- while (i < tokens.length) {
721
- const token = assertDefined8(tokens[i]);
762
+ const tokenRegex = /("[^"]*"|'[^']*'|\S+)/g;
763
+ let match;
764
+ while ((match = tokenRegex.exec(input)) !== null) {
765
+ const token = match[0];
722
766
  const tokenLower = token.toLowerCase();
723
767
  if (shellFlagsWithParams.has(tokenLower)) {
724
768
  flags.add(token);
725
- if (i + 1 < tokens.length) {
726
- flags.add(assertDefined8(tokens[i + 1]));
727
- i++;
769
+ const nextMatch = tokenRegex.exec(input);
770
+ if (nextMatch) {
771
+ flags.add(nextMatch[0]);
728
772
  }
729
- i++;
730
773
  } else if (shellFlagsNoParams.has(tokenLower)) {
731
774
  flags.add(token);
732
- i++;
733
775
  } else {
734
- break;
776
+ const isPreEncoded2 = Array.from(flags).some((flag) => flag.toLowerCase() === "-encodedcommand");
777
+ return {
778
+ flags,
779
+ command: input.slice(match.index),
780
+ isPreEncoded: isPreEncoded2
781
+ };
735
782
  }
736
783
  }
737
- const command = tokens.slice(i).join(" ");
784
+ const isPreEncoded = Array.from(flags).some((flag) => flag.toLowerCase() === "-encodedcommand");
738
785
  return {
739
786
  flags,
740
- command,
787
+ command: "",
741
788
  isPreEncoded
742
789
  };
743
790
  };
744
791
 
745
- // packages/core/src/lib/types/shell.ts
746
- var Shell = {
747
- sh: "sh",
748
- bash: "bash",
749
- zsh: "zsh",
750
- pwsh: "pwsh",
751
- fish: "fish",
752
- powershell: "powershell",
753
- cmd: "cmd"
754
- };
755
-
756
- // packages/core/src/lib/process/functions/escape-shell-arg.ts
757
- var escapeShellArg = (value, shell) => {
758
- switch (shell) {
759
- case Shell.cmd: {
760
- const escaped = value.replace(/\^/g, "^^^^").replace(/([&<>|()])/g, "^$1").replace(/!/g, "^^!").replace(/%/g, "%%%%");
761
- return `"${escaped}"`;
792
+ // packages/core/src/lib/process/functions/strip-clixml.ts
793
+ var createClixmlStripper = () => {
794
+ let buffer = "";
795
+ return (chunk) => {
796
+ buffer += chunk;
797
+ if (!buffer.includes("<") && !buffer.includes("#< CLIXML")) {
798
+ const out = buffer;
799
+ buffer = "";
800
+ return out;
762
801
  }
763
- case Shell.powershell:
764
- case Shell.pwsh:
765
- return `'${value.replace(/'/g, "''")}'`;
766
- case Shell.sh:
767
- case Shell.bash:
768
- case Shell.zsh:
769
- case Shell.fish:
770
- default:
771
- return `'${value.replace(/'/g, "'\\''")}'`;
772
- }
773
- };
774
-
775
- // packages/core/src/lib/process/functions/get-shell.ts
776
- import {
777
- platform,
778
- env
779
- } from "process";
780
- var getShell = () => {
781
- const isWindows = platform === "win32";
782
- if (!isWindows) {
783
- const envShell = (env.SHELL ?? "").toLowerCase();
784
- switch (true) {
785
- case envShell.includes("bash"):
786
- return Shell.bash;
787
- case envShell.includes("zsh"):
788
- return Shell.zsh;
789
- case envShell.includes("fish"):
790
- return Shell.fish;
791
- default:
792
- return Shell.sh;
802
+ const hasClixmlHeader = buffer.includes("#< CLIXML");
803
+ const hasClixmlTags = /<Obj|S S="Error"|<\/Objs>/.test(buffer);
804
+ if (!hasClixmlHeader && !hasClixmlTags) {
805
+ const out = buffer;
806
+ buffer = "";
807
+ return out;
793
808
  }
794
- }
795
- if (Bun.which(Shell.pwsh)) {
796
- return Shell.pwsh;
797
- }
798
- if (Bun.which(Shell.powershell)) {
799
- return Shell.powershell;
800
- }
801
- return Shell.cmd;
809
+ buffer = buffer.replace(/#< CLIXML/g, "").replace(/<Obj S="progress"[\s\S]*?<\/Obj>/g, "");
810
+ let output = "";
811
+ buffer = buffer.replace(/<S S="Error">([\s\S]*?)<\/S>/g, (_, msg) => {
812
+ output += msg;
813
+ return "";
814
+ });
815
+ if (buffer.includes("</Objs>")) {
816
+ output += buffer.replace(/<[^>]+>/g, "");
817
+ buffer = "";
818
+ }
819
+ if (!output)
820
+ return "";
821
+ return output.replace(/_x([0-9A-F]{4})_/g, (_, hex) => String.fromCharCode(parseInt(hex, 16))).replace(/<[^>]+>/g, "");
822
+ };
802
823
  };
803
824
 
804
825
  // packages/core/src/lib/process/functions/get-commands-for-shell.ts
@@ -806,11 +827,14 @@ var getCommandsForShell = (shellCommand) => {
806
827
  const shell = getShell();
807
828
  switch (shell) {
808
829
  case Shell.cmd:
809
- return [
810
- shell,
811
- "/c",
812
- escapeShellArg(shellCommand, shell)
813
- ];
830
+ return {
831
+ commands: [
832
+ shell,
833
+ "/c",
834
+ shellCommand
835
+ ],
836
+ stderrProcessor: identity
837
+ };
814
838
  case Shell.pwsh:
815
839
  case Shell.powershell:
816
840
  const {
@@ -819,35 +843,66 @@ var getCommandsForShell = (shellCommand) => {
819
843
  isPreEncoded
820
844
  } = parsePsShellFlags(shellCommand);
821
845
  if (isPreEncoded) {
822
- return [shell, shellCommand];
846
+ return {
847
+ commands: [shell, ...flags],
848
+ stderrProcessor: createClixmlStripper()
849
+ };
823
850
  }
824
851
  const encodedCommand = Buffer.from(command || " ", "utf16le").toString("base64");
825
- return [
826
- shell,
827
- ...flags,
828
- ...encodedCommand ? ["-EncodedCommand", encodedCommand] : []
829
- ];
852
+ return {
853
+ commands: [
854
+ shell,
855
+ ...flags,
856
+ ...encodedCommand ? ["-EncodedCommand", encodedCommand] : []
857
+ ],
858
+ stderrProcessor: createClixmlStripper()
859
+ };
830
860
  default:
831
- return [
832
- shell,
833
- "-c",
834
- escapeShellArg(shellCommand, shell)
835
- ];
861
+ return {
862
+ commands: [
863
+ shell,
864
+ "-c",
865
+ shellCommand
866
+ ],
867
+ stderrProcessor: identity
868
+ };
836
869
  }
837
870
  };
838
871
 
839
872
  // packages/core/src/lib/process/functions/get-line-buffered-writer.ts
840
- import { identity } from "@package-pal/util";
841
- var getLineBufferedWriter = (prefix, style = identity, write = process.stdout.write.bind(process.stdout)) => {
873
+ import { identity as identity2 } from "@package-pal/util";
874
+ var getLineBufferedWriter = (prefix, style = identity2, write = process.stdout.write.bind(process.stdout)) => {
842
875
  let buffer = "";
843
- return (chunk) => {
844
- buffer += chunk;
845
- const lines = buffer.split(`
876
+ return {
877
+ write: (chunk) => {
878
+ if (chunk === null) {
879
+ if (buffer.length > 0) {
880
+ write(`${prefix}${style(buffer)}
881
+ `);
882
+ buffer = "";
883
+ }
884
+ return;
885
+ }
886
+ buffer += chunk;
887
+ let start = 0;
888
+ let newlineIndex = buffer.indexOf(`
846
889
  `);
847
- buffer = lines.pop() ?? "";
848
- for (const line of lines) {
849
- write(`${prefix}${style(line)}
890
+ while (newlineIndex !== -1) {
891
+ let end = newlineIndex;
892
+ if (end > start && buffer[end - 1] === "\r") {
893
+ end--;
894
+ }
895
+ const line = buffer.slice(start, end);
896
+ write(`${prefix}${style(line)}
850
897
  `);
898
+ start = newlineIndex + 1;
899
+ newlineIndex = buffer.indexOf(`
900
+ `, start);
901
+ }
902
+ buffer = buffer.slice(start);
903
+ },
904
+ flush() {
905
+ this.write(null);
851
906
  }
852
907
  };
853
908
  };
@@ -856,10 +911,14 @@ var getLineBufferedWriter = (prefix, style = identity, write = process.stdout.wr
856
911
  var readStream = async (stream, use) => {
857
912
  const decoder = new TextDecoder;
858
913
  const reader = stream.getReader();
859
- let result = await reader.read();
860
- while (!result.done) {
861
- use(decoder.decode(result.value, { stream: true }));
862
- result = await reader.read();
914
+ try {
915
+ let result = await reader.read();
916
+ while (!result.done) {
917
+ use(decoder.decode(result.value, { stream: true }));
918
+ result = await reader.read();
919
+ }
920
+ } finally {
921
+ reader.releaseLock();
863
922
  }
864
923
  const flush = decoder.decode();
865
924
  if (flush) {
@@ -878,14 +937,21 @@ var cancelCodes = new Set([
878
937
  ]);
879
938
  var runSubprocess = async (opts) => {
880
939
  if (opts.signal?.aborted) {
881
- opts.logger.debug(styleText7("dim", `Skipped '${opts.debugName}' subprocess command; signal already cancelled.`));
940
+ opts.logger?.debug(styleText7("dim", `Skipped '${opts.debugName}' subprocess command; signal already cancelled.`));
882
941
  return ExitState.Cancelled;
883
942
  }
884
- const commands = getCommandsForShell(opts.shellCommand);
943
+ const {
944
+ commands,
945
+ stderrProcessor
946
+ } = getCommandsForShell(opts.shellCommand);
885
947
  const baseSubprocessOpts = {
886
948
  stdout: "pipe",
887
949
  stderr: "pipe",
888
- stdin: "ignore"
950
+ stdin: "ignore",
951
+ env: {
952
+ ...process.env,
953
+ ...opts.env
954
+ }
889
955
  };
890
956
  const subprocessOpts = {
891
957
  ...baseSubprocessOpts,
@@ -898,25 +964,30 @@ var runSubprocess = async (opts) => {
898
964
  const [readStdout, readStderr] = [{
899
965
  source: subprocess.stdout,
900
966
  type: StdType.Out,
901
- write: getLineBufferedWriter(styleText7("dim", `[O-${pid}]`.padEnd(minPrefixLen, " ")))
967
+ writer: getLineBufferedWriter(styleText7("dim", `[O-${pid}]`.padEnd(minPrefixLen, " ")))
902
968
  }, {
903
969
  source: subprocess.stderr,
904
970
  type: StdType.Err,
905
- write: getLineBufferedWriter(styleText7("yellow", styleText7("dim", `[E-${pid}]`.padEnd(minPrefixLen, " "))))
906
- }].map(({
971
+ writer: getLineBufferedWriter(styleText7("yellow", styleText7("dim", `[E-${pid}]`.padEnd(minPrefixLen, " "))), undefined, process.stderr.write.bind(process.stderr))
972
+ }].map(async ({
907
973
  source,
908
974
  type,
909
- write
975
+ writer
910
976
  }) => {
911
- return readStream(source, (chunk) => {
912
- write(chunk);
977
+ await readStream(source, (chunk) => {
978
+ const processedChunk = type === StdType.Err ? stderrProcessor(chunk) : chunk;
979
+ if (processedChunk === "" && chunk !== "") {
980
+ return;
981
+ }
982
+ writer.write(processedChunk);
913
983
  if (opts.onStdChunk) {
914
- opts.onStdChunk(chunk, type);
984
+ opts.onStdChunk(processedChunk, type);
915
985
  }
916
986
  });
987
+ writer.flush();
917
988
  });
918
989
  const executedCommand = commands.join(" ");
919
- opts.logger.debug(styleText7("dim", `Started '${opts.debugName}' subprocess command '${opts.shellCommand}' (${executedCommand}) with PID ${pid}.`));
990
+ opts.logger?.debug(styleText7("dim", `Started '${opts.debugName}' subprocess command '${opts.shellCommand}' (${executedCommand}) with PID ${pid}.`));
920
991
  const [
921
992
  ,
922
993
  ,
@@ -926,14 +997,14 @@ var runSubprocess = async (opts) => {
926
997
  readStderr,
927
998
  subprocess.exited.then((exitCode) => {
928
999
  if (cancelCodes.has(exitCode)) {
929
- opts.logger.debug(styleText7("dim", `Cancelled '${opts.debugName}' subprocess command; PID ${pid} exited.`));
1000
+ opts.logger?.debug(styleText7("dim", `Cancelled '${opts.debugName}' subprocess command; PID ${pid} exited.`));
930
1001
  return ExitState.Cancelled;
931
1002
  }
932
1003
  if (exitCode !== 0) {
933
- opts.logger.error(styleText7("red", `'${opts.debugName}' command '${opts.shellCommand}' (${executedCommand}) with PID ${pid} failed with exit code ${exitCode.toString()}.`));
1004
+ opts.logger?.error(styleText7("red", `'${opts.debugName}' command '${opts.shellCommand}' (${executedCommand}) with PID ${pid} failed with exit code ${exitCode.toString()}.`));
934
1005
  return ExitState.Errored;
935
1006
  }
936
- opts.logger.debug(styleText7("dim", `Completed '${opts.debugName}' subprocess command; PID ${pid} exited.`));
1007
+ opts.logger?.debug(styleText7("dim", `Completed '${opts.debugName}' subprocess command; PID ${pid} exited.`));
937
1008
  return ExitState.Completed;
938
1009
  })
939
1010
  ]);
@@ -943,18 +1014,18 @@ var runSubprocess = async (opts) => {
943
1014
  // packages/core/src/lib/package/functions/run-for-each-package.ts
944
1015
  var runForEachPackage = async (packageGraphs, packageOrder, getCommand, logger, topological = true, concurrency) => {
945
1016
  const controller = new AbortController;
946
- let processPackageOrder = packageOrder.groups.concat(packageOrder.circular);
1017
+ let processPackageOrder = packageOrder.circular.length > 0 ? packageOrder.groups.concat([packageOrder.circular]) : packageOrder.groups;
947
1018
  if (!topological) {
948
1019
  processPackageOrder = [processPackageOrder.flat()];
949
1020
  }
950
1021
  for (const group of processPackageOrder) {
951
1022
  await runAsync(group.map((packageName) => async () => {
952
- const packageNode = assertDefined9(packageGraphs.dependencies.get(packageName));
1023
+ const packageNode = assertDefined8(packageGraphs.dependencies.get(packageName));
953
1024
  const processPackageProps = {
954
1025
  name: packageName,
955
1026
  dir: packageNode.packageData.dir
956
1027
  };
957
- const processPackageCwd = dirname6(packageNode.packageData.path);
1028
+ const processPackageCwd = dirname4(packageNode.packageData.path);
958
1029
  const shellCommand = await getCommand(processPackageProps);
959
1030
  if (!shellCommand) {
960
1031
  return;
@@ -963,6 +1034,10 @@ var runForEachPackage = async (packageGraphs, packageOrder, getCommand, logger,
963
1034
  debugName: `run for ${packageName}`,
964
1035
  shellCommand,
965
1036
  cwd: processPackageCwd,
1037
+ env: {
1038
+ PP_PACKAGE_NAME: packageName,
1039
+ PP_PACKAGE_DIR: processPackageProps.dir
1040
+ },
966
1041
  signal: controller.signal,
967
1042
  logger
968
1043
  });
@@ -974,139 +1049,24 @@ var runForEachPackage = async (packageGraphs, packageOrder, getCommand, logger,
974
1049
  }
975
1050
  };
976
1051
 
977
- // packages/core/src/lib/package/functions/update-package-version.ts
978
- import { styleText as styleText8 } from "util";
979
- var {semver } = globalThis.Bun;
980
- import { inc } from "semver";
981
- var findAndReplaceVersion = ({
982
- raw,
983
- field,
984
- packageName,
985
- updatePackageName,
986
- newVersion,
987
- exact,
988
- logger
989
- }) => {
990
- if (field === "version" && packageName === updatePackageName) {
991
- const versionKey = `"version"`;
992
- const keyIndex = raw.indexOf(versionKey);
993
- if (keyIndex === -1) {
994
- return raw;
995
- }
996
- const versionStart2 = raw.indexOf('"', keyIndex + versionKey.length);
997
- const versionEnd2 = raw.indexOf('"', versionStart2 + 1);
998
- if (versionStart2 === -1 || versionEnd2 === -1) {
999
- return raw;
1000
- }
1001
- const currentVersionString2 = raw.slice(versionStart2 + 1, versionEnd2);
1002
- const updatedVersion2 = newVersion;
1003
- logger.info(`Updating '${updatePackageName}' version: ${currentVersionString2} \u2192 ${updatedVersion2}.`);
1004
- const before2 = raw.slice(0, versionStart2 + 1);
1005
- const after2 = raw.slice(versionEnd2);
1006
- return `${before2}${updatedVersion2}${after2}`;
1007
- }
1008
- const fieldIndex = raw.indexOf(`"${field}"`);
1009
- if (fieldIndex === -1) {
1010
- return raw;
1011
- }
1012
- const fieldStart = raw.indexOf("{", fieldIndex);
1013
- if (fieldStart === -1) {
1014
- return raw;
1015
- }
1016
- const fieldEnd = raw.indexOf("}", fieldStart);
1017
- if (fieldEnd === -1) {
1018
- return raw;
1019
- }
1020
- const fieldBlock = raw.slice(fieldStart, fieldEnd);
1021
- const depKey = `"${packageName}"`;
1022
- const depIndex = fieldBlock.indexOf(depKey);
1023
- if (depIndex === -1) {
1024
- return raw;
1025
- }
1026
- const versionStart = fieldBlock.indexOf('"', depIndex + depKey.length);
1027
- const versionEnd = fieldBlock.indexOf('"', versionStart + 1);
1028
- if (versionStart === -1 || versionEnd === -1) {
1029
- return raw;
1030
- }
1031
- const currentVersionString = fieldBlock.slice(versionStart + 1, versionEnd);
1032
- const preservedPrefix = exact ? "" : /^([~^><=]*)/.exec(currentVersionString)?.[1] ?? "";
1033
- const updatedVersion = `${preservedPrefix}${newVersion}`;
1034
- logger.info(`Updating '${updatePackageName}' ${field} '${packageName}': ${currentVersionString} \u2192 ${updatedVersion}.`);
1035
- const before = raw.slice(0, fieldStart + versionStart + 1);
1036
- const after = raw.slice(fieldStart + versionEnd);
1037
- return `${before}${updatedVersion}${after}`;
1038
- };
1039
- var updatePackageVersion = async (packageName, type, packageGraphs, preId, exact, logger) => {
1040
- logger.debug(styleText8("dim", `Bumping package '${packageName}'...`));
1041
- const packageNode = packageGraphs.dependencies.get(packageName);
1042
- if (!packageNode) {
1043
- throw new Error(`Package '${packageName}' not found.`);
1044
- }
1045
- const currentVersion = packageNode.packageData.version;
1046
- if (!currentVersion) {
1047
- throw new Error(`Package '${packageName}' has no version.`);
1048
- }
1049
- const bumpedVersion = inc(currentVersion, type, undefined, preId);
1050
- if (!bumpedVersion) {
1051
- throw new Error(`Package '${packageName}' version '${currentVersion}' is invalid.`);
1052
- }
1053
- const updatedContent = findAndReplaceVersion({
1054
- raw: packageNode.packageData.rawContent,
1055
- field: "version",
1056
- packageName,
1057
- updatePackageName: packageName,
1058
- newVersion: bumpedVersion,
1059
- exact,
1060
- logger
1061
- });
1062
- const baseWrite = Bun.write(packageNode.packageData.path, updatedContent);
1063
- const dependentWrites = Array.from(dfsTraverseGraph(packageGraphs.dependents, packageName).flatMap((dependent) => {
1064
- return Object.values(DependenciesField).flatMap((field) => {
1065
- const entry = dependent[field];
1066
- const depVersion = entry?.[packageName];
1067
- if (!depVersion) {
1068
- return [];
1069
- }
1070
- if (exact ? depVersion === bumpedVersion : semver.satisfies(bumpedVersion, depVersion)) {
1071
- logger.debug(styleText8("dim", `Skipping '${dependent.name}': ${field} version '${depVersion}' already satisfies '${bumpedVersion}'.`));
1072
- return [];
1073
- }
1074
- const updatedContent2 = findAndReplaceVersion({
1075
- raw: dependent.rawContent,
1076
- field,
1077
- packageName,
1078
- updatePackageName: dependent.name,
1079
- newVersion: bumpedVersion,
1080
- exact,
1081
- logger
1082
- });
1083
- return [Bun.write(dependent.path, updatedContent2)];
1084
- });
1085
- }));
1086
- return Promise.all([baseWrite, ...dependentWrites]).then(() => {
1087
- return;
1088
- });
1089
- };
1090
-
1091
1052
  // packages/core/src/lib/watch/functions/watch-package-changes.ts
1092
1053
  import {
1093
1054
  watch
1094
1055
  } from "fs";
1095
- import { styleText as styleText10 } from "util";
1096
1056
  import {
1097
- dirname as dirname8,
1098
- join as join4
1057
+ dirname as dirname6,
1058
+ join as join3
1099
1059
  } from "path";
1060
+ import { styleText as styleText9 } from "util";
1100
1061
  import {
1101
1062
  assertDefined as assertDefined12,
1102
- DedupePathsBy,
1103
- dedupeSharedPaths,
1104
1063
  getDeferredPromise,
1105
1064
  getStringMatcher,
1106
1065
  isDefined as isDefined4,
1107
- runAsync as runAsync2
1066
+ normalisePath,
1067
+ runAsync as runAsync3
1108
1068
  } from "@package-pal/util";
1109
- var {Glob: Glob2 } = globalThis.Bun;
1069
+ var {Glob } = globalThis.Bun;
1110
1070
 
1111
1071
  // packages/core/src/lib/graph/functions/merge-graphs.ts
1112
1072
  var mergeGraphs = (a, b) => {
@@ -1133,18 +1093,72 @@ var ChangeAction = {
1133
1093
  Restart: "Restart"
1134
1094
  };
1135
1095
 
1096
+ // packages/core/src/lib/watch/types/dedupe-paths-by.ts
1097
+ var DedupePathsBy = {
1098
+ Parent: "parent",
1099
+ Child: "child"
1100
+ };
1101
+
1102
+ // packages/core/src/lib/watch/functions/dedupe-shared-paths.ts
1103
+ import { sep } from "path";
1104
+ import { assertDefined as assertDefined9 } from "@package-pal/util";
1105
+ var dedupeSharedPaths = (paths, by) => {
1106
+ const mapped = paths.map((path) => {
1107
+ let count = 0;
1108
+ for (const char of path) {
1109
+ if (char === sep) {
1110
+ count++;
1111
+ }
1112
+ }
1113
+ return {
1114
+ path,
1115
+ count
1116
+ };
1117
+ });
1118
+ mapped.sort((a, b) => a.count - b.count);
1119
+ const sorted = mapped.map((item) => item.path);
1120
+ const deduped = [];
1121
+ if (by === DedupePathsBy.Parent) {
1122
+ for (const path of sorted) {
1123
+ if (!deduped.some((base) => path.startsWith(base + sep))) {
1124
+ deduped.push(path);
1125
+ }
1126
+ }
1127
+ return deduped;
1128
+ }
1129
+ for (const path of sorted) {
1130
+ for (let i = deduped.length - 1;i >= 0; i--) {
1131
+ const base = assertDefined9(deduped[i]);
1132
+ if (path.startsWith(base + sep)) {
1133
+ deduped.splice(i, 1);
1134
+ }
1135
+ }
1136
+ if (!deduped.some((base) => base.startsWith(path + sep))) {
1137
+ deduped.push(path);
1138
+ }
1139
+ }
1140
+ return Array.from(new Set(deduped));
1141
+ };
1142
+
1136
1143
  // packages/core/src/lib/watch/functions/filter-files-modified-since.ts
1137
- var filterFilesModifiedSince = (paths, sinceMs) => {
1138
- return paths.filter((path) => {
1139
- const changedFile = Bun.file(path);
1140
- const isDeleted = changedFile.lastModified === 0;
1141
- const isModifiedSince = changedFile.lastModified >= sinceMs;
1142
- return isDeleted || isModifiedSince;
1144
+ import { stat } from "fs/promises";
1145
+ import { runAsync as runAsync2 } from "@package-pal/util";
1146
+ var filterFilesModifiedSince = async (paths, sinceMs) => {
1147
+ const tasks = paths.map((path) => async () => {
1148
+ try {
1149
+ const s = await stat(path);
1150
+ const isModifiedSince = s.mtimeMs >= sinceMs;
1151
+ return isModifiedSince ? path : null;
1152
+ } catch {
1153
+ return path;
1154
+ }
1143
1155
  });
1156
+ const results = await runAsync2(tasks, 20);
1157
+ return results.filter((path) => path !== null);
1144
1158
  };
1145
1159
 
1146
1160
  // packages/core/src/lib/watch/functions/get-change-logic.ts
1147
- import { styleText as styleText9 } from "util";
1161
+ import { styleText as styleText8 } from "util";
1148
1162
  import { assertDefined as assertDefined11 } from "@package-pal/util";
1149
1163
 
1150
1164
  // packages/core/src/lib/graph/functions/generate-topological-ranking-range.ts
@@ -1245,21 +1259,21 @@ var getChangeLogic = (packageGraphs, packageChanges, lastProcessedSubgraph, conf
1245
1259
  const changedPackages = Array.from(packageChanges.keys());
1246
1260
  const changedFilePaths = Array.from(packageChanges.values()).flat();
1247
1261
  if (packageChanges.size) {
1248
- logger.debug(styleText9("dim", `Changes detected in ${changedPackages.map((packageName) => `'${packageName}'`).join(", ")}.`));
1249
- logger.debug(styleText9("dim", `Changed file paths: ${changedFilePaths.map((filePath) => `'${filePath}'`).join(", ")}.`));
1262
+ logger?.debug(styleText8("dim", `Changes detected in ${changedPackages.map((packageName) => `'${packageName}'`).join(", ")}.`));
1263
+ logger?.debug(styleText8("dim", `Changed file paths: ${changedFilePaths.map((filePath) => `'${filePath}'`).join(", ")}.`));
1250
1264
  }
1251
1265
  const packageOrder = generateTopologicalSortedGroups(packageGraphs.dependents, logger);
1252
- const packageProcessOrder = packageOrder.groups.toReversed().concat(packageOrder.circular);
1266
+ const packageProcessOrder = packageOrder.circular.length > 0 ? packageOrder.groups.toReversed().concat([packageOrder.circular]) : packageOrder.groups.toReversed();
1253
1267
  const packageRankings = generateTopologicalRanking(packageProcessOrder);
1254
1268
  const changedPackageSubgraph = extractSubgraph(packageGraphs.dependents, changedPackages);
1255
1269
  const changedPackageOrder = generateTopologicalSortedGroups(changedPackageSubgraph, logger);
1256
- const changedPackageProcessOrder = changedPackageOrder.groups.toReversed().concat(changedPackageOrder.circular);
1270
+ const changedPackageProcessOrder = changedPackageOrder.circular.length > 0 ? changedPackageOrder.groups.toReversed().concat([changedPackageOrder.circular]) : changedPackageOrder.groups.toReversed();
1257
1271
  const isSubgraphOfPrevious = !!lastProcessedSubgraph && isSubgraph(lastProcessedSubgraph, changedPackageSubgraph);
1258
1272
  const isDisjointFromPrevious = !lastProcessedSubgraph || !isSubgraphOfPrevious && isDisjoint(lastProcessedSubgraph, changedPackageSubgraph);
1259
1273
  const isRankedGreaterThanOrEqualToPrevious = !!lastProcessedSubgraph && !isSubgraphOfPrevious && isRankedGreaterThanOrEqual(lastProcessedSubgraph, changedPackageSubgraph, packageRankings);
1260
- logger.debug(styleText9("dim", `Changes are subgraph of previous: ${isSubgraphOfPrevious.toString()}.`));
1261
- logger.debug(styleText9("dim", `Changes are disjoint from previous: ${isDisjointFromPrevious.toString()}.`));
1262
- logger.debug(styleText9("dim", `Changes are ranked greater than or equal to previous: ${isRankedGreaterThanOrEqualToPrevious.toString()}.`));
1274
+ logger?.debug(styleText8("dim", `Changes are subgraph of previous: ${isSubgraphOfPrevious.toString()}.`));
1275
+ logger?.debug(styleText8("dim", `Changes are disjoint from previous: ${isDisjointFromPrevious.toString()}.`));
1276
+ logger?.debug(styleText8("dim", `Changes are ranked greater than or equal to previous: ${isRankedGreaterThanOrEqualToPrevious.toString()}.`));
1263
1277
  let action = ChangeAction.Restart;
1264
1278
  if (!packageChanges.size) {
1265
1279
  action = ChangeAction.Ignore;
@@ -1279,7 +1293,7 @@ var getChangeLogic = (packageGraphs, packageChanges, lastProcessedSubgraph, conf
1279
1293
  });
1280
1294
  }
1281
1295
  }
1282
- logger.debug(styleText9("dim", `Determined change action: ${action}.`));
1296
+ logger?.debug(styleText8("dim", `Determined change action: ${action}.`));
1283
1297
  return {
1284
1298
  changedPackageProcessOrder,
1285
1299
  changedPackageSubgraph,
@@ -1287,16 +1301,11 @@ var getChangeLogic = (packageGraphs, packageChanges, lastProcessedSubgraph, conf
1287
1301
  };
1288
1302
  };
1289
1303
 
1290
- // packages/core/src/lib/watch/functions/normalise-pattern-separators.ts
1291
- var normalisePatternSeparators = (path) => {
1292
- return path.replace(/\\/g, "/");
1293
- };
1294
-
1295
1304
  // packages/core/src/lib/watch/functions/normalise-watched-file-path.ts
1296
1305
  import {
1297
1306
  basename as basename3,
1298
- dirname as dirname7,
1299
- join as join3
1307
+ dirname as dirname5,
1308
+ join as join2
1300
1309
  } from "path";
1301
1310
  var removeTrailing = [
1302
1311
  "~",
@@ -1309,34 +1318,34 @@ var removeTrailing = [
1309
1318
  ".swn"
1310
1319
  ];
1311
1320
  var normaliseWatchedFilePath = (filePath) => {
1312
- const dir = dirname7(filePath);
1321
+ const dir = dirname5(filePath);
1313
1322
  let base = basename3(filePath);
1323
+ const baseLower = base.toLowerCase();
1314
1324
  for (const trailing of removeTrailing) {
1315
- if (base.toLowerCase().endsWith(trailing)) {
1325
+ if (baseLower.endsWith(trailing)) {
1316
1326
  const sliceStart = base.startsWith(".") ? 1 : 0;
1317
1327
  base = base.slice(sliceStart, -trailing.length);
1318
1328
  break;
1319
1329
  }
1320
1330
  }
1321
- return join3(dir, base);
1331
+ return join2(dir, base);
1322
1332
  };
1323
1333
 
1324
1334
  // packages/core/src/lib/watch/functions/watch-package-changes.ts
1325
1335
  var fileModifiedThresholdMs = 5000;
1326
- var lastProcessedSubgraph;
1327
- var onProcessPackage = async (packageGraphs, packageChanges, watchConfig, determineAbortController, logger) => {
1336
+ var onProcessPackage = async (packageGraphs, packageChanges, watchConfig, determineAbortController, state, logger) => {
1328
1337
  const {
1329
1338
  action,
1330
1339
  changedPackageProcessOrder,
1331
1340
  changedPackageSubgraph
1332
- } = getChangeLogic(packageGraphs, packageChanges, lastProcessedSubgraph, watchConfig, logger);
1341
+ } = getChangeLogic(packageGraphs, packageChanges, state.lastProcessedSubgraph, watchConfig, logger);
1333
1342
  const isRestart = action === ChangeAction.Restart;
1334
1343
  const isSequential = watchConfig.subprocess.concurrency === 1;
1335
1344
  const controller = determineAbortController(isRestart);
1336
1345
  const onProcessFailure = () => {
1337
- logger.debug(styleText10("dim", "Aborting controller: process failed."));
1346
+ logger.debug(styleText9("dim", "Aborting controller: process failed."));
1338
1347
  controller.abort();
1339
- lastProcessedSubgraph = undefined;
1348
+ state.lastProcessedSubgraph = undefined;
1340
1349
  };
1341
1350
  if (action === ChangeAction.Ignore && packageChanges.size) {
1342
1351
  logger.info(`Changes detected; but were ignored due to 'partialProcessing: true'. Waiting for changes..`);
@@ -1344,10 +1353,10 @@ var onProcessPackage = async (packageGraphs, packageChanges, watchConfig, determ
1344
1353
  }
1345
1354
  if (packageChanges.size) {
1346
1355
  logger.info(`${isRestart ? "Restarting processing" : "Initiating partial processing"} ${isSequential ? "sequentially" : `in parallel${isDefined4(watchConfig.subprocess.concurrency) ? ` with concurrency ${watchConfig.subprocess.concurrency.toString()}` : ""}`}.`);
1347
- lastProcessedSubgraph = lastProcessedSubgraph && !isRestart ? mergeGraphs(lastProcessedSubgraph, changedPackageSubgraph) : changedPackageSubgraph;
1356
+ state.lastProcessedSubgraph = state.lastProcessedSubgraph && !isRestart ? mergeGraphs(state.lastProcessedSubgraph, changedPackageSubgraph) : changedPackageSubgraph;
1348
1357
  }
1349
1358
  for (const group of changedPackageProcessOrder) {
1350
- await runAsync2(group.map((packageName) => async () => {
1359
+ await runAsync3(group.map((packageName) => async () => {
1351
1360
  const packageNode = assertDefined12(packageGraphs.dependencies.get(packageName));
1352
1361
  const changedPaths = packageChanges.get(packageName) ?? [];
1353
1362
  const processPackageProps = {
@@ -1358,7 +1367,7 @@ var onProcessPackage = async (packageGraphs, packageChanges, watchConfig, determ
1358
1367
  totalProcessOrder: changedPackageProcessOrder,
1359
1368
  signal: controller.signal
1360
1369
  };
1361
- const processPackageCwd = dirname8(packageNode.packageData.path);
1370
+ const processPackageCwd = dirname6(packageNode.packageData.path);
1362
1371
  const beforeProcessPackageShellCommand = await watchConfig.hooks.onBeforeProcessPackage(processPackageProps);
1363
1372
  if (beforeProcessPackageShellCommand) {
1364
1373
  await runSubprocess({
@@ -1399,7 +1408,7 @@ var onProcessPackage = async (packageGraphs, packageChanges, watchConfig, determ
1399
1408
  if (!errored) {
1400
1409
  const matchedErrorText = erroredMatcher?.push(chunk).matched();
1401
1410
  if (matchedErrorText) {
1402
- logger.error(styleText10("red", `'${packageName}' subprocess matched error text '${matchedErrorText}'.`));
1411
+ logger.error(styleText9("red", `'${packageName}' subprocess matched error text '${matchedErrorText}'.`));
1403
1412
  errored = true;
1404
1413
  Promise.resolve(watchConfig.hooks.onProcessPackageError(processPackageProps)).then((processPackageErrorCommand) => {
1405
1414
  if (!processPackageErrorCommand) {
@@ -1477,17 +1486,18 @@ var onProcessPackage = async (packageGraphs, packageChanges, watchConfig, determ
1477
1486
  };
1478
1487
  var watchPackageChanges = (packageData, packageGraphs, watchConfig, rootDir, logger) => {
1479
1488
  const dedupedRootPackageData = dedupeSharedPaths(packageData.map((packageData2) => packageData2.path), DedupePathsBy.Parent).map((packagePath) => assertDefined12(packageData.find((data) => data.path === packagePath)));
1480
- logger.debug(styleText10("dim", `Starting ${dedupedRootPackageData.length.toString()} watchers for ${packageData.length.toString()} packages.`));
1489
+ logger.debug(styleText9("dim", `Starting ${dedupedRootPackageData.length.toString()} watchers for ${packageData.length.toString()} packages.`));
1481
1490
  let closed = false;
1491
+ const state = { lastProcessedSubgraph: undefined };
1482
1492
  let debounceTimeout;
1483
1493
  let startedDebounceMs;
1484
1494
  let controller;
1485
- const ignoreGlobs = watchConfig.ignore ? (Array.isArray(watchConfig.ignore) ? watchConfig.ignore : [watchConfig.ignore]).map((pattern) => new Glob2(pattern)) : undefined;
1495
+ const ignoreGlobs = watchConfig.ignore ? (Array.isArray(watchConfig.ignore) ? watchConfig.ignore : [watchConfig.ignore]).map((pattern) => new Glob(pattern)) : undefined;
1486
1496
  const changedPackagePaths = new Map;
1487
1497
  const useController = (reset) => {
1488
1498
  if (controller && (reset || controller.signal.aborted)) {
1489
1499
  if (reset) {
1490
- logger.debug(styleText10("dim", "Aborting controller: reset for new packages."));
1500
+ logger.debug(styleText9("dim", "Aborting controller: reset for new packages."));
1491
1501
  controller.abort();
1492
1502
  }
1493
1503
  controller = undefined;
@@ -1505,12 +1515,12 @@ var watchPackageChanges = (packageData, packageGraphs, watchConfig, rootDir, log
1505
1515
  startedDebounceMs = Date.now();
1506
1516
  }
1507
1517
  if (packageName && watchPath && filePath) {
1508
- const changedPath = normalisePatternSeparators(join4(watchPath, normaliseWatchedFilePath(filePath)));
1518
+ const changedPath = normalisePath(join3(watchPath, normaliseWatchedFilePath(filePath)));
1509
1519
  if (ignoreGlobs?.some((glob) => glob.match(changedPath))) {
1510
- logger.debug(styleText10("dim", `Ignoring change '${changedPath}' (matched ignore pattern).`));
1520
+ logger.debug(styleText9("dim", `Ignoring change '${changedPath}' (matched ignore pattern).`));
1511
1521
  return;
1512
1522
  }
1513
- logger.debug(styleText10("dim", `Tracked change '${changedPath}'.`));
1523
+ logger.debug(styleText9("dim", `Tracked change '${changedPath}'.`));
1514
1524
  const existingPaths = changedPackagePaths.get(packageName);
1515
1525
  if (existingPaths) {
1516
1526
  existingPaths.add(changedPath);
@@ -1523,30 +1533,32 @@ var watchPackageChanges = (packageData, packageGraphs, watchConfig, rootDir, log
1523
1533
  }
1524
1534
  const debounceMs = isInitial ? 0 : watchConfig.debounceMs;
1525
1535
  debounceTimeout = setTimeout(() => {
1526
- if (closed) {
1527
- return;
1528
- }
1529
- const packageChanges = new Map;
1530
- for (const [packageName2, paths] of changedPackagePaths) {
1531
- const dedupedPaths = dedupeSharedPaths(Array.from(paths), DedupePathsBy.Child).sort();
1532
- const processedPaths = filterFilesModifiedSince(dedupedPaths, assertDefined12(startedDebounceMs) - fileModifiedThresholdMs);
1533
- if (processedPaths.length) {
1534
- packageChanges.set(packageName2, processedPaths);
1536
+ (async () => {
1537
+ if (closed) {
1538
+ return;
1535
1539
  }
1536
- }
1537
- startedDebounceMs = undefined;
1538
- changedPackagePaths.clear();
1539
- if (!packageChanges.size && !isInitial) {
1540
- return;
1541
- }
1542
- onProcessPackage(packageGraphs, packageChanges, watchConfig, (reset) => useController(reset), logger);
1540
+ const packageChanges = new Map;
1541
+ for (const [packageName2, paths] of changedPackagePaths) {
1542
+ const dedupedPaths = dedupeSharedPaths(Array.from(paths), DedupePathsBy.Child).sort();
1543
+ const processedPaths = await filterFilesModifiedSince(dedupedPaths, assertDefined12(startedDebounceMs) - fileModifiedThresholdMs);
1544
+ if (processedPaths.length) {
1545
+ packageChanges.set(packageName2, processedPaths);
1546
+ }
1547
+ }
1548
+ startedDebounceMs = undefined;
1549
+ changedPackagePaths.clear();
1550
+ if (!packageChanges.size && !isInitial) {
1551
+ return;
1552
+ }
1553
+ onProcessPackage(packageGraphs, packageChanges, watchConfig, (reset) => useController(reset), state, logger);
1554
+ })();
1543
1555
  }, debounceMs);
1544
1556
  };
1545
1557
  const watchers = dedupedRootPackageData.map(({
1546
1558
  name,
1547
1559
  path
1548
1560
  }) => {
1549
- const watchPath = dirname8(path);
1561
+ const watchPath = dirname6(path);
1550
1562
  return watch(watchPath, { recursive: true }, (event, filePath) => {
1551
1563
  onWatchEvent({
1552
1564
  watchPath,
@@ -1560,12 +1572,12 @@ var watchPackageChanges = (packageData, packageGraphs, watchConfig, rootDir, log
1560
1572
  watchers.forEach((watcher) => {
1561
1573
  watcher.close();
1562
1574
  });
1563
- logger.debug(styleText10("dim", "Aborting controller: closing watchers."));
1575
+ logger.debug(styleText9("dim", "Aborting controller: closing watchers."));
1564
1576
  controller?.abort();
1565
1577
  closed = true;
1566
1578
  };
1567
1579
  process.on("SIGINT", () => {
1568
- logger.debug(styleText10("dim", "Received SIGINT: closing watchers."));
1580
+ logger.debug(styleText9("dim", "Received SIGINT: closing watchers."));
1569
1581
  closeWatchers();
1570
1582
  process.exit(0);
1571
1583
  });
@@ -1583,10 +1595,10 @@ var watchPackageChanges = (packageData, packageGraphs, watchConfig, rootDir, log
1583
1595
  });
1584
1596
  return { close: () => {
1585
1597
  if (closed) {
1586
- logger.debug(styleText10("dim", "Watchers already closed."));
1598
+ logger.debug(styleText9("dim", "Watchers already closed."));
1587
1599
  return;
1588
1600
  }
1589
- logger.debug(styleText10("dim", "Closing watchers."));
1601
+ logger.debug(styleText9("dim", "Closing watchers."));
1590
1602
  closeWatchers();
1591
1603
  } };
1592
1604
  };
@@ -1599,7 +1611,7 @@ var readPackagePalConfig = (options) => {
1599
1611
  var readPackageData = async (options) => {
1600
1612
  checkBun();
1601
1613
  const packagePatterns = Array.isArray(options.config.packages) ? options.config.packages : [options.config.packages];
1602
- return loadPackages(options.rootDir, packagePatterns, options.config.logger);
1614
+ return loadPackages(options.rootDir, packagePatterns, options.adapter, options.config.logger);
1603
1615
  };
1604
1616
  var getPackageGraphs = (options) => {
1605
1617
  checkBun();
@@ -1613,11 +1625,9 @@ var getPackageCircularDependencyPaths = (options) => {
1613
1625
  checkBun();
1614
1626
  return generatePackageCircularDependencyPaths(options.packageGraphs, options.packageOrder, options.config.logger);
1615
1627
  };
1616
- var bumpPackageVersion = (options) => {
1628
+ var bumpPackageVersion2 = (options) => {
1617
1629
  checkBun();
1618
- const exact = isDefined5(options.exact) ? options.exact : options.config.version.exact;
1619
- const preId = isDefined5(options.preId) ? options.preId : options.config.version.preId;
1620
- return updatePackageVersion(options.packageName, options.type, options.packageGraphs, preId, exact, options.config.logger);
1630
+ return bumpPackageVersion(options);
1621
1631
  };
1622
1632
  var watchPackages = (options) => {
1623
1633
  checkBun();
@@ -1629,15 +1639,18 @@ var forEachPackage = (options) => {
1629
1639
  };
1630
1640
  export {
1631
1641
  watchPackages,
1642
+ scanPackagePaths,
1632
1643
  readPackagePalConfig,
1633
1644
  readPackageData,
1634
1645
  getPackageOrder,
1635
1646
  getPackageGraphs,
1636
1647
  getPackageCircularDependencyPaths,
1637
1648
  forEachPackage,
1638
- bumpPackageVersion,
1649
+ dfsTraverseGraph2 as dfsTraverseGraph,
1650
+ bumpPackageVersion2 as bumpPackageVersion,
1651
+ PackageAdapter,
1639
1652
  BumpVersionType
1640
1653
  };
1641
1654
 
1642
- //# debugId=C0E622D78585C05964756E2164756E21
1655
+ //# debugId=C18A12C7802A030C64756E2164756E21
1643
1656
  //# sourceMappingURL=index.js.map