@package-pal/core 0.0.2 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/index.d.ts +0 -1
  2. package/index.d.ts.map +1 -1
  3. package/index.js +535 -351
  4. package/index.js.map +30 -27
  5. package/lib/api.d.ts +7 -2
  6. package/lib/api.d.ts.map +1 -1
  7. package/lib/configuration/functions/load-config.d.ts +2 -2
  8. package/lib/configuration/functions/load-config.d.ts.map +1 -1
  9. package/lib/configuration/functions/parse-config.d.ts +4 -3
  10. package/lib/configuration/functions/parse-config.d.ts.map +1 -1
  11. package/lib/configuration/schemas/config.d.ts +17 -11
  12. package/lib/configuration/schemas/config.d.ts.map +1 -1
  13. package/lib/configuration/types/activated-config.d.ts +4 -0
  14. package/lib/configuration/types/activated-config.d.ts.map +1 -1
  15. package/lib/configuration/types/config.d.ts +1 -0
  16. package/lib/configuration/types/config.d.ts.map +1 -1
  17. package/lib/graph/functions/generate-graphs.d.ts.map +1 -1
  18. package/lib/graph/functions/generate-package-circular-dependency-paths.d.ts.map +1 -1
  19. package/lib/graph/functions/generate-topological-sorted-groups.d.ts.map +1 -1
  20. package/lib/graph/functions/merge-graphs.d.ts +3 -0
  21. package/lib/graph/functions/merge-graphs.d.ts.map +1 -0
  22. package/lib/package/functions/load-packages.d.ts +1 -1
  23. package/lib/package/functions/load-packages.d.ts.map +1 -1
  24. package/lib/package/functions/parse-package.d.ts.map +1 -1
  25. package/lib/package/functions/run-for-each-package.d.ts +6 -0
  26. package/lib/package/functions/run-for-each-package.d.ts.map +1 -0
  27. package/lib/package/functions/scan-package-paths.d.ts +1 -1
  28. package/lib/package/functions/scan-package-paths.d.ts.map +1 -1
  29. package/lib/package/functions/scan-packages.d.ts +1 -1
  30. package/lib/package/functions/scan-packages.d.ts.map +1 -1
  31. package/lib/package/functions/update-package-version.d.ts +1 -1
  32. package/lib/package/functions/update-package-version.d.ts.map +1 -1
  33. package/lib/package/types/dependencies-field.d.ts +9 -0
  34. package/lib/package/types/dependencies-field.d.ts.map +1 -0
  35. package/lib/package/types/package-data.d.ts +5 -4
  36. package/lib/package/types/package-data.d.ts.map +1 -1
  37. package/lib/process/functions/get-commands-for-shell.d.ts.map +1 -0
  38. package/lib/process/functions/get-line-buffered-writer.d.ts.map +1 -0
  39. package/lib/process/functions/parse-ps-flags.d.ts +5 -0
  40. package/lib/process/functions/parse-ps-flags.d.ts.map +1 -0
  41. package/lib/process/functions/read-stream.d.ts +2 -0
  42. package/lib/process/functions/read-stream.d.ts.map +1 -0
  43. package/lib/process/functions/run-subprocess.d.ts.map +1 -0
  44. package/lib/process/types/exit-state.d.ts.map +1 -0
  45. package/lib/process/types/std-type.d.ts.map +1 -0
  46. package/lib/types/bump-package-version-options.d.ts +2 -2
  47. package/lib/types/bump-package-version-options.d.ts.map +1 -1
  48. package/lib/types/for-each-command-callback.d.ts +6 -0
  49. package/lib/types/for-each-command-callback.d.ts.map +1 -0
  50. package/lib/types/for-each-package-options.d.ts +11 -0
  51. package/lib/types/for-each-package-options.d.ts.map +1 -0
  52. package/lib/types/get-config-options.d.ts +1 -1
  53. package/lib/types/get-config-options.d.ts.map +1 -1
  54. package/lib/types/get-package-data-options.d.ts +3 -1
  55. package/lib/types/get-package-data-options.d.ts.map +1 -1
  56. package/lib/types/root-dir-options.d.ts +4 -0
  57. package/lib/types/root-dir-options.d.ts.map +1 -0
  58. package/lib/types/watch-packages-options.d.ts +2 -1
  59. package/lib/types/watch-packages-options.d.ts.map +1 -1
  60. package/lib/watch/functions/get-change-logic.d.ts +11 -0
  61. package/lib/watch/functions/get-change-logic.d.ts.map +1 -0
  62. package/lib/watch/functions/watch-package-changes.d.ts +1 -1
  63. package/lib/watch/functions/watch-package-changes.d.ts.map +1 -1
  64. package/package.json +10 -8
  65. package/lib/watch/functions/get-commands-for-shell.d.ts.map +0 -1
  66. package/lib/watch/functions/get-line-buffered-writer.d.ts.map +0 -1
  67. package/lib/watch/functions/read-stream.d.ts +0 -2
  68. package/lib/watch/functions/read-stream.d.ts.map +0 -1
  69. package/lib/watch/functions/run-async.d.ts +0 -3
  70. package/lib/watch/functions/run-async.d.ts.map +0 -1
  71. package/lib/watch/functions/run-subprocess.d.ts.map +0 -1
  72. package/lib/watch/types/exit-state.d.ts.map +0 -1
  73. package/lib/watch/types/run-async-type.d.ts +0 -7
  74. package/lib/watch/types/run-async-type.d.ts.map +0 -1
  75. package/lib/watch/types/spawn-options.d.ts +0 -4
  76. package/lib/watch/types/spawn-options.d.ts.map +0 -1
  77. package/lib/watch/types/std-type.d.ts.map +0 -1
  78. /package/lib/{watch → process}/functions/get-commands-for-shell.d.ts +0 -0
  79. /package/lib/{watch → process}/functions/get-line-buffered-writer.d.ts +0 -0
  80. /package/lib/{watch → process}/functions/run-subprocess.d.ts +0 -0
  81. /package/lib/{watch → process}/types/exit-state.d.ts +0 -0
  82. /package/lib/{watch → process}/types/std-type.d.ts +0 -0
package/index.js CHANGED
@@ -15,20 +15,19 @@ import { isDefined as isDefined5 } from "@package-pal/util";
15
15
  // packages/core/src/lib/configuration/functions/check-bun.ts
16
16
  var checkBun = () => {
17
17
  if (!Bun) {
18
- throw new Error("This package must be run with the Bun runtime.");
18
+ throw new Error("This package must be run using the Bun runtime (see https://bun.com/).");
19
19
  }
20
20
  };
21
21
 
22
22
  // packages/core/src/lib/configuration/functions/load-config.ts
23
+ import { styleText } from "util";
24
+ import { dirname as dirname3 } from "path";
25
+ import { cwd } from "process";
23
26
  import {
24
27
  deepMergeDefined,
25
28
  formatSimpleLogObject,
26
29
  noOp as noOp2
27
30
  } from "@package-pal/util";
28
- import {
29
- bgGray,
30
- dim
31
- } from "yoctocolors";
32
31
 
33
32
  // packages/core/src/lib/configuration/functions/get-default-logger.ts
34
33
  import {
@@ -94,6 +93,7 @@ var Config = z3.object({
94
93
  watch: z3.optional(zLooseObjectWithoutIndexSignature({
95
94
  debounceMs: z3.optional(z3.number()),
96
95
  hooks: z3.optional(z3.object({
96
+ onInit: z3.optional(zLooseFunction()),
97
97
  onBeforeProcessPackage: z3.optional(zLooseFunction()),
98
98
  onProcessPackage: z3.optional(zLooseFunction()),
99
99
  onProcessPackageError: z3.optional(zLooseFunction()),
@@ -104,9 +104,9 @@ var Config = z3.object({
104
104
  })),
105
105
  subprocess: z3.optional(z3.object({
106
106
  partialProcessing: z3.optional(z3.boolean()),
107
- parallelProcessing: z3.optional(z3.boolean()),
108
- matchLongRunningOutputAsReady: z3.nullish(z3.string()),
109
- matchLongRunningOutputAsErrored: z3.nullish(z3.string())
107
+ concurrency: z3.nullish(z3.number()),
108
+ matchLongRunningOutputAsReady: z3.nullish(z3.union([z3.string(), z3.array(z3.string())])),
109
+ matchLongRunningOutputAsErrored: z3.nullish(z3.union([z3.string(), z3.array(z3.string())]))
110
110
  }))
111
111
  })),
112
112
  logLevel: z3.optional(LogLevel)
@@ -227,6 +227,7 @@ var defaultConfig = {
227
227
  watch: {
228
228
  debounceMs: 500,
229
229
  hooks: {
230
+ onInit: noOp2,
230
231
  onBeforeProcessPackage: noOp2,
231
232
  onProcessPackage: noOp2,
232
233
  onProcessPackageError: noOp2,
@@ -237,7 +238,7 @@ var defaultConfig = {
237
238
  },
238
239
  subprocess: {
239
240
  partialProcessing: false,
240
- parallelProcessing: true,
241
+ concurrency: null,
241
242
  matchLongRunningOutputAsReady: null,
242
243
  matchLongRunningOutputAsErrored: null
243
244
  }
@@ -249,31 +250,48 @@ var loadConfig = async (overrideConfigPath) => {
249
250
  const path = await searchConfigPath(overrideConfigPath);
250
251
  if (!path) {
251
252
  defaultConfig.logger.info("No config file found. Defaults will be applied.");
252
- return defaultConfig;
253
+ return {
254
+ config: defaultConfig,
255
+ rootDir: cwd()
256
+ };
253
257
  }
254
258
  const parsedConfig = await parseConfig(path);
255
259
  const parsedLogger = parsedConfig["logger"];
256
260
  const logger = parsedLogger ?? (!parsedConfig.logLevel || parsedConfig.logLevel === defaultConfig.logLevel ? defaultConfig.logger : getDefaultLogger(parsedConfig.logLevel));
257
- logger.debug(dim(bgGray("User config:")), `
258
- ${dim(formatSimpleLogObject(parsedConfig))}`);
259
- logger.debug(dim(bgGray("Default config:")), `
260
- ${dim(formatSimpleLogObject(defaultConfig))}`);
261
+ logger.debug(`Successfully loaded config file '${path}'.`);
262
+ logger.debug(styleText("dim", styleText("bgGray", "User config:")), `
263
+ ${styleText("dim", formatSimpleLogObject(parsedConfig))}`);
264
+ logger.debug(styleText("dim", styleText("bgGray", "Default config:")), `
265
+ ${styleText("dim", formatSimpleLogObject(defaultConfig))}`);
261
266
  const activatedConfig = deepMergeDefined(defaultConfig, parsedConfig);
262
267
  activatedConfig.logger = logger;
263
- logger.debug(dim(bgGray("Activated config:")), `
264
- ${dim(formatSimpleLogObject(activatedConfig))}`);
265
- return activatedConfig;
268
+ logger.debug(styleText("dim", styleText("bgGray", "Activated config:")), `
269
+ ${styleText("dim", formatSimpleLogObject(activatedConfig))}`);
270
+ return {
271
+ config: activatedConfig,
272
+ rootDir: dirname3(path)
273
+ };
266
274
  };
267
275
 
268
276
  // packages/core/src/lib/graph/functions/generate-graphs.ts
277
+ import { styleText as styleText2 } from "util";
269
278
  import { assertDefined as assertDefined2 } from "@package-pal/util";
270
- import { dim as dim2 } from "yoctocolors";
279
+
280
+ // packages/core/src/lib/package/types/dependencies-field.ts
281
+ var DependenciesField = {
282
+ Dependencies: "dependencies",
283
+ DevDependencies: "devDependencies",
284
+ PeerDependencies: "peerDependencies",
285
+ OptionalDependencies: "optionalDependencies"
286
+ };
287
+
288
+ // packages/core/src/lib/graph/functions/generate-graphs.ts
271
289
  var trackPackageEntryDependencies = ({
272
290
  trackedDependencies,
273
291
  packageNames,
274
292
  packageData
275
293
  }) => {
276
- const iterateEntries = [packageData.dependencies, packageData.peerDependencies];
294
+ const iterateEntries = Object.values(DependenciesField).map((field) => packageData[field]);
277
295
  for (const packageEntries of iterateEntries) {
278
296
  if (!packageEntries) {
279
297
  continue;
@@ -301,7 +319,7 @@ var generateReverseGraph = (packages, packageGraph) => {
301
319
  return reversePackageGraph;
302
320
  };
303
321
  var generateGraphs = (packages, logger) => {
304
- logger.debug(dim2(`Generating package graphs for ${packages.length.toString()} packages...`));
322
+ logger.debug(styleText2("dim", `Generating package graphs for ${packages.length.toString()} packages...`));
305
323
  const packageNames = new Set(packages.map((packageData) => packageData.name));
306
324
  const packageGraph = new Map;
307
325
  for (const packageData of packages) {
@@ -324,11 +342,8 @@ var generateGraphs = (packages, logger) => {
324
342
  };
325
343
 
326
344
  // packages/core/src/lib/graph/functions/generate-package-circular-dependency-paths.ts
345
+ import { styleText as styleText3 } from "util";
327
346
  import { assertDefined as assertDefined6 } from "@package-pal/util";
328
- import {
329
- dim as dim3,
330
- yellow
331
- } from "yoctocolors";
332
347
 
333
348
  // packages/core/src/lib/graph/functions/dfs-traverse-graph-paths.ts
334
349
  import { assertDefined as assertDefined3 } from "@package-pal/util";
@@ -479,7 +494,7 @@ var findSampleCyclePath = (scc, graph) => {
479
494
  }));
480
495
  };
481
496
  var generatePackageCircularDependencyPaths = ({ dependents }, packageSorted, logger) => {
482
- logger.debug(dim3("Generating circular dependency paths..."));
497
+ logger.debug(styleText3("dim", "Generating circular dependency paths..."));
483
498
  const subgraph = extractSubgraph(dependents, packageSorted.circular);
484
499
  const scss = findStronglyConnectedComponents(subgraph);
485
500
  const sampleCycles = scss.map((scc) => findSampleCyclePath(scc, subgraph).reverse());
@@ -488,20 +503,17 @@ var generatePackageCircularDependencyPaths = ({ dependents }, packageSorted, log
488
503
  return ` ${(index + 1).toString()}. ` + cycle.map((name) => `'${name}'`).join(" \u2192 ");
489
504
  }).join(`
490
505
  `);
491
- logger.warn(yellow(`${sampleCycles.length.toString()} cyclic paths found:
506
+ logger.warn(styleText3("yellow", `${sampleCycles.length.toString()} cyclic paths found:
492
507
  ${sampleCycleContents}`));
493
508
  } else {
494
- logger.debug(dim3(`No cyclic paths found.`));
509
+ logger.debug(styleText3("dim", `No cyclic paths found.`));
495
510
  }
496
511
  return sampleCycles;
497
512
  };
498
513
 
499
514
  // packages/core/src/lib/graph/functions/generate-topological-sorted-groups.ts
515
+ import { styleText as styleText4 } from "util";
500
516
  import { assertDefined as assertDefined7 } from "@package-pal/util";
501
- import {
502
- dim as dim4,
503
- yellow as yellow2
504
- } from "yoctocolors";
505
517
  var getCircularDependencies = (inDegree) => {
506
518
  return Array.from(inDegree.keys()).sort((a, b) => {
507
519
  const degA = assertDefined7(inDegree.get(a));
@@ -510,7 +522,7 @@ var getCircularDependencies = (inDegree) => {
510
522
  }).sort();
511
523
  };
512
524
  var generateTopologicalSortedGroups = (packageGraph, logger) => {
513
- logger.debug(dim4("Generating topological sorted groups..."));
525
+ logger.debug(styleText4("dim", "Generating topological sorted groups..."));
514
526
  const graphEntries = Array.from(packageGraph.entries());
515
527
  const inDegree = new Map(graphEntries.map(([packageName]) => [packageName, 0]));
516
528
  const graph = new Map(graphEntries.map(([packageName]) => [packageName, new Set]));
@@ -545,10 +557,10 @@ var generateTopologicalSortedGroups = (packageGraph, logger) => {
545
557
  }
546
558
  ready = nextReady;
547
559
  }
548
- logger.debug(dim4(`Sorted packages into ${result.length.toString()} sequential groups of parallelizable dependencies.`));
560
+ logger.debug(styleText4("dim", `Sorted packages into ${result.length.toString()} sequential groups of parallelizable dependencies.`));
549
561
  const circular = getCircularDependencies(inDegree);
550
562
  if (circular.length) {
551
- logger.warn(yellow2(`${circular.length.toString()} packages could not be sorted due to circular dependencies. Correct ordering cannot be guaranteed.`));
563
+ logger.warn(styleText4("yellow", `${circular.length.toString()} packages could not be sorted due to circular dependencies. Correct ordering cannot be guaranteed.`));
552
564
  }
553
565
  return {
554
566
  groups: result.map((group) => group.sort()),
@@ -557,22 +569,19 @@ var generateTopologicalSortedGroups = (packageGraph, logger) => {
557
569
  };
558
570
 
559
571
  // packages/core/src/lib/package/functions/load-packages.ts
560
- import { dim as dim6 } from "yoctocolors";
572
+ import { styleText as styleText6 } from "util";
561
573
 
562
574
  // packages/core/src/lib/package/functions/scan-packages.ts
575
+ import { styleText as styleText5 } from "util";
563
576
  import {
564
- dirname as dirname4,
577
+ dirname as dirname5,
565
578
  join as join2
566
579
  } from "path";
567
580
  import { formatUnknownError } from "@package-pal/util";
568
- import {
569
- dim as dim5,
570
- red
571
- } from "yoctocolors";
572
581
 
573
582
  // packages/core/src/lib/package/functions/parse-package.ts
574
583
  import {
575
- dirname as dirname3,
584
+ dirname as dirname4,
576
585
  basename as basename2
577
586
  } from "path";
578
587
  import { isDefined as isDefined2 } from "@package-pal/util";
@@ -587,14 +596,17 @@ var parsePackage = (path, text) => {
587
596
  peerDependencies,
588
597
  devDependencies
589
598
  } = props;
590
- if (isDefined2(dependencies) && !(typeof dependencies === "object") || isDefined2(peerDependencies) && !(typeof peerDependencies === "object") || isDefined2(devDependencies) && !(typeof devDependencies === "object")) {
591
- return;
599
+ for (const field of Object.values(DependenciesField)) {
600
+ const value = props[field];
601
+ if (isDefined2(value) && typeof value !== "object") {
602
+ return;
603
+ }
592
604
  }
593
605
  return {
594
606
  rawContent: text,
595
607
  path,
596
608
  name: props.name ?? path,
597
- dir: basename2(dirname3(path)),
609
+ dir: basename2(dirname4(path)),
598
610
  version: props.version ?? undefined,
599
611
  dependencies: dependencies ?? undefined,
600
612
  peerDependencies: peerDependencies ?? undefined,
@@ -604,41 +616,51 @@ var parsePackage = (path, text) => {
604
616
 
605
617
  // packages/core/src/lib/package/functions/scan-package-paths.ts
606
618
  import { scanGlobPatternPaths } from "@package-pal/util";
607
- var scanPackagePaths = (packages) => {
608
- return scanGlobPatternPaths(packages, {
619
+ var scanPackagePaths = (packages, cwd2) => {
620
+ const baseOpts = {
609
621
  absolute: true,
610
622
  onlyFiles: false
611
- });
623
+ };
624
+ const opts = {
625
+ ...baseOpts,
626
+ ...cwd2 ? { cwd: cwd2 } : {}
627
+ };
628
+ return scanGlobPatternPaths(packages, opts);
612
629
  };
613
630
 
614
631
  // packages/core/src/lib/package/functions/scan-packages.ts
615
- var scanPackages = async function* (patterns, logger) {
616
- for await (const path of scanPackagePaths(patterns)) {
632
+ var scanPackages = async function* (patterns, logger, cwd2) {
633
+ for await (const path of scanPackagePaths(patterns, cwd2)) {
617
634
  const packagePath = join2(path, "package.json");
618
- const dir = dirname4(packagePath);
635
+ const dir = dirname5(packagePath);
619
636
  try {
637
+ logger.debug(styleText5("dim", `Trying to read read package.json in '${dir}'.`));
620
638
  const file = Bun.file(packagePath);
639
+ if (!file.size) {
640
+ logger.debug(styleText5("dim", `Failed to read package.json in '${dir}' - ${styleText5("red", "File not found")}.`));
641
+ continue;
642
+ }
621
643
  const text = await file.text();
622
644
  const packageData = parsePackage(packagePath, text);
623
645
  if (!packageData) {
624
- logger.debug(dim5(`Invalid package.json found in '${dir}'.`));
646
+ logger.debug(styleText5("dim", `Invalid package.json found in '${dir}'.`));
625
647
  continue;
626
648
  }
627
- logger.debug(dim5(`Successfully read package.json in '${dir}'.`));
649
+ logger.debug(styleText5("dim", `Successfully read package.json in '${dir}'.`));
628
650
  yield packageData;
629
651
  } catch (e) {
630
- logger.debug(dim5(`Failed to read package.json in '${dir}' - ${red(formatUnknownError(e))}.`));
652
+ logger.debug(styleText5("dim", `Failed to read package.json in '${dir}' - ${styleText5("red", formatUnknownError(e))}.`));
631
653
  }
632
654
  }
633
655
  };
634
656
 
635
657
  // packages/core/src/lib/package/functions/load-packages.ts
636
- var loadPackages = async (packagePatterns, logger) => {
658
+ var loadPackages = async (rootDir, packagePatterns, logger) => {
637
659
  const patternContent = packagePatterns.map((pattern) => `'${pattern}'`).join(", ");
638
- logger.debug(dim6(`Loading packages matching pattern/s ${patternContent}...`));
660
+ logger.debug(styleText6("dim", `Loading packages matching pattern/s ${patternContent}...${rootDir ? ` from ${rootDir}` : ""}`));
639
661
  const packages = [];
640
662
  const seen = new Set;
641
- for await (const packageData of scanPackages(Array.from(new Set(packagePatterns)), logger)) {
663
+ for await (const packageData of scanPackages(Array.from(new Set(packagePatterns)), logger, rootDir)) {
642
664
  if (seen.has(packageData.name)) {
643
665
  continue;
644
666
  }
@@ -651,10 +673,282 @@ var loadPackages = async (packagePatterns, logger) => {
651
673
  return packages;
652
674
  };
653
675
 
676
+ // packages/core/src/lib/package/functions/run-for-each-package.ts
677
+ import { dirname as dirname6 } from "path";
678
+ import {
679
+ assertDefined as assertDefined9,
680
+ runAsync
681
+ } from "@package-pal/util";
682
+
683
+ // packages/core/src/lib/process/functions/run-subprocess.ts
684
+ import { styleText as styleText7 } from "util";
685
+
686
+ // packages/core/src/lib/process/types/exit-state.ts
687
+ var ExitState = {
688
+ Completed: "Completed",
689
+ Errored: "Errored",
690
+ Cancelled: "Cancelled"
691
+ };
692
+
693
+ // packages/core/src/lib/process/types/std-type.ts
694
+ var StdType = {
695
+ Out: "Out",
696
+ Err: "Err"
697
+ };
698
+
699
+ // packages/core/src/lib/process/functions/get-commands-for-shell.ts
700
+ import {
701
+ escapeShellArg,
702
+ getShell,
703
+ Shell
704
+ } from "@package-pal/util";
705
+
706
+ // packages/core/src/lib/process/functions/parse-ps-flags.ts
707
+ import { assertDefined as assertDefined8 } from "@package-pal/util";
708
+ var knownFlagsWithParams = new Set([
709
+ "-executionpolicy",
710
+ "-windowstyle",
711
+ "-version",
712
+ "-file",
713
+ "-inputformat",
714
+ "-outputformat",
715
+ "-workingdirectory",
716
+ "-psconsolefile",
717
+ "-pshome",
718
+ "-configurationname",
719
+ "-argumentlist",
720
+ "-warningaction",
721
+ "-erroraction",
722
+ "-informationaction",
723
+ "-informationvariable",
724
+ "-warningvariable",
725
+ "-errorvariable",
726
+ "-outvariable",
727
+ "-outbuffer",
728
+ "-throttlelimit",
729
+ "-culture",
730
+ "-uiculture"
731
+ ]);
732
+ var knownFlagsNoParams = new Set([
733
+ "-noprofile",
734
+ "-noninteractive",
735
+ "-nologo",
736
+ "-sta",
737
+ "-mta",
738
+ "-encodedcommand",
739
+ "-command",
740
+ "-help",
741
+ "-?",
742
+ "-verbose",
743
+ "-debug",
744
+ "-whatif",
745
+ "-confirm",
746
+ "-usewindowspowershell",
747
+ "-noexit"
748
+ ]);
749
+ var parsePsFlags = (input) => {
750
+ const tokens = input.trim().split(/\s+/);
751
+ const flags = [];
752
+ let i = 0;
753
+ while (i < tokens.length) {
754
+ const token = assertDefined8(tokens[i]);
755
+ const tokenLower = token.toLowerCase();
756
+ if (knownFlagsWithParams.has(tokenLower)) {
757
+ if (i + 1 >= tokens.length) {
758
+ break;
759
+ }
760
+ flags.push(token, assertDefined8(tokens[i + 1]));
761
+ i += 2;
762
+ continue;
763
+ }
764
+ if (knownFlagsNoParams.has(tokenLower)) {
765
+ flags.push(token);
766
+ i += 1;
767
+ continue;
768
+ }
769
+ break;
770
+ }
771
+ const command = tokens.slice(i).join(" ");
772
+ return {
773
+ flags,
774
+ command
775
+ };
776
+ };
777
+
778
+ // packages/core/src/lib/process/functions/get-commands-for-shell.ts
779
+ var shell;
780
+ var getCommandsForShell = (shellCommand) => {
781
+ shell = shell ?? getShell();
782
+ switch (shell) {
783
+ case Shell.cmd:
784
+ return [
785
+ shell,
786
+ "/c",
787
+ escapeShellArg(shellCommand, shell)
788
+ ];
789
+ case Shell.pwsh:
790
+ case Shell.powershell:
791
+ const {
792
+ flags,
793
+ command
794
+ } = parsePsFlags(shellCommand);
795
+ const encodedCommand = Buffer.from(command, "utf16le").toString("base64");
796
+ return [
797
+ shell,
798
+ ...flags,
799
+ ...encodedCommand ? ["-EncodedCommand", encodedCommand] : []
800
+ ];
801
+ default:
802
+ return [
803
+ shell,
804
+ "-c",
805
+ escapeShellArg(shellCommand, shell)
806
+ ];
807
+ }
808
+ };
809
+
810
+ // packages/core/src/lib/process/functions/get-line-buffered-writer.ts
811
+ import { identity } from "@package-pal/util";
812
+ var getLineBufferedWriter = (prefix, style = identity, write = process.stdout.write.bind(process.stdout)) => {
813
+ let buffer = "";
814
+ return (chunk) => {
815
+ buffer += chunk;
816
+ const lines = buffer.split(`
817
+ `);
818
+ buffer = lines.pop() ?? "";
819
+ for (const line of lines) {
820
+ write(`${prefix}${style(line)}
821
+ `);
822
+ }
823
+ };
824
+ };
825
+
826
+ // packages/core/src/lib/process/functions/read-stream.ts
827
+ var readStream = async (stream, use) => {
828
+ const decoder = new TextDecoder;
829
+ const reader = stream.getReader();
830
+ let result = await reader.read();
831
+ while (!result.done) {
832
+ use(decoder.decode(result.value, { stream: true }));
833
+ result = await reader.read();
834
+ }
835
+ const flush = decoder.decode();
836
+ if (flush) {
837
+ use(flush);
838
+ }
839
+ };
840
+
841
+ // packages/core/src/lib/process/functions/run-subprocess.ts
842
+ var sigintCode = 130;
843
+ var sigtermCode = 143;
844
+ var sigkillCode = 137;
845
+ var cancelCodes = new Set([
846
+ sigintCode,
847
+ sigtermCode,
848
+ sigkillCode
849
+ ]);
850
+ var runSubprocess = async (opts) => {
851
+ if (opts.signal?.aborted) {
852
+ opts.logger.debug(styleText7("dim", `Skipped '${opts.debugName}' subprocess command; signal already cancelled.`));
853
+ return ExitState.Cancelled;
854
+ }
855
+ const commands = getCommandsForShell(opts.shellCommand);
856
+ const baseSubprocessOpts = {
857
+ stdout: "pipe",
858
+ stderr: "pipe",
859
+ stdin: "ignore"
860
+ };
861
+ const subprocessOpts = {
862
+ ...baseSubprocessOpts,
863
+ ...opts.cwd ? { cwd: opts.cwd } : {},
864
+ ...opts.signal ? { signal: opts.signal } : {}
865
+ };
866
+ const subprocess = Bun.spawn(commands, subprocessOpts);
867
+ const pid = subprocess.pid.toString();
868
+ const minPrefixLen = 14;
869
+ const [readStdout, readStderr] = [{
870
+ source: subprocess.stdout,
871
+ type: StdType.Out,
872
+ write: getLineBufferedWriter(styleText7("dim", `[O-${pid}]`.padEnd(minPrefixLen, " ")))
873
+ }, {
874
+ source: subprocess.stderr,
875
+ type: StdType.Err,
876
+ write: getLineBufferedWriter(styleText7("yellow", styleText7("dim", `[E-${pid}]`.padEnd(minPrefixLen, " "))))
877
+ }].map(({
878
+ source,
879
+ type,
880
+ write
881
+ }) => {
882
+ return readStream(source, (chunk) => {
883
+ write(chunk);
884
+ if (opts.onStdChunk) {
885
+ opts.onStdChunk(chunk, type);
886
+ }
887
+ });
888
+ });
889
+ const executedCommand = commands.join(" ");
890
+ opts.logger.debug(styleText7("dim", `Started '${opts.debugName}' subprocess command '${opts.shellCommand}' (${executedCommand}) with PID ${pid}.`));
891
+ const [
892
+ ,
893
+ ,
894
+ exitState
895
+ ] = await Promise.all([
896
+ readStdout,
897
+ readStderr,
898
+ subprocess.exited.then((exitCode) => {
899
+ if (cancelCodes.has(exitCode)) {
900
+ opts.logger.debug(styleText7("dim", `Cancelled '${opts.debugName}' subprocess command; PID ${pid} exited.`));
901
+ return ExitState.Cancelled;
902
+ }
903
+ if (exitCode !== 0) {
904
+ opts.logger.error(styleText7("red", `'${opts.debugName}' command '${opts.shellCommand}' (${executedCommand}) with PID ${pid} failed with exit code ${exitCode.toString()}.`));
905
+ return ExitState.Errored;
906
+ }
907
+ opts.logger.debug(styleText7("dim", `Completed '${opts.debugName}' subprocess command; PID ${pid} exited.`));
908
+ return ExitState.Completed;
909
+ })
910
+ ]);
911
+ return exitState;
912
+ };
913
+
914
+ // packages/core/src/lib/package/functions/run-for-each-package.ts
915
+ var runForEachPackage = async (packageGraphs, packageOrder, getCommand, logger, topological = true, concurrency) => {
916
+ const controller = new AbortController;
917
+ let processPackageOrder = packageOrder.groups.concat(packageOrder.circular);
918
+ if (!topological) {
919
+ processPackageOrder = [processPackageOrder.flat()];
920
+ }
921
+ for (const group of processPackageOrder) {
922
+ await runAsync(group.map((packageName) => async () => {
923
+ const packageNode = assertDefined9(packageGraphs.dependencies.get(packageName));
924
+ const processPackageProps = {
925
+ name: packageName,
926
+ dir: packageNode.packageData.dir
927
+ };
928
+ const processPackageCwd = dirname6(packageNode.packageData.path);
929
+ const shellCommand = await getCommand(processPackageProps);
930
+ if (!shellCommand) {
931
+ return;
932
+ }
933
+ const exitState = await runSubprocess({
934
+ debugName: `run for ${packageName}`,
935
+ shellCommand,
936
+ cwd: processPackageCwd,
937
+ signal: controller.signal,
938
+ logger
939
+ });
940
+ if (exitState === ExitState.Errored) {
941
+ controller.abort();
942
+ throw new Error("Command failed.");
943
+ }
944
+ }), concurrency);
945
+ }
946
+ };
947
+
654
948
  // packages/core/src/lib/package/functions/update-package-version.ts
949
+ import { styleText as styleText8 } from "util";
655
950
  var {semver } = globalThis.Bun;
656
951
  import { inc } from "semver";
657
- import { dim as dim7 } from "yoctocolors";
658
952
  var findAndReplaceVersion = ({
659
953
  raw,
660
954
  field,
@@ -714,7 +1008,7 @@ var findAndReplaceVersion = ({
714
1008
  return `${before}${updatedVersion}${after}`;
715
1009
  };
716
1010
  var updatePackageVersion = async (packageName, type, packageGraphs, preId, exact, logger) => {
717
- logger.debug(dim7(`Bumping package '${packageName}'...`));
1011
+ logger.debug(styleText8("dim", `Bumping package '${packageName}'...`));
718
1012
  const packageNode = packageGraphs.dependencies.get(packageName);
719
1013
  if (!packageNode) {
720
1014
  throw new Error(`Package '${packageName}' not found.`);
@@ -738,15 +1032,14 @@ var updatePackageVersion = async (packageName, type, packageGraphs, preId, exact
738
1032
  });
739
1033
  const baseWrite = Bun.write(packageNode.packageData.path, updatedContent);
740
1034
  const dependentWrites = Array.from(dfsTraverseGraph(packageGraphs.dependents, packageName).flatMap((dependent) => {
741
- const fields = ["dependencies", "peerDependencies"];
742
- return fields.flatMap((field) => {
1035
+ return Object.values(DependenciesField).flatMap((field) => {
743
1036
  const entry = dependent[field];
744
1037
  const depVersion = entry?.[packageName];
745
1038
  if (!depVersion) {
746
1039
  return [];
747
1040
  }
748
1041
  if (exact ? depVersion === bumpedVersion : semver.satisfies(bumpedVersion, depVersion)) {
749
- logger.debug(dim7(`Skipping '${dependent.name}': ${field} version '${depVersion}' already satisfies '${bumpedVersion}'.`));
1042
+ logger.debug(styleText8("dim", `Skipping '${dependent.name}': ${field} version '${depVersion}' already satisfies '${bumpedVersion}'.`));
750
1043
  return [];
751
1044
  }
752
1045
  const updatedContent2 = findAndReplaceVersion({
@@ -770,22 +1063,57 @@ var updatePackageVersion = async (packageName, type, packageGraphs, preId, exact
770
1063
  import {
771
1064
  watch
772
1065
  } from "fs";
1066
+ import { styleText as styleText10 } from "util";
773
1067
  import {
774
- dirname as dirname6,
1068
+ dirname as dirname8,
775
1069
  join as join4
776
1070
  } from "path";
777
1071
  import {
778
- assertDefined as assertDefined9,
1072
+ assertDefined as assertDefined12,
779
1073
  DedupePathsBy,
780
1074
  dedupeSharedPaths,
781
1075
  getDeferredPromise,
782
1076
  getStringMatcher,
783
- isDefined as isDefined4
1077
+ isDefined as isDefined4,
1078
+ runAsync as runAsync2
784
1079
  } from "@package-pal/util";
785
- import {
786
- dim as dim9,
787
- red as red3
788
- } from "yoctocolors";
1080
+
1081
+ // packages/core/src/lib/graph/functions/merge-graphs.ts
1082
+ var mergeGraphs = (a, b) => {
1083
+ const merged = new Map;
1084
+ for (const [name, node] of a) {
1085
+ merged.set(name, {
1086
+ packageData: node.packageData,
1087
+ pointsToPackages: new Set(node.pointsToPackages)
1088
+ });
1089
+ }
1090
+ for (const [name, node] of b) {
1091
+ merged.set(name, {
1092
+ packageData: node.packageData,
1093
+ pointsToPackages: new Set(node.pointsToPackages)
1094
+ });
1095
+ }
1096
+ return merged;
1097
+ };
1098
+
1099
+ // packages/core/src/lib/watch/types/change-action.ts
1100
+ var ChangeAction = {
1101
+ Ignore: "Ignore",
1102
+ Partial: "Partial",
1103
+ Restart: "Restart"
1104
+ };
1105
+
1106
+ // packages/core/src/lib/watch/functions/filter-files-modified-since.ts
1107
+ var filterFilesModifiedSince = (paths, sinceMs) => {
1108
+ return paths.filter((path) => {
1109
+ const changedFile = Bun.file(path);
1110
+ return changedFile.lastModified >= sinceMs;
1111
+ });
1112
+ };
1113
+
1114
+ // packages/core/src/lib/watch/functions/get-change-logic.ts
1115
+ import { styleText as styleText9 } from "util";
1116
+ import { assertDefined as assertDefined11 } from "@package-pal/util";
789
1117
 
790
1118
  // packages/core/src/lib/graph/functions/generate-topological-ranking-range.ts
791
1119
  import { isDefined as isDefined3 } from "@package-pal/util";
@@ -811,11 +1139,11 @@ var generateTopologicalRankingRange = (graph, ranking) => {
811
1139
  };
812
1140
 
813
1141
  // packages/core/src/lib/graph/functions/generate-topological-ranking.ts
814
- import { assertDefined as assertDefined8 } from "@package-pal/util";
1142
+ import { assertDefined as assertDefined10 } from "@package-pal/util";
815
1143
  var generateTopologicalRanking = (packageProcessOrder) => {
816
1144
  const rankMap = new Map;
817
1145
  for (let i = 0;i < packageProcessOrder.length; i++) {
818
- for (const packageName of assertDefined8(packageProcessOrder[i])) {
1146
+ for (const packageName of assertDefined10(packageProcessOrder[i])) {
819
1147
  rankMap.set(packageName, i);
820
1148
  }
821
1149
  }
@@ -880,225 +1208,13 @@ var isSubgraph = (a, b) => {
880
1208
  return true;
881
1209
  };
882
1210
 
883
- // packages/core/src/lib/watch/types/change-action.ts
884
- var ChangeAction = {
885
- Ignore: "Ignore",
886
- Partial: "Partial",
887
- Restart: "Restart"
888
- };
889
-
890
- // packages/core/src/lib/watch/types/exit-state.ts
891
- var ExitState = {
892
- Completed: "Completed",
893
- Errored: "Errored",
894
- Cancelled: "Cancelled"
895
- };
896
-
897
- // packages/core/src/lib/watch/types/run-async-type.ts
898
- var RunAsyncType = {
899
- Sequential: "Sequential",
900
- Parallel: "Parallel"
901
- };
902
-
903
- // packages/core/src/lib/watch/functions/filter-files-modified-since.ts
904
- var filterFilesModifiedSince = (paths, sinceMs) => {
905
- return paths.filter((path) => {
906
- const changedFile = Bun.file(path);
907
- return changedFile.lastModified >= sinceMs;
908
- });
909
- };
910
-
911
- // packages/core/src/lib/watch/functions/normalise-watched-file-path.ts
912
- import {
913
- basename as basename3,
914
- dirname as dirname5,
915
- join as join3
916
- } from "path";
917
- var removeTrailing = [
918
- "~",
919
- ".tmp",
920
- ".temp",
921
- ".bak",
922
- ".backup",
923
- ".swp",
924
- ".swo",
925
- ".swn"
926
- ];
927
- var normaliseWatchedFilePath = (filePath) => {
928
- const dir = dirname5(filePath);
929
- let base = basename3(filePath);
930
- for (const trailing of removeTrailing) {
931
- if (base.toLowerCase().endsWith(trailing)) {
932
- const sliceStart = base.startsWith(".") ? 1 : 0;
933
- base = base.slice(sliceStart, -trailing.length);
934
- break;
935
- }
936
- }
937
- return join3(dir, base);
938
- };
939
-
940
- // packages/core/src/lib/watch/functions/run-async.ts
941
- var runAsync = async (type, tasks) => {
942
- if (type === RunAsyncType.Parallel) {
943
- return Promise.all(tasks.map((task) => task()));
944
- }
945
- const outputs = [];
946
- for (const task of tasks) {
947
- const result = await task();
948
- outputs.push(result);
949
- }
950
- return outputs;
951
- };
952
-
953
- // packages/core/src/lib/watch/functions/run-subprocess.ts
954
- import {
955
- dim as dim8,
956
- red as red2
957
- } from "yoctocolors";
958
-
959
- // packages/core/src/lib/watch/types/std-type.ts
960
- var StdType = {
961
- Out: "Out",
962
- Err: "Err"
963
- };
964
-
965
- // packages/core/src/lib/watch/functions/get-commands-for-shell.ts
966
- var getCommandsForShell = (shellCommand) => {
967
- const isWindows = process.platform === "win32";
968
- if (!isWindows) {
969
- return [
970
- "sh",
971
- "-c",
972
- `"${shellCommand}"`
973
- ];
974
- }
975
- const shell = Bun.which("pwsh") ? "pwsh" : Bun.which("powershell") ? "powershell" : "cmd";
976
- if (shell === "cmd") {
977
- return [
978
- shell,
979
- "/c",
980
- `"${shellCommand}"`
981
- ];
982
- }
983
- const encodedCommand = Buffer.from(shellCommand, "utf16le").toString("base64");
984
- return [
985
- shell,
986
- "-EncodedCommand",
987
- encodedCommand
988
- ];
989
- };
990
-
991
- // packages/core/src/lib/watch/functions/get-line-buffered-writer.ts
992
- import { identity } from "@package-pal/util";
993
- var getLineBufferedWriter = (prefix, style = identity, write = process.stdout.write.bind(process.stdout)) => {
994
- let buffer = "";
995
- return (chunk) => {
996
- buffer += chunk;
997
- const lines = buffer.split(`
998
- `);
999
- buffer = lines.pop() ?? "";
1000
- for (const line of lines) {
1001
- write(`${prefix}${style(line)}
1002
- `);
1003
- }
1004
- };
1005
- };
1006
-
1007
- // packages/core/src/lib/watch/functions/read-stream.ts
1008
- var readStream = async (stream, use) => {
1009
- if (!stream) {
1010
- return;
1011
- }
1012
- const decoder = new TextDecoder;
1013
- const reader = stream.getReader();
1014
- let result = await reader.read();
1015
- while (!result.done) {
1016
- use(decoder.decode(result.value, { stream: true }));
1017
- result = await reader.read();
1018
- }
1019
- const flush = decoder.decode();
1020
- if (flush) {
1021
- use(flush);
1022
- }
1023
- };
1024
-
1025
- // packages/core/src/lib/watch/functions/run-subprocess.ts
1026
- var sigintCode = 130;
1027
- var sigtermCode = 143;
1028
- var sigkillCode = 137;
1029
- var cancelCodes = new Set([
1030
- sigintCode,
1031
- sigtermCode,
1032
- sigkillCode
1033
- ]);
1034
- var runSubprocess = async (opts) => {
1035
- if (opts.signal?.aborted) {
1036
- opts.logger.debug(dim8(`Skipped '${opts.debugName}' subprocess command; signal already cancelled.`));
1037
- return ExitState.Cancelled;
1038
- }
1039
- const commands = getCommandsForShell(opts.shellCommand);
1040
- const subprocess = Bun.spawn(commands, {
1041
- cwd: opts.cwd,
1042
- stdout: "pipe",
1043
- stderr: "pipe",
1044
- stdin: "ignore",
1045
- signal: opts.signal
1046
- });
1047
- const pid = subprocess.pid.toString();
1048
- const [readStdout, readStderr] = [{
1049
- source: subprocess.stdout,
1050
- type: StdType.Out,
1051
- write: getLineBufferedWriter(dim8(`[OUT-${pid}] `))
1052
- }, {
1053
- source: subprocess.stderr,
1054
- type: StdType.Err,
1055
- write: getLineBufferedWriter(red2(dim8(`[ERR-${pid}] `)))
1056
- }].map(({
1057
- source,
1058
- type,
1059
- write
1060
- }) => {
1061
- return readStream(source, (chunk) => {
1062
- write(chunk);
1063
- if (opts.onStdChunk) {
1064
- opts.onStdChunk(chunk, type);
1065
- }
1066
- });
1067
- });
1068
- const executedCommand = commands.join(" ");
1069
- opts.logger.debug(dim8(`Started '${opts.debugName}' subprocess command '${opts.shellCommand}' (${executedCommand}) with PID ${pid}.`));
1070
- const [
1071
- ,
1072
- ,
1073
- exitState
1074
- ] = await Promise.all([
1075
- readStdout,
1076
- readStderr,
1077
- subprocess.exited.then((exitCode) => {
1078
- if (cancelCodes.has(exitCode)) {
1079
- opts.logger.debug(dim8(`Cancelled '${opts.debugName}' subprocess command; PID ${pid} exited.`));
1080
- return ExitState.Cancelled;
1081
- }
1082
- if (exitCode !== 0) {
1083
- opts.logger.error(red2(`'${opts.debugName}' command '${opts.shellCommand}' (${executedCommand}) with PID ${pid} failed with exit code ${exitCode.toString()}.`));
1084
- return ExitState.Errored;
1085
- }
1086
- opts.logger.debug(dim8(`Completed '${opts.debugName}' subprocess command; PID ${pid} exited.`));
1087
- return ExitState.Completed;
1088
- })
1089
- ]);
1090
- return exitState;
1091
- };
1092
-
1093
- // packages/core/src/lib/watch/functions/watch-package-changes.ts
1094
- var fileModifiedThresholdMs = 5000;
1095
- var lastProcessedSubgraph;
1096
- var getChangeLogic = (packageGraphs, packageChanges, config, logger) => {
1211
+ // packages/core/src/lib/watch/functions/get-change-logic.ts
1212
+ var getChangeLogic = (packageGraphs, packageChanges, lastProcessedSubgraph, config, logger) => {
1097
1213
  const changedPackages = Array.from(packageChanges.keys());
1098
1214
  const changedFilePaths = Array.from(packageChanges.values()).flat();
1099
1215
  if (packageChanges.size) {
1100
- logger.debug(dim9(`Changes detected in ${changedPackages.map((packageName) => `'${packageName}'`).join(", ")}.`));
1101
- logger.debug(dim9(`Changed file paths: ${changedFilePaths.map((filePath) => `'${filePath}'`).join(", ")}.`));
1216
+ logger.debug(styleText9("dim", `Changes detected in ${changedPackages.map((packageName) => `'${packageName}'`).join(", ")}.`));
1217
+ logger.debug(styleText9("dim", `Changed file paths: ${changedFilePaths.map((filePath) => `'${filePath}'`).join(", ")}.`));
1102
1218
  }
1103
1219
  const packageOrder = generateTopologicalSortedGroups(packageGraphs.dependents, logger);
1104
1220
  const packageProcessOrder = packageOrder.groups.toReversed().concat(packageOrder.circular);
@@ -1109,9 +1225,9 @@ var getChangeLogic = (packageGraphs, packageChanges, config, logger) => {
1109
1225
  const isSubgraphOfPrevious = !!lastProcessedSubgraph && isSubgraph(lastProcessedSubgraph, changedPackageSubgraph);
1110
1226
  const isDisjointFromPrevious = !lastProcessedSubgraph || !isSubgraphOfPrevious && isDisjoint(lastProcessedSubgraph, changedPackageSubgraph);
1111
1227
  const isRankedGreaterThanOrEqualToPrevious = !!lastProcessedSubgraph && !isSubgraphOfPrevious && isRankedGreaterThanOrEqual(lastProcessedSubgraph, changedPackageSubgraph, packageRankings);
1112
- logger.debug(dim9(`Changes are subgraph of previous: ${isSubgraphOfPrevious.toString()}.`));
1113
- logger.debug(dim9(`Changes are disjoint from previous: ${isDisjointFromPrevious.toString()}.`));
1114
- logger.debug(dim9(`Changes are ranked greater than or equal to previous: ${isRankedGreaterThanOrEqualToPrevious.toString()}.`));
1228
+ logger.debug(styleText9("dim", `Changes are subgraph of previous: ${isSubgraphOfPrevious.toString()}.`));
1229
+ logger.debug(styleText9("dim", `Changes are disjoint from previous: ${isDisjointFromPrevious.toString()}.`));
1230
+ logger.debug(styleText9("dim", `Changes are ranked greater than or equal to previous: ${isRankedGreaterThanOrEqualToPrevious.toString()}.`));
1115
1231
  let action = ChangeAction.Restart;
1116
1232
  if (!packageChanges.size) {
1117
1233
  action = ChangeAction.Ignore;
@@ -1123,30 +1239,64 @@ var getChangeLogic = (packageGraphs, packageChanges, config, logger) => {
1123
1239
  action = ChangeAction.Partial;
1124
1240
  }
1125
1241
  if (action === ChangeAction.Partial && isRankedGreaterThanOrEqualToPrevious) {
1126
- const [prevMinRank] = generateTopologicalRankingRange(assertDefined9(lastProcessedSubgraph), packageRankings);
1242
+ const [prevMinRank] = generateTopologicalRankingRange(assertDefined11(lastProcessedSubgraph), packageRankings);
1127
1243
  for (let i = 0;i < changedPackageProcessOrder.length; i++) {
1128
- changedPackageProcessOrder[i] = assertDefined9(changedPackageProcessOrder[i]).filter((packageName) => {
1244
+ changedPackageProcessOrder[i] = assertDefined11(changedPackageProcessOrder[i]).filter((packageName) => {
1129
1245
  const rank = packageRankings.get(packageName);
1130
1246
  return rank !== undefined && rank >= prevMinRank;
1131
1247
  });
1132
1248
  }
1133
1249
  }
1134
- logger.debug(dim9(`Determined change action: ${action}.`));
1250
+ logger.debug(styleText9("dim", `Determined change action: ${action}.`));
1135
1251
  return {
1136
1252
  changedPackageProcessOrder,
1137
1253
  changedPackageSubgraph,
1138
1254
  action
1139
1255
  };
1140
1256
  };
1257
+
1258
+ // packages/core/src/lib/watch/functions/normalise-watched-file-path.ts
1259
+ import {
1260
+ basename as basename3,
1261
+ dirname as dirname7,
1262
+ join as join3
1263
+ } from "path";
1264
+ var removeTrailing = [
1265
+ "~",
1266
+ ".tmp",
1267
+ ".temp",
1268
+ ".bak",
1269
+ ".backup",
1270
+ ".swp",
1271
+ ".swo",
1272
+ ".swn"
1273
+ ];
1274
+ var normaliseWatchedFilePath = (filePath) => {
1275
+ const dir = dirname7(filePath);
1276
+ let base = basename3(filePath);
1277
+ for (const trailing of removeTrailing) {
1278
+ if (base.toLowerCase().endsWith(trailing)) {
1279
+ const sliceStart = base.startsWith(".") ? 1 : 0;
1280
+ base = base.slice(sliceStart, -trailing.length);
1281
+ break;
1282
+ }
1283
+ }
1284
+ return join3(dir, base);
1285
+ };
1286
+
1287
+ // packages/core/src/lib/watch/functions/watch-package-changes.ts
1288
+ var fileModifiedThresholdMs = 5000;
1289
+ var lastProcessedSubgraph;
1141
1290
  var onProcessPackage = async (packageGraphs, packageChanges, watchConfig, determineAbortController, logger) => {
1142
1291
  const {
1143
1292
  action,
1144
1293
  changedPackageProcessOrder,
1145
1294
  changedPackageSubgraph
1146
- } = getChangeLogic(packageGraphs, packageChanges, watchConfig, logger);
1295
+ } = getChangeLogic(packageGraphs, packageChanges, lastProcessedSubgraph, watchConfig, logger);
1147
1296
  const controller = determineAbortController(action === ChangeAction.Restart);
1297
+ const isSequential = watchConfig.subprocess.concurrency === 1;
1148
1298
  const onProcessFailure = () => {
1149
- logger.debug(dim9("Aborting controller: process failed."));
1299
+ logger.debug(styleText10("dim", "Aborting controller: process failed."));
1150
1300
  controller.abort();
1151
1301
  lastProcessedSubgraph = undefined;
1152
1302
  };
@@ -1155,8 +1305,8 @@ var onProcessPackage = async (packageGraphs, packageChanges, watchConfig, determ
1155
1305
  return;
1156
1306
  }
1157
1307
  if (packageChanges.size) {
1158
- logger.info(`Changes detected. ${action === ChangeAction.Restart ? "Restarting processing" : "Initiating partial processing"} ${watchConfig.subprocess.parallelProcessing ? "in parallel" : "sequentially"}.`);
1159
- lastProcessedSubgraph = changedPackageSubgraph;
1308
+ logger.info(`${action === ChangeAction.Restart ? "Restarting processing" : "Initiating partial processing"} ${isSequential ? "sequentially" : `in parallel${isDefined4(watchConfig.subprocess.concurrency) ? ` with concurrency ${watchConfig.subprocess.concurrency.toString()}` : ""}`}.`);
1309
+ lastProcessedSubgraph = lastProcessedSubgraph ? mergeGraphs(lastProcessedSubgraph, changedPackageSubgraph) : changedPackageSubgraph;
1160
1310
  }
1161
1311
  for (const group of changedPackageProcessOrder) {
1162
1312
  const {
@@ -1164,12 +1314,12 @@ var onProcessPackage = async (packageGraphs, packageChanges, watchConfig, determ
1164
1314
  resolve: matchedParallelLongReadyRunningOutput
1165
1315
  } = getDeferredPromise();
1166
1316
  let matchedLongRunningOutputCount = 0;
1167
- await runAsync(watchConfig.subprocess.parallelProcessing ? RunAsyncType.Parallel : RunAsyncType.Sequential, group.map((packageName) => async () => {
1317
+ await runAsync2(group.map((packageName) => async () => {
1168
1318
  const {
1169
1319
  promise: longRunningSequentialProcessReady,
1170
1320
  resolve: matchedSequentialLongRunningReadyOutput
1171
1321
  } = getDeferredPromise();
1172
- const packageNode = assertDefined9(packageGraphs.dependencies.get(packageName));
1322
+ const packageNode = assertDefined12(packageGraphs.dependencies.get(packageName));
1173
1323
  const changedPaths = packageChanges.get(packageName) ?? [];
1174
1324
  const processPackageProps = {
1175
1325
  name: packageName,
@@ -1179,7 +1329,7 @@ var onProcessPackage = async (packageGraphs, packageChanges, watchConfig, determ
1179
1329
  totalProcessOrder: changedPackageProcessOrder,
1180
1330
  signal: controller.signal
1181
1331
  };
1182
- const processPackageCwd = dirname6(packageNode.packageData.path);
1332
+ const processPackageCwd = dirname8(packageNode.packageData.path);
1183
1333
  const beforeProcessPackageShellCommand = await watchConfig.hooks.onBeforeProcessPackage(processPackageProps);
1184
1334
  if (beforeProcessPackageShellCommand) {
1185
1335
  await runSubprocess({
@@ -1205,36 +1355,42 @@ var onProcessPackage = async (packageGraphs, packageChanges, watchConfig, determ
1205
1355
  signal: controller.signal,
1206
1356
  logger,
1207
1357
  onStdChunk: (chunk) => {
1208
- if (!ready && readyMatcher?.push(chunk).matched()) {
1209
- ready = true;
1210
- matchedLongRunningOutputCount++;
1211
- logger.debug(`'${packageName}' (${matchedLongRunningOutputCount.toString()}/${group.length.toString()}) subprocess matched ready text '${assertDefined9(longRunningOutputReadyText)}'.`);
1212
- if (!watchConfig.subprocess.parallelProcessing && matchedLongRunningOutputCount) {
1213
- matchedSequentialLongRunningReadyOutput();
1358
+ if (!ready) {
1359
+ const matchedReadyText = readyMatcher?.push(chunk).matched();
1360
+ if (matchedReadyText) {
1361
+ ready = true;
1362
+ matchedLongRunningOutputCount++;
1363
+ logger.debug(`'${packageName}' (${matchedLongRunningOutputCount.toString()}/${group.length.toString()}) subprocess matched ready text '${matchedReadyText}'.`);
1364
+ if (isSequential && matchedLongRunningOutputCount) {
1365
+ matchedSequentialLongRunningReadyOutput();
1366
+ }
1214
1367
  }
1215
1368
  }
1216
- if (!errored && erroredMatcher?.push(chunk).matched()) {
1217
- logger.error(red3(`'${packageName}' subprocess matched error text '${assertDefined9(longRunningOutputErroredText)}'.`));
1218
- errored = true;
1219
- Promise.resolve(watchConfig.hooks.onProcessPackageError(processPackageProps)).then((processPackageErrorCommand) => {
1220
- if (!processPackageErrorCommand) {
1221
- onProcessFailure();
1222
- return;
1223
- }
1224
- return runSubprocess({
1225
- debugName: `after process ${packageName}`,
1226
- shellCommand: processPackageErrorCommand,
1227
- cwd: processPackageCwd,
1228
- signal: controller.signal,
1229
- logger
1369
+ if (!errored) {
1370
+ const matchedErrorText = erroredMatcher?.push(chunk).matched();
1371
+ if (matchedErrorText) {
1372
+ logger.error(styleText10("red", `'${packageName}' subprocess matched error text '${matchedErrorText}'.`));
1373
+ errored = true;
1374
+ Promise.resolve(watchConfig.hooks.onProcessPackageError(processPackageProps)).then((processPackageErrorCommand) => {
1375
+ if (!processPackageErrorCommand) {
1376
+ onProcessFailure();
1377
+ return;
1378
+ }
1379
+ return runSubprocess({
1380
+ debugName: `after process ${packageName}`,
1381
+ shellCommand: processPackageErrorCommand,
1382
+ cwd: processPackageCwd,
1383
+ signal: controller.signal,
1384
+ logger
1385
+ });
1386
+ }).then((exitState) => {
1387
+ if (exitState === ExitState.Errored) {
1388
+ onProcessFailure();
1389
+ }
1230
1390
  });
1231
- }).then((exitState) => {
1232
- if (exitState === ExitState.Errored) {
1233
- onProcessFailure();
1234
- }
1235
- });
1391
+ }
1236
1392
  }
1237
- if (watchConfig.subprocess.parallelProcessing && matchedLongRunningOutputCount === group.length) {
1393
+ if (!isSequential && matchedLongRunningOutputCount === group.length) {
1238
1394
  matchedParallelLongReadyRunningOutput();
1239
1395
  }
1240
1396
  }
@@ -1259,7 +1415,7 @@ var onProcessPackage = async (packageGraphs, packageChanges, watchConfig, determ
1259
1415
  logger
1260
1416
  });
1261
1417
  }
1262
- }));
1418
+ }), watchConfig.subprocess.concurrency);
1263
1419
  }
1264
1420
  if (packageChanges.size) {
1265
1421
  logger.info(`Processing ${controller.signal.aborted ? "cancelled due to new changes" : "completed"}.`);
@@ -1296,26 +1452,31 @@ var onProcessPackage = async (packageGraphs, packageChanges, watchConfig, determ
1296
1452
  });
1297
1453
  }
1298
1454
  };
1299
- var watchPackageChanges = (packageData, packageGraphs, watchConfig, logger) => {
1300
- const dedupedRootPackageData = dedupeSharedPaths(packageData.map((packageData2) => packageData2.path), DedupePathsBy.Parent).map((packagePath) => assertDefined9(packageData.find((data) => data.path === packagePath)));
1301
- logger.debug(dim9(`Starting ${dedupedRootPackageData.length.toString()} watchers for ${packageData.length.toString()} packages.`));
1455
+ var watchPackageChanges = (packageData, packageGraphs, watchConfig, rootDir, logger) => {
1456
+ const dedupedRootPackageData = dedupeSharedPaths(packageData.map((packageData2) => packageData2.path), DedupePathsBy.Parent).map((packagePath) => assertDefined12(packageData.find((data) => data.path === packagePath)));
1457
+ logger.debug(styleText10("dim", `Starting ${dedupedRootPackageData.length.toString()} watchers for ${packageData.length.toString()} packages.`));
1302
1458
  let closed = false;
1303
1459
  let debounceTimeout;
1304
1460
  let startedDebounceMs;
1305
- let abortController;
1461
+ let controller;
1306
1462
  const changedPackagePaths = new Map;
1307
1463
  const useController = (reset) => {
1308
- if (abortController && (reset || abortController.signal.aborted)) {
1464
+ if (controller && (reset || controller.signal.aborted)) {
1309
1465
  if (reset) {
1310
- logger.debug(dim9("Aborting controller: reset for new packages."));
1311
- abortController.abort();
1466
+ logger.debug(styleText10("dim", "Aborting controller: reset for new packages."));
1467
+ controller.abort();
1312
1468
  }
1313
- abortController = undefined;
1469
+ controller = undefined;
1314
1470
  }
1315
- abortController ??= new AbortController;
1316
- return abortController;
1471
+ controller ??= new AbortController;
1472
+ return controller;
1317
1473
  };
1318
- const onWatchEvent = (watchPath, packageName, _event, filePath, forceEmpty = false) => {
1474
+ const onWatchEvent = ({
1475
+ watchPath,
1476
+ packageName,
1477
+ filePath,
1478
+ isInitial = false
1479
+ }) => {
1319
1480
  if (!isDefined4(startedDebounceMs)) {
1320
1481
  startedDebounceMs = Date.now();
1321
1482
  }
@@ -1331,54 +1492,72 @@ var watchPackageChanges = (packageData, packageGraphs, watchConfig, logger) => {
1331
1492
  changedPackagePaths.set(packageName, new Set([changedPath]));
1332
1493
  }
1333
1494
  }
1495
+ const debounceMs = isInitial ? 0 : watchConfig.debounceMs;
1334
1496
  debounceTimeout = setTimeout(() => {
1335
1497
  if (closed) {
1336
1498
  return;
1337
1499
  }
1338
1500
  const packageChanges = new Map;
1339
1501
  for (const [packageName2, paths] of changedPackagePaths) {
1340
- const processedPaths = filterFilesModifiedSince(dedupeSharedPaths(Array.from(paths), DedupePathsBy.Child).sort(), assertDefined9(startedDebounceMs) - fileModifiedThresholdMs);
1502
+ const dedupedPaths = dedupeSharedPaths(Array.from(paths), DedupePathsBy.Child).sort();
1503
+ const processedPaths = filterFilesModifiedSince(dedupedPaths, assertDefined12(startedDebounceMs) - fileModifiedThresholdMs);
1341
1504
  if (processedPaths.length) {
1342
1505
  packageChanges.set(packageName2, processedPaths);
1343
1506
  }
1344
1507
  }
1345
1508
  startedDebounceMs = undefined;
1346
1509
  changedPackagePaths.clear();
1347
- if (!packageChanges.size && !forceEmpty) {
1510
+ if (!packageChanges.size && !isInitial) {
1348
1511
  return;
1349
1512
  }
1350
1513
  onProcessPackage(packageGraphs, packageChanges, watchConfig, (reset) => useController(reset), logger);
1351
- }, watchConfig.debounceMs);
1514
+ }, debounceMs);
1352
1515
  };
1353
1516
  const watchers = dedupedRootPackageData.map(({
1354
1517
  name,
1355
1518
  path
1356
1519
  }) => {
1357
- const watchPath = dirname6(path);
1520
+ const watchPath = dirname8(path);
1358
1521
  return watch(watchPath, { recursive: true }, (event, filePath) => {
1359
- onWatchEvent(watchPath, name, event, filePath);
1522
+ onWatchEvent({
1523
+ watchPath,
1524
+ packageName: name,
1525
+ event,
1526
+ filePath: filePath ?? undefined
1527
+ });
1360
1528
  });
1361
1529
  });
1362
1530
  const closeWatchers = () => {
1363
1531
  watchers.forEach((watcher) => {
1364
1532
  watcher.close();
1365
1533
  });
1366
- logger.debug(dim9("Aborting controller: closing watchers."));
1367
- abortController?.abort();
1534
+ logger.debug(styleText10("dim", "Aborting controller: closing watchers."));
1535
+ controller?.abort();
1368
1536
  closed = true;
1369
1537
  };
1370
1538
  process.on("SIGINT", () => {
1371
- logger.debug(dim9("Received SIGINT: closing watchers."));
1539
+ logger.debug(styleText10("dim", "Received SIGINT: closing watchers."));
1372
1540
  closeWatchers();
1373
1541
  process.exit(0);
1374
1542
  });
1375
- onWatchEvent(undefined, undefined, undefined, null, true);
1543
+ Promise.resolve(watchConfig.hooks.onInit()).then(async (onInitShellCommand) => {
1544
+ if (onInitShellCommand) {
1545
+ await runSubprocess({
1546
+ debugName: `on init`,
1547
+ shellCommand: onInitShellCommand,
1548
+ signal: useController(false).signal,
1549
+ cwd: rootDir,
1550
+ logger
1551
+ });
1552
+ }
1553
+ onWatchEvent({ isInitial: true });
1554
+ });
1376
1555
  return { close: () => {
1377
1556
  if (closed) {
1378
- logger.debug(dim9("Watchers already closed."));
1557
+ logger.debug(styleText10("dim", "Watchers already closed."));
1379
1558
  return;
1380
1559
  }
1381
- logger.debug(dim9("Closing watchers."));
1560
+ logger.debug(styleText10("dim", "Closing watchers."));
1382
1561
  closeWatchers();
1383
1562
  } };
1384
1563
  };
@@ -1391,7 +1570,7 @@ var readPackagePalConfig = (options) => {
1391
1570
  var readPackageData = async (options) => {
1392
1571
  checkBun();
1393
1572
  const packagePatterns = Array.isArray(options.config.packages) ? options.config.packages : [options.config.packages];
1394
- return loadPackages(packagePatterns, options.config.logger);
1573
+ return loadPackages(options.rootDir, packagePatterns, options.config.logger);
1395
1574
  };
1396
1575
  var getPackageGraphs = (options) => {
1397
1576
  checkBun();
@@ -1413,7 +1592,11 @@ var bumpPackageVersion = (options) => {
1413
1592
  };
1414
1593
  var watchPackages = (options) => {
1415
1594
  checkBun();
1416
- watchPackageChanges(options.packageData, options.packageGraphs, options.config.watch, options.config.logger);
1595
+ watchPackageChanges(options.packageData, options.packageGraphs, options.config.watch, options.rootDir, options.config.logger);
1596
+ };
1597
+ var forEachPackage = (options) => {
1598
+ checkBun();
1599
+ return runForEachPackage(options.packageGraphs, options.packageOrder, options.getCommand, options.config.logger, options.topological, options.concurrency);
1417
1600
  };
1418
1601
  export {
1419
1602
  watchPackages,
@@ -1422,9 +1605,10 @@ export {
1422
1605
  getPackageOrder,
1423
1606
  getPackageGraphs,
1424
1607
  getPackageCircularDependencyPaths,
1608
+ forEachPackage,
1425
1609
  bumpPackageVersion,
1426
1610
  BumpVersionType
1427
1611
  };
1428
1612
 
1429
- //# debugId=038CF7D68B032DA664756E2164756E21
1613
+ //# debugId=57C320DF799C435664756E2164756E21
1430
1614
  //# sourceMappingURL=index.js.map