ts-repo-utils 6.0.4 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/cmd/assert-repo-is-clean.mjs +21 -21
  2. package/dist/cmd/check-should-run-type-checks.mjs +28 -30
  3. package/dist/cmd/format-diff-from.mjs +33 -34
  4. package/dist/cmd/format-untracked.mjs +23 -23
  5. package/dist/cmd/gen-index-ts.mjs +86 -102
  6. package/dist/functions/workspace-utils/execute-parallel.d.mts +10 -7
  7. package/dist/functions/workspace-utils/execute-parallel.d.mts.map +1 -1
  8. package/dist/functions/workspace-utils/execute-parallel.mjs +60 -14
  9. package/dist/functions/workspace-utils/execute-parallel.mjs.map +1 -1
  10. package/dist/functions/workspace-utils/run-cmd-in-parallel.d.mts +3 -1
  11. package/dist/functions/workspace-utils/run-cmd-in-parallel.d.mts.map +1 -1
  12. package/dist/functions/workspace-utils/run-cmd-in-parallel.mjs +8 -3
  13. package/dist/functions/workspace-utils/run-cmd-in-parallel.mjs.map +1 -1
  14. package/dist/functions/workspace-utils/run-cmd-in-stages.d.mts +3 -1
  15. package/dist/functions/workspace-utils/run-cmd-in-stages.d.mts.map +1 -1
  16. package/dist/functions/workspace-utils/run-cmd-in-stages.mjs +8 -3
  17. package/dist/functions/workspace-utils/run-cmd-in-stages.mjs.map +1 -1
  18. package/dist/index.d.mts +1 -0
  19. package/dist/index.d.mts.map +1 -1
  20. package/dist/index.mjs +1 -0
  21. package/dist/index.mjs.map +1 -1
  22. package/package.json +1 -1
  23. package/src/cmd/assert-repo-is-clean.mts +1 -1
  24. package/src/cmd/check-should-run-type-checks.mts +1 -1
  25. package/src/cmd/format-diff-from.mts +1 -1
  26. package/src/cmd/format-untracked.mts +1 -1
  27. package/src/cmd/gen-index-ts.mts +1 -1
  28. package/src/functions/diff.test.mts +5 -1
  29. package/src/functions/workspace-utils/execute-parallel.mts +74 -22
  30. package/src/functions/workspace-utils/run-cmd-in-parallel.mts +11 -6
  31. package/src/functions/workspace-utils/run-cmd-in-stages.mts +11 -6
  32. package/src/index.mts +2 -0
@@ -1,32 +1,32 @@
1
1
  #!/usr/bin/env -S npx tsx
2
- import 'child_process';
3
2
  import * as cmd from 'cmd-ts';
4
- import 'micromatch';
5
- import 'node:child_process';
6
- import 'prettier';
7
3
  import 'ts-data-forge';
8
- import { assertRepoIsClean } from '../functions/assert-repo-is-clean.mjs';
9
4
  import '../node-global.mjs';
5
+ import { assertRepoIsClean } from '../functions/assert-repo-is-clean.mjs';
6
+ import 'node:child_process';
7
+ import 'prettier';
8
+ import 'micromatch';
9
+ import 'child_process';
10
10
 
11
11
  const cmdDef = cmd.command({
12
- name: 'assert-repo-is-clean-cli',
13
- version: '6.0.4',
14
- args: {
15
- silent: cmd.flag({
16
- long: 'silent',
17
- type: cmd.optional(cmd.boolean),
18
- description: 'If true, suppresses output messages (default: false)',
19
- }),
20
- },
21
- handler: (args) => {
22
- main(args).catch((error) => {
23
- console.error('An error occurred:', error);
24
- process.exit(1);
25
- });
26
- },
12
+ name: 'assert-repo-is-clean-cli',
13
+ version: '6.1.0',
14
+ args: {
15
+ silent: cmd.flag({
16
+ long: 'silent',
17
+ type: cmd.optional(cmd.boolean),
18
+ description: 'If true, suppresses output messages (default: false)',
19
+ }),
20
+ },
21
+ handler: (args) => {
22
+ main(args).catch((error) => {
23
+ console.error('An error occurred:', error);
24
+ process.exit(1);
25
+ });
26
+ },
27
27
  });
28
28
  const main = async (args) => {
29
- await assertRepoIsClean({ silent: args.silent });
29
+ await assertRepoIsClean({ silent: args.silent });
30
30
  };
31
31
  await cmd.run(cmdDef, process.argv.slice(2));
32
32
  //# sourceMappingURL=assert-repo-is-clean.mjs.map
@@ -1,42 +1,40 @@
1
1
  #!/usr/bin/env -S npx tsx
2
- import 'child_process';
3
2
  import * as cmd from 'cmd-ts';
4
- import 'micromatch';
3
+ import 'ts-data-forge';
4
+ import '../node-global.mjs';
5
5
  import 'node:child_process';
6
6
  import 'prettier';
7
- import 'ts-data-forge';
7
+ import 'micromatch';
8
8
  import { checkShouldRunTypeChecks } from '../functions/should-run.mjs';
9
- import '../node-global.mjs';
9
+ import 'child_process';
10
10
 
11
11
  const cmdDef = cmd.command({
12
- name: 'check-should-run-type-checks-cli',
13
- version: '6.0.4',
14
- args: {
15
- pathsIgnore: cmd.multioption({
16
- long: 'paths-ignore',
17
- type: cmd.optional(cmd.array(cmd.string)),
18
- description:
19
- 'Patterns to ignore when checking if type checks should run. Supports exact file matches, directory prefixes (ending with "/"), and file extensions (starting with "**.")',
20
- }),
21
- baseBranch: cmd.option({
22
- long: 'base-branch',
23
- type: cmd.optional(cmd.string),
24
- description:
25
- 'Base branch to compare against for determining changed files. Defaults to "origin/main"',
26
- }),
27
- },
28
- handler: (args) => {
29
- main(args).catch((error) => {
30
- console.error('An error occurred:', error);
31
- process.exit(1);
32
- });
33
- },
12
+ name: 'check-should-run-type-checks-cli',
13
+ version: '6.1.0',
14
+ args: {
15
+ pathsIgnore: cmd.multioption({
16
+ long: 'paths-ignore',
17
+ type: cmd.optional(cmd.array(cmd.string)),
18
+ description: 'Patterns to ignore when checking if type checks should run. Supports exact file matches, directory prefixes (ending with "/"), and file extensions (starting with "**.")',
19
+ }),
20
+ baseBranch: cmd.option({
21
+ long: 'base-branch',
22
+ type: cmd.optional(cmd.string),
23
+ description: 'Base branch to compare against for determining changed files. Defaults to "origin/main"',
24
+ }),
25
+ },
26
+ handler: (args) => {
27
+ main(args).catch((error) => {
28
+ console.error('An error occurred:', error);
29
+ process.exit(1);
30
+ });
31
+ },
34
32
  });
35
33
  const main = async (args) => {
36
- await checkShouldRunTypeChecks({
37
- pathsIgnore: args.pathsIgnore,
38
- baseBranch: args.baseBranch,
39
- });
34
+ await checkShouldRunTypeChecks({
35
+ pathsIgnore: args.pathsIgnore,
36
+ baseBranch: args.baseBranch,
37
+ });
40
38
  };
41
39
  await cmd.run(cmdDef, process.argv.slice(2));
42
40
  //# sourceMappingURL=check-should-run-type-checks.mjs.map
@@ -1,45 +1,44 @@
1
1
  #!/usr/bin/env -S npx tsx
2
- import 'child_process';
3
2
  import * as cmd from 'cmd-ts';
4
- import 'micromatch';
5
- import 'node:child_process';
6
3
  import 'ts-data-forge';
7
- import { formatDiffFrom } from '../functions/format.mjs';
8
4
  import '../node-global.mjs';
5
+ import 'node:child_process';
6
+ import { formatDiffFrom } from '../functions/format.mjs';
7
+ import 'micromatch';
8
+ import 'child_process';
9
9
 
10
10
  const cmdDef = cmd.command({
11
- name: 'format-diff-from-cli',
12
- version: '6.0.4',
13
- args: {
14
- base: cmd.positional({
15
- type: cmd.string,
16
- displayName: 'base',
17
- description: 'Base branch name or commit hash to compare against',
18
- }),
19
- includeUntracked: cmd.flag({
20
- long: 'include-untracked',
21
- type: cmd.optional(cmd.boolean),
22
- description:
23
- 'Include untracked files in addition to diff files (default: true)',
24
- }),
25
- silent: cmd.flag({
26
- long: 'silent',
27
- type: cmd.optional(cmd.boolean),
28
- description: 'If true, suppresses output messages (default: false)',
29
- }),
30
- },
31
- handler: (args) => {
32
- main(args).catch((error) => {
33
- console.error('An error occurred:', error);
34
- process.exit(1);
35
- });
36
- },
11
+ name: 'format-diff-from-cli',
12
+ version: '6.1.0',
13
+ args: {
14
+ base: cmd.positional({
15
+ type: cmd.string,
16
+ displayName: 'base',
17
+ description: 'Base branch name or commit hash to compare against',
18
+ }),
19
+ includeUntracked: cmd.flag({
20
+ long: 'include-untracked',
21
+ type: cmd.optional(cmd.boolean),
22
+ description: 'Include untracked files in addition to diff files (default: true)',
23
+ }),
24
+ silent: cmd.flag({
25
+ long: 'silent',
26
+ type: cmd.optional(cmd.boolean),
27
+ description: 'If true, suppresses output messages (default: false)',
28
+ }),
29
+ },
30
+ handler: (args) => {
31
+ main(args).catch((error) => {
32
+ console.error('An error occurred:', error);
33
+ process.exit(1);
34
+ });
35
+ },
37
36
  });
38
37
  const main = async (args) => {
39
- const result = await formatDiffFrom(args.base, args);
40
- if (result === 'err') {
41
- process.exit(1);
42
- }
38
+ const result = await formatDiffFrom(args.base, args);
39
+ if (result === 'err') {
40
+ process.exit(1);
41
+ }
43
42
  };
44
43
  await cmd.run(cmdDef, process.argv.slice(2));
45
44
  //# sourceMappingURL=format-diff-from.mjs.map
@@ -1,34 +1,34 @@
1
1
  #!/usr/bin/env -S npx tsx
2
- import 'child_process';
3
2
  import * as cmd from 'cmd-ts';
4
- import 'micromatch';
5
- import 'node:child_process';
6
3
  import 'ts-data-forge';
7
- import { formatUntracked } from '../functions/format.mjs';
8
4
  import '../node-global.mjs';
5
+ import 'node:child_process';
6
+ import { formatUntracked } from '../functions/format.mjs';
7
+ import 'micromatch';
8
+ import 'child_process';
9
9
 
10
10
  const cmdDef = cmd.command({
11
- name: 'format-untracked-cli',
12
- version: '6.0.4',
13
- args: {
14
- silent: cmd.flag({
15
- long: 'silent',
16
- type: cmd.optional(cmd.boolean),
17
- description: 'If true, suppresses output messages (default: false)',
18
- }),
19
- },
20
- handler: (args) => {
21
- main(args).catch((error) => {
22
- console.error('An error occurred:', error);
23
- process.exit(1);
24
- });
25
- },
11
+ name: 'format-untracked-cli',
12
+ version: '6.1.0',
13
+ args: {
14
+ silent: cmd.flag({
15
+ long: 'silent',
16
+ type: cmd.optional(cmd.boolean),
17
+ description: 'If true, suppresses output messages (default: false)',
18
+ }),
19
+ },
20
+ handler: (args) => {
21
+ main(args).catch((error) => {
22
+ console.error('An error occurred:', error);
23
+ process.exit(1);
24
+ });
25
+ },
26
26
  });
27
27
  const main = async (args) => {
28
- const result = await formatUntracked({ silent: args.silent });
29
- if (result === 'err') {
30
- process.exit(1);
31
- }
28
+ const result = await formatUntracked({ silent: args.silent });
29
+ if (result === 'err') {
30
+ process.exit(1);
31
+ }
32
32
  };
33
33
  await cmd.run(cmdDef, process.argv.slice(2));
34
34
  //# sourceMappingURL=format-untracked.mjs.map
@@ -1,119 +1,103 @@
1
1
  #!/usr/bin/env -S npx tsx
2
- import 'child_process';
3
2
  import * as cmd from 'cmd-ts';
3
+ import 'ts-data-forge';
4
+ import '../node-global.mjs';
4
5
  import 'node:child_process';
5
6
  import 'prettier';
6
- import 'ts-data-forge';
7
7
  import { genIndex } from '../functions/gen-index.mjs';
8
- import '../node-global.mjs';
8
+ import 'child_process';
9
9
 
10
10
  const extensionType = cmd.extendType(cmd.string, {
11
- from: (s) => {
12
- if (!s.startsWith('.')) {
13
- throw new Error(`ext should start with '.'`);
14
- }
15
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
16
- return Promise.resolve(s);
17
- },
11
+ from: (s) => {
12
+ if (!s.startsWith('.')) {
13
+ throw new Error(`ext should start with '.'`);
14
+ }
15
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
16
+ return Promise.resolve(s);
17
+ },
18
18
  });
19
19
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
20
- const nonEmptyArray = (t, commandName) =>
21
- cmd.extendType(cmd.array(t), {
20
+ const nonEmptyArray = (t, commandName) => cmd.extendType(cmd.array(t), {
22
21
  from: (arr) => {
23
- if (arr.length === 0) {
24
- throw new Error(
25
- `No value provided for --${commandName}. At least one value is required.`,
26
- );
27
- }
28
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
29
- return Promise.resolve(arr);
22
+ if (arr.length === 0) {
23
+ throw new Error(`No value provided for --${commandName}. At least one value is required.`);
24
+ }
25
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
26
+ return Promise.resolve(arr);
30
27
  },
31
- });
28
+ });
32
29
  const cmdDef = cmd.command({
33
- name: 'gen-index-ts-cli',
34
- version: '6.0.4',
35
- args: {
36
- // required args
37
- targetDirectory: cmd.positional({
38
- type: cmd.string,
39
- displayName: 'target-directory',
40
- description:
41
- 'Directory where the index file will be generated (Comma-separated list can be used)',
42
- }),
43
- targetExtensions: cmd.multioption({
44
- long: 'target-ext',
45
- type: nonEmptyArray(extensionType, 'target-ext'),
46
- description: 'File extensions to include in the index file',
47
- }),
48
- indexFileExtension: cmd.option({
49
- long: 'index-ext',
50
- type: extensionType,
51
- description: 'Extension of the index file to be generated',
52
- }),
53
- exportStatementExtension: cmd.option({
54
- long: 'export-ext',
55
- type: cmd.union([
56
- extensionType,
57
- cmd.extendType(cmd.string, {
58
- from: (s) => {
59
- if (s !== 'none') {
60
- throw new Error(
61
- `export-ext should be 'none' or a valid extension`,
62
- );
63
- }
64
- return Promise.resolve('none');
65
- },
30
+ name: 'gen-index-ts-cli',
31
+ version: '6.1.0',
32
+ args: {
33
+ // required args
34
+ targetDirectory: cmd.positional({
35
+ type: cmd.string,
36
+ displayName: 'target-directory',
37
+ description: 'Directory where the index file will be generated (Comma-separated list can be used)',
66
38
  }),
67
- ]),
68
- description: 'Extension of the export statements in the index file',
69
- }),
70
- // optional args
71
- exclude: cmd.multioption({
72
- long: 'exclude',
73
- type: cmd.optional(cmd.array(cmd.string)),
74
- description:
75
- 'Glob patterns of files to exclude from the index file (e.g., "*.d.mts", "*.test.mts")',
76
- }),
77
- formatCommand: cmd.option({
78
- long: 'fmt',
79
- type: cmd.optional(cmd.string),
80
- description:
81
- 'Command to format after generating the index file (e.g., "npm run fmt")',
82
- }),
83
- silent: cmd.flag({
84
- long: 'silent',
85
- type: cmd.optional(cmd.boolean),
86
- description: 'If true, suppresses output messages (default: false)',
87
- }),
88
- },
89
- handler: (args) => {
90
- console.log(args);
91
- main(args).catch((error) => {
92
- console.error('An error occurred:', error);
93
- process.exit(1);
94
- });
95
- },
39
+ targetExtensions: cmd.multioption({
40
+ long: 'target-ext',
41
+ type: nonEmptyArray(extensionType, 'target-ext'),
42
+ description: 'File extensions to include in the index file',
43
+ }),
44
+ indexFileExtension: cmd.option({
45
+ long: 'index-ext',
46
+ type: extensionType,
47
+ description: 'Extension of the index file to be generated',
48
+ }),
49
+ exportStatementExtension: cmd.option({
50
+ long: 'export-ext',
51
+ type: cmd.union([
52
+ extensionType,
53
+ cmd.extendType(cmd.string, {
54
+ from: (s) => {
55
+ if (s !== 'none') {
56
+ throw new Error(`export-ext should be 'none' or a valid extension`);
57
+ }
58
+ return Promise.resolve('none');
59
+ },
60
+ }),
61
+ ]),
62
+ description: 'Extension of the export statements in the index file',
63
+ }),
64
+ // optional args
65
+ exclude: cmd.multioption({
66
+ long: 'exclude',
67
+ type: cmd.optional(cmd.array(cmd.string)),
68
+ description: 'Glob patterns of files to exclude from the index file (e.g., "*.d.mts", "*.test.mts")',
69
+ }),
70
+ formatCommand: cmd.option({
71
+ long: 'fmt',
72
+ type: cmd.optional(cmd.string),
73
+ description: 'Command to format after generating the index file (e.g., "npm run fmt")',
74
+ }),
75
+ silent: cmd.flag({
76
+ long: 'silent',
77
+ type: cmd.optional(cmd.boolean),
78
+ description: 'If true, suppresses output messages (default: false)',
79
+ }),
80
+ },
81
+ handler: (args) => {
82
+ console.log(args);
83
+ main(args).catch((error) => {
84
+ console.error('An error occurred:', error);
85
+ process.exit(1);
86
+ });
87
+ },
96
88
  });
97
- const main = async ({
98
- targetDirectory,
99
- targetExtensions,
100
- exportStatementExtension,
101
- indexFileExtension,
102
- exclude,
103
- formatCommand,
104
- silent,
105
- }) => {
106
- await genIndex({
107
- targetDirectory: targetDirectory.includes(',')
108
- ? targetDirectory.split(',').map((dir) => dir.trim())
109
- : targetDirectory,
110
- exportStatementExtension,
111
- targetExtensions,
112
- exclude,
113
- indexFileExtension,
114
- formatCommand,
115
- silent,
116
- });
89
+ const main = async ({ targetDirectory, targetExtensions, exportStatementExtension, indexFileExtension, exclude, formatCommand, silent, }) => {
90
+ await genIndex({
91
+ targetDirectory: targetDirectory.includes(',')
92
+ ? targetDirectory.split(',').map((dir) => dir.trim())
93
+ : targetDirectory,
94
+ exportStatementExtension,
95
+ targetExtensions,
96
+ exclude,
97
+ indexFileExtension,
98
+ formatCommand,
99
+ silent,
100
+ });
117
101
  };
118
102
  await cmd.run(cmdDef, process.argv.slice(2));
119
103
  //# sourceMappingURL=gen-index-ts.mjs.map
@@ -1,30 +1,33 @@
1
- import { Result } from 'ts-data-forge';
2
1
  import '../../node-global.mjs';
3
2
  import { type Package } from './types.mjs';
4
3
  /**
5
4
  * Executes a npm script across multiple packages in parallel with a concurrency
6
- * limit.
5
+ * limit. Uses fail-fast behavior - stops execution immediately when any package
6
+ * fails.
7
7
  *
8
8
  * @param packages - Array of Package objects to execute the script in
9
9
  * @param scriptName - The name of the npm script to execute
10
10
  * @param concurrency - Maximum number of packages to process simultaneously
11
11
  * (default: 3)
12
- * @returns A promise that resolves to an array of execution results
12
+ * @returns A promise that resolves to an array of execution results, or rejects
13
+ * immediately on first failure
13
14
  */
14
- export declare const executeParallel: (packages: readonly Package[], scriptName: string, concurrency?: number) => Promise<readonly Result<Readonly<{
15
+ export declare const executeParallel: (packages: readonly Package[], scriptName: string, concurrency?: number) => Promise<readonly Readonly<{
15
16
  code?: number;
16
17
  skipped?: boolean;
17
- }>, Error>[]>;
18
+ }>[]>;
18
19
  /**
19
20
  * Executes a npm script across packages in dependency order stages. Packages
20
21
  * are grouped into stages where each stage contains packages whose dependencies
21
- * have been completed in previous stages.
22
+ * have been completed in previous stages. Uses fail-fast behavior - stops
23
+ * execution immediately when any package fails.
22
24
  *
23
25
  * @param packages - Array of Package objects to execute the script in
24
26
  * @param scriptName - The name of the npm script to execute
25
27
  * @param concurrency - Maximum number of packages to process simultaneously
26
28
  * within each stage (default: 3)
27
- * @returns A promise that resolves when all stages are complete
29
+ * @returns A promise that resolves when all stages are complete, or rejects
30
+ * immediately on first failure
28
31
  */
29
32
  export declare const executeStages: (packages: readonly Package[], scriptName: string, concurrency?: number) => Promise<void>;
30
33
  //# sourceMappingURL=execute-parallel.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"execute-parallel.d.mts","sourceRoot":"","sources":["../../../src/functions/workspace-utils/execute-parallel.mts"],"names":[],"mappings":"AACA,OAAO,EAML,MAAM,EACP,MAAM,eAAe,CAAC;AACvB,OAAO,uBAAuB,CAAC;AAC/B,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,aAAa,CAAC;AAI3C;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,GAC1B,UAAU,SAAS,OAAO,EAAE,EAC5B,YAAY,MAAM,EAClB,cAAa,MAAU,KACtB,OAAO,CACR,SAAS,MAAM,CAAC,QAAQ,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,EAAE,KAAK,CAAC,EAAE,CAkCzE,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,aAAa,GACxB,UAAU,SAAS,OAAO,EAAE,EAC5B,YAAY,MAAM,EAClB,cAAa,MAAU,KACtB,OAAO,CAAC,IAAI,CAyCd,CAAC"}
1
+ {"version":3,"file":"execute-parallel.d.mts","sourceRoot":"","sources":["../../../src/functions/workspace-utils/execute-parallel.mts"],"names":[],"mappings":"AAUA,OAAO,uBAAuB,CAAC;AAC/B,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,aAAa,CAAC;AAI3C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,eAAe,GAC1B,UAAU,SAAS,OAAO,EAAE,EAC5B,YAAY,MAAM,EAClB,cAAa,MAAU,KACtB,OAAO,CAAC,SAAS,QAAQ,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,EAAE,CA8DnE,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,aAAa,GACxB,UAAU,SAAS,OAAO,EAAE,EAC5B,YAAY,MAAM,EAClB,cAAa,MAAU,KACtB,OAAO,CAAC,IAAI,CA0Dd,CAAC"}
@@ -1,45 +1,79 @@
1
1
  import { spawn } from 'child_process';
2
- import { pipe, createPromise, isRecord, hasKey, Result, isNotUndefined } from 'ts-data-forge';
2
+ import { pipe, Result, createPromise, isRecord, hasKey, isNotUndefined } from 'ts-data-forge';
3
3
  import '../../node-global.mjs';
4
4
 
5
+ /* eslint-disable require-atomic-updates */
5
6
  /**
6
7
  * Executes a npm script across multiple packages in parallel with a concurrency
7
- * limit.
8
+ * limit. Uses fail-fast behavior - stops execution immediately when any package
9
+ * fails.
8
10
  *
9
11
  * @param packages - Array of Package objects to execute the script in
10
12
  * @param scriptName - The name of the npm script to execute
11
13
  * @param concurrency - Maximum number of packages to process simultaneously
12
14
  * (default: 3)
13
- * @returns A promise that resolves to an array of execution results
15
+ * @returns A promise that resolves to an array of execution results, or rejects
16
+ * immediately on first failure
14
17
  */
15
18
  const executeParallel = async (packages, scriptName, concurrency = 3) => {
16
19
  const mut_resultPromises = [];
17
20
  const mut_executing = new Set();
21
+ let mut_failed = false;
18
22
  for (const pkg of packages) {
19
- const promise = executeScript(pkg, scriptName);
23
+ // Stop starting new processes if any has failed
24
+ if (mut_failed) {
25
+ break;
26
+ }
27
+ // eslint-disable-next-line @typescript-eslint/no-loop-func
28
+ const promise = executeScript(pkg, scriptName).then((result) => {
29
+ // Check for failure immediately
30
+ if (Result.isErr(result)) {
31
+ mut_failed = true;
32
+ throw result.value; // Throw the error to trigger fail-fast
33
+ }
34
+ return result.value; // Return the unwrapped value for success
35
+ });
20
36
  mut_resultPromises.push(promise);
21
- const wrappedPromise = promise.finally(() => {
37
+ const wrappedPromise = promise
38
+ // eslint-disable-next-line @typescript-eslint/no-loop-func
39
+ .catch((error) => {
40
+ mut_failed = true;
41
+ throw error; // Re-throw to ensure fail-fast propagation
42
+ })
43
+ .finally(() => {
22
44
  mut_executing.delete(wrappedPromise);
23
45
  });
24
46
  mut_executing.add(wrappedPromise);
25
47
  // If we reach concurrency limit, wait for one to finish
26
48
  if (mut_executing.size >= concurrency) {
27
- // eslint-disable-next-line no-await-in-loop
28
- await Promise.race(mut_executing);
49
+ try {
50
+ // eslint-disable-next-line no-await-in-loop
51
+ await Promise.race(mut_executing);
52
+ }
53
+ catch (error) {
54
+ // If any process fails, cancel remaining processes and throw immediately
55
+ // eslint-disable-next-line no-useless-assignment
56
+ mut_failed = true;
57
+ throw error;
58
+ }
29
59
  }
30
60
  }
61
+ // Wait for all started processes to complete
62
+ // This will throw immediately if any process fails (fail-fast)
31
63
  return Promise.all(mut_resultPromises);
32
64
  };
33
65
  /**
34
66
  * Executes a npm script across packages in dependency order stages. Packages
35
67
  * are grouped into stages where each stage contains packages whose dependencies
36
- * have been completed in previous stages.
68
+ * have been completed in previous stages. Uses fail-fast behavior - stops
69
+ * execution immediately when any package fails.
37
70
  *
38
71
  * @param packages - Array of Package objects to execute the script in
39
72
  * @param scriptName - The name of the npm script to execute
40
73
  * @param concurrency - Maximum number of packages to process simultaneously
41
74
  * within each stage (default: 3)
42
- * @returns A promise that resolves when all stages are complete
75
+ * @returns A promise that resolves when all stages are complete, or rejects
76
+ * immediately on first failure
43
77
  */
44
78
  const executeStages = async (packages, scriptName, concurrency = 3) => {
45
79
  const dependencyGraph = buildDependencyGraph(packages);
@@ -65,12 +99,24 @@ const executeStages = async (packages, scriptName, concurrency = 3) => {
65
99
  mut_completed.add(pkg.name);
66
100
  }
67
101
  }
68
- console.log(`\nExecuting ${scriptName} in ${mut_stages.length} stages...\n`);
102
+ console.log(`\nExecuting ${scriptName} in ${mut_stages.length} stages (fail-fast mode)...\n`);
69
103
  for (const [i, stage] of mut_stages.entries()) {
70
104
  if (stage.length > 0) {
71
105
  console.log(`Stage ${i + 1}: ${stage.map((p) => p.name).join(', ')}`);
72
- // eslint-disable-next-line no-await-in-loop
73
- await executeParallel(stage, scriptName, concurrency);
106
+ try {
107
+ // eslint-disable-next-line no-await-in-loop
108
+ const results = await executeParallel(stage, scriptName, concurrency);
109
+ // Log successful completion of the stage
110
+ // All results are successful because executeParallel throws on any failure
111
+ console.log(`✅ Stage ${i + 1} completed successfully (${results.length}/${stage.length} packages)`);
112
+ }
113
+ catch (error) {
114
+ // executeParallel will throw immediately on any failure (fail-fast)
115
+ const errorMessage = error instanceof Error ? error.message : String(error);
116
+ console.error(`\n❌ Stage ${i + 1} failed (fail-fast):`);
117
+ console.error(errorMessage);
118
+ throw new Error(`Stage ${i + 1} failed: ${errorMessage}`);
119
+ }
74
120
  }
75
121
  }
76
122
  };
@@ -107,8 +153,8 @@ const executeScript = (pkg, scriptName, { prefix = true } = {}) => pipe(createPr
107
153
  process.stderr.write(prefixStr + data.toString());
108
154
  });
109
155
  proc.on('close', (code) => {
110
- if (code === 0) {
111
- resolve({ code });
156
+ if (code === 0 || code === null) {
157
+ resolve({ code: code ?? 0 });
112
158
  }
113
159
  else {
114
160
  reject(new Error(`${pkg.name} exited with code ${code}`));
@@ -1 +1 @@
1
- {"version":3,"file":"execute-parallel.mjs","sources":["../../../src/functions/workspace-utils/execute-parallel.mts"],"sourcesContent":[null],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"execute-parallel.mjs","sources":["../../../src/functions/workspace-utils/execute-parallel.mts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env tsx
2
2
  /**
3
- * Executes a npm script command across all workspace packages in parallel.
3
+ * Executes a npm script command across all workspace packages in parallel. Uses
4
+ * fail-fast behavior - stops execution immediately when any package fails.
4
5
  *
5
6
  * @param options - Configuration options for the parallel execution
6
7
  * @param options.rootPackageJsonDir - The directory containing the root
@@ -11,6 +12,7 @@
11
12
  * @param options.filterWorkspacePattern - Optional function to filter packages
12
13
  * by name
13
14
  * @returns A promise that resolves when all packages have completed execution
15
+ * successfully, or rejects immediately on first failure
14
16
  */
15
17
  export declare const runCmdInParallelAcrossWorkspaces: ({ rootPackageJsonDir, cmd, concurrency, filterWorkspacePattern, }: Readonly<{
16
18
  rootPackageJsonDir: string;
@@ -1 +1 @@
1
- {"version":3,"file":"run-cmd-in-parallel.d.mts","sourceRoot":"","sources":["../../../src/functions/workspace-utils/run-cmd-in-parallel.mts"],"names":[],"mappings":";AAKA;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,gCAAgC,GAAU,mEAKpD,QAAQ,CAAC;IACV,kBAAkB,EAAE,MAAM,CAAC;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sBAAsB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC;CAC3D,CAAC,KAAG,OAAO,CAAC,IAAI,CAkBhB,CAAC"}
1
+ {"version":3,"file":"run-cmd-in-parallel.d.mts","sourceRoot":"","sources":["../../../src/functions/workspace-utils/run-cmd-in-parallel.mts"],"names":[],"mappings":";AAKA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,gCAAgC,GAAU,mEAKpD,QAAQ,CAAC;IACV,kBAAkB,EAAE,MAAM,CAAC;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sBAAsB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC;CAC3D,CAAC,KAAG,OAAO,CAAC,IAAI,CAqBhB,CAAC"}
@@ -3,7 +3,8 @@ import { executeParallel } from './execute-parallel.mjs';
3
3
  import { getWorkspacePackages } from './get-workspace-packages.mjs';
4
4
 
5
5
  /**
6
- * Executes a npm script command across all workspace packages in parallel.
6
+ * Executes a npm script command across all workspace packages in parallel. Uses
7
+ * fail-fast behavior - stops execution immediately when any package fails.
7
8
  *
8
9
  * @param options - Configuration options for the parallel execution
9
10
  * @param options.rootPackageJsonDir - The directory containing the root
@@ -14,6 +15,7 @@ import { getWorkspacePackages } from './get-workspace-packages.mjs';
14
15
  * @param options.filterWorkspacePattern - Optional function to filter packages
15
16
  * by name
16
17
  * @returns A promise that resolves when all packages have completed execution
18
+ * successfully, or rejects immediately on first failure
17
19
  */
18
20
  const runCmdInParallelAcrossWorkspaces = async ({ rootPackageJsonDir, cmd, concurrency = 3, filterWorkspacePattern, }) => {
19
21
  try {
@@ -21,11 +23,14 @@ const runCmdInParallelAcrossWorkspaces = async ({ rootPackageJsonDir, cmd, concu
21
23
  const filteredPackages = filterWorkspacePattern === undefined
22
24
  ? packages
23
25
  : packages.filter((pkg) => filterWorkspacePattern(pkg.name));
26
+ console.log(`\nStarting ${cmd} across ${filteredPackages.length} packages (fail-fast parallel mode)...`);
24
27
  await executeParallel(filteredPackages, cmd, concurrency);
25
- console.log(`\n✅ ${cmd} completed successfully`);
28
+ console.log(`\n✅ ${cmd} completed successfully (all packages)`);
26
29
  }
27
30
  catch (error) {
28
- console.error(`\n❌ ${cmd} failed:`, error instanceof Error ? error.message : (error?.toString() ?? ''));
31
+ const errorMessage = error instanceof Error ? error.message : (error?.toString() ?? '');
32
+ console.error(`\n❌ ${cmd} failed (fail-fast mode stopped execution):`);
33
+ console.error(errorMessage);
29
34
  process.exit(1);
30
35
  }
31
36
  };
@@ -1 +1 @@
1
- {"version":3,"file":"run-cmd-in-parallel.mjs","sources":["../../../src/functions/workspace-utils/run-cmd-in-parallel.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAKA;;;;;;;;;;;;AAYG;AACI,MAAM,gCAAgC,GAAG,OAAO,EACrD,kBAAkB,EAClB,GAAG,EACH,WAAW,GAAG,CAAC,EACf,sBAAsB,GAMtB,KAAmB;AACnB,IAAA,IAAI;AACF,QAAA,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,kBAAkB,CAAC;AAE/D,QAAA,MAAM,gBAAgB,GACpB,sBAAsB,KAAK;AACzB,cAAE;AACF,cAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAEhE,MAAM,eAAe,CAAC,gBAAgB,EAAE,GAAG,EAAE,WAAW,CAAC;AACzD,QAAA,OAAO,CAAC,GAAG,CAAC,OAAO,GAAG,CAAA,uBAAA,CAAyB,CAAC;IAClD;IAAE,OAAO,KAAK,EAAE;AACd,QAAA,OAAO,CAAC,KAAK,CACX,CAAA,IAAA,EAAO,GAAG,CAAA,QAAA,CAAU,EACpB,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,IAAI,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CACnE;AACD,QAAA,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACjB;AACF;;;;"}
1
+ {"version":3,"file":"run-cmd-in-parallel.mjs","sources":["../../../src/functions/workspace-utils/run-cmd-in-parallel.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAKA;;;;;;;;;;;;;;AAcG;AACI,MAAM,gCAAgC,GAAG,OAAO,EACrD,kBAAkB,EAClB,GAAG,EACH,WAAW,GAAG,CAAC,EACf,sBAAsB,GAMtB,KAAmB;AACnB,IAAA,IAAI;AACF,QAAA,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,kBAAkB,CAAC;AAE/D,QAAA,MAAM,gBAAgB,GACpB,sBAAsB,KAAK;AACzB,cAAE;AACF,cAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAEhE,OAAO,CAAC,GAAG,CACT,CAAA,WAAA,EAAc,GAAG,CAAA,QAAA,EAAW,gBAAgB,CAAC,MAAM,CAAA,sCAAA,CAAwC,CAC5F;QACD,MAAM,eAAe,CAAC,gBAAgB,EAAE,GAAG,EAAE,WAAW,CAAC;AACzD,QAAA,OAAO,CAAC,GAAG,CAAC,OAAO,GAAG,CAAA,sCAAA,CAAwC,CAAC;IACjE;IAAE,OAAO,KAAK,EAAE;QACd,MAAM,YAAY,GAChB,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,IAAI,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AACpE,QAAA,OAAO,CAAC,KAAK,CAAC,OAAO,GAAG,CAAA,2CAAA,CAA6C,CAAC;AACtE,QAAA,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC;AAC3B,QAAA,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACjB;AACF;;;;"}
@@ -2,7 +2,8 @@
2
2
  /**
3
3
  * Executes a npm script command across all workspace packages in dependency
4
4
  * order stages. Packages are grouped into stages where each stage contains
5
- * packages whose dependencies have been completed in previous stages.
5
+ * packages whose dependencies have been completed in previous stages. Uses
6
+ * fail-fast behavior - stops execution immediately when any package fails.
6
7
  *
7
8
  * @param options - Configuration options for the staged execution
8
9
  * @param options.rootPackageJsonDir - The directory containing the root
@@ -13,6 +14,7 @@
13
14
  * @param options.filterWorkspacePattern - Optional function to filter packages
14
15
  * by name
15
16
  * @returns A promise that resolves when all stages have completed execution
17
+ * successfully, or rejects immediately on first failure
16
18
  */
17
19
  export declare const runCmdInStagesAcrossWorkspaces: ({ rootPackageJsonDir, cmd, concurrency, filterWorkspacePattern, }: Readonly<{
18
20
  rootPackageJsonDir: string;
@@ -1 +1 @@
1
- {"version":3,"file":"run-cmd-in-stages.d.mts","sourceRoot":"","sources":["../../../src/functions/workspace-utils/run-cmd-in-stages.mts"],"names":[],"mappings":";AAKA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,8BAA8B,GAAU,mEAKlD,QAAQ,CAAC;IACV,kBAAkB,EAAE,MAAM,CAAC;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sBAAsB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC;CAC3D,CAAC,KAAG,OAAO,CAAC,IAAI,CAkBhB,CAAC"}
1
+ {"version":3,"file":"run-cmd-in-stages.d.mts","sourceRoot":"","sources":["../../../src/functions/workspace-utils/run-cmd-in-stages.mts"],"names":[],"mappings":";AAKA;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,8BAA8B,GAAU,mEAKlD,QAAQ,CAAC;IACV,kBAAkB,EAAE,MAAM,CAAC;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sBAAsB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC;CAC3D,CAAC,KAAG,OAAO,CAAC,IAAI,CAqBhB,CAAC"}
@@ -5,7 +5,8 @@ import { getWorkspacePackages } from './get-workspace-packages.mjs';
5
5
  /**
6
6
  * Executes a npm script command across all workspace packages in dependency
7
7
  * order stages. Packages are grouped into stages where each stage contains
8
- * packages whose dependencies have been completed in previous stages.
8
+ * packages whose dependencies have been completed in previous stages. Uses
9
+ * fail-fast behavior - stops execution immediately when any package fails.
9
10
  *
10
11
  * @param options - Configuration options for the staged execution
11
12
  * @param options.rootPackageJsonDir - The directory containing the root
@@ -16,6 +17,7 @@ import { getWorkspacePackages } from './get-workspace-packages.mjs';
16
17
  * @param options.filterWorkspacePattern - Optional function to filter packages
17
18
  * by name
18
19
  * @returns A promise that resolves when all stages have completed execution
20
+ * successfully, or rejects immediately on first failure
19
21
  */
20
22
  const runCmdInStagesAcrossWorkspaces = async ({ rootPackageJsonDir, cmd, concurrency = 3, filterWorkspacePattern, }) => {
21
23
  try {
@@ -23,11 +25,14 @@ const runCmdInStagesAcrossWorkspaces = async ({ rootPackageJsonDir, cmd, concurr
23
25
  const filteredPackages = filterWorkspacePattern === undefined
24
26
  ? packages
25
27
  : packages.filter((pkg) => filterWorkspacePattern(pkg.name));
28
+ console.log(`\nStarting ${cmd} across ${filteredPackages.length} packages (fail-fast mode)...`);
26
29
  await executeStages(filteredPackages, cmd, concurrency);
27
- console.log(`\n✅ ${cmd} completed successfully`);
30
+ console.log(`\n✅ ${cmd} completed successfully (all stages)`);
28
31
  }
29
32
  catch (error) {
30
- console.error(`\n❌ ${cmd} failed:`, error instanceof Error ? error.message : (error?.toString() ?? ''));
33
+ const errorMessage = error instanceof Error ? error.message : (error?.toString() ?? '');
34
+ console.error(`\n❌ ${cmd} failed (fail-fast mode stopped execution):`);
35
+ console.error(errorMessage);
31
36
  process.exit(1);
32
37
  }
33
38
  };
@@ -1 +1 @@
1
- {"version":3,"file":"run-cmd-in-stages.mjs","sources":["../../../src/functions/workspace-utils/run-cmd-in-stages.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAKA;;;;;;;;;;;;;;AAcG;AACI,MAAM,8BAA8B,GAAG,OAAO,EACnD,kBAAkB,EAClB,GAAG,EACH,WAAW,GAAG,CAAC,EACf,sBAAsB,GAMtB,KAAmB;AACnB,IAAA,IAAI;AACF,QAAA,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,kBAAkB,CAAC;AAE/D,QAAA,MAAM,gBAAgB,GACpB,sBAAsB,KAAK;AACzB,cAAE;AACF,cAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAEhE,MAAM,aAAa,CAAC,gBAAgB,EAAE,GAAG,EAAE,WAAW,CAAC;AACvD,QAAA,OAAO,CAAC,GAAG,CAAC,OAAO,GAAG,CAAA,uBAAA,CAAyB,CAAC;IAClD;IAAE,OAAO,KAAK,EAAE;AACd,QAAA,OAAO,CAAC,KAAK,CACX,CAAA,IAAA,EAAO,GAAG,CAAA,QAAA,CAAU,EACpB,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,IAAI,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CACnE;AACD,QAAA,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACjB;AACF;;;;"}
1
+ {"version":3,"file":"run-cmd-in-stages.mjs","sources":["../../../src/functions/workspace-utils/run-cmd-in-stages.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAKA;;;;;;;;;;;;;;;;AAgBG;AACI,MAAM,8BAA8B,GAAG,OAAO,EACnD,kBAAkB,EAClB,GAAG,EACH,WAAW,GAAG,CAAC,EACf,sBAAsB,GAMtB,KAAmB;AACnB,IAAA,IAAI;AACF,QAAA,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,kBAAkB,CAAC;AAE/D,QAAA,MAAM,gBAAgB,GACpB,sBAAsB,KAAK;AACzB,cAAE;AACF,cAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAEhE,OAAO,CAAC,GAAG,CACT,CAAA,WAAA,EAAc,GAAG,CAAA,QAAA,EAAW,gBAAgB,CAAC,MAAM,CAAA,6BAAA,CAA+B,CACnF;QACD,MAAM,aAAa,CAAC,gBAAgB,EAAE,GAAG,EAAE,WAAW,CAAC;AACvD,QAAA,OAAO,CAAC,GAAG,CAAC,OAAO,GAAG,CAAA,oCAAA,CAAsC,CAAC;IAC/D;IAAE,OAAO,KAAK,EAAE;QACd,MAAM,YAAY,GAChB,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,IAAI,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AACpE,QAAA,OAAO,CAAC,KAAK,CAAC,OAAO,GAAG,CAAA,2CAAA,CAA6C,CAAC;AACtE,QAAA,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC;AAC3B,QAAA,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACjB;AACF;;;;"}
package/dist/index.d.mts CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from './functions/index.mjs';
2
+ export { Result } from 'ts-data-forge';
2
3
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.mts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.mts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AAEtC,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC"}
package/dist/index.mjs CHANGED
@@ -10,4 +10,5 @@ export { executeParallel, executeStages } from './functions/workspace-utils/exec
10
10
  export { getWorkspacePackages } from './functions/workspace-utils/get-workspace-packages.mjs';
11
11
  export { runCmdInParallelAcrossWorkspaces } from './functions/workspace-utils/run-cmd-in-parallel.mjs';
12
12
  export { runCmdInStagesAcrossWorkspaces } from './functions/workspace-utils/run-cmd-in-stages.mjs';
13
+ export { Result } from 'ts-data-forge';
13
14
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;"}
1
+ {"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-repo-utils",
3
- "version": "6.0.4",
3
+ "version": "6.1.0",
4
4
  "private": false,
5
5
  "keywords": [
6
6
  "typescript"
@@ -5,7 +5,7 @@ import { assertRepoIsClean } from '../functions/index.mjs';
5
5
 
6
6
  const cmdDef = cmd.command({
7
7
  name: 'assert-repo-is-clean-cli',
8
- version: '6.0.4',
8
+ version: '6.1.0',
9
9
  args: {
10
10
  silent: cmd.flag({
11
11
  long: 'silent',
@@ -5,7 +5,7 @@ import { checkShouldRunTypeChecks } from '../functions/index.mjs';
5
5
 
6
6
  const cmdDef = cmd.command({
7
7
  name: 'check-should-run-type-checks-cli',
8
- version: '6.0.4',
8
+ version: '6.1.0',
9
9
  args: {
10
10
  pathsIgnore: cmd.multioption({
11
11
  long: 'paths-ignore',
@@ -5,7 +5,7 @@ import { formatDiffFrom } from '../functions/index.mjs';
5
5
 
6
6
  const cmdDef = cmd.command({
7
7
  name: 'format-diff-from-cli',
8
- version: '6.0.4',
8
+ version: '6.1.0',
9
9
  args: {
10
10
  base: cmd.positional({
11
11
  type: cmd.string,
@@ -5,7 +5,7 @@ import { formatUntracked } from '../functions/index.mjs';
5
5
 
6
6
  const cmdDef = cmd.command({
7
7
  name: 'format-untracked-cli',
8
- version: '6.0.4',
8
+ version: '6.1.0',
9
9
  args: {
10
10
  silent: cmd.flag({
11
11
  long: 'silent',
@@ -38,7 +38,7 @@ const nonEmptyArray = <T extends cmd.Type<any, any>>(
38
38
 
39
39
  const cmdDef = cmd.command({
40
40
  name: 'gen-index-ts-cli',
41
- version: '6.0.4',
41
+ version: '6.1.0',
42
42
  args: {
43
43
  // required args
44
44
  targetDirectory: cmd.positional({
@@ -2,7 +2,11 @@ import { Result } from 'ts-data-forge';
2
2
  import '../node-global.mjs';
3
3
  import { getDiffFrom, getUntrackedFiles } from './diff.mjs';
4
4
 
5
- describe('diff', () => {
5
+ // Check if running in CI environment (GitHub Actions or other CI)
6
+ const isCI =
7
+ process.env['CI'] === 'true' || process.env['GITHUB_ACTIONS'] === 'true';
8
+
9
+ describe.skipIf(!isCI)('diff', () => {
6
10
  // Helper function to clean up test files
7
11
  const cleanupTestFiles = async (files: Set<string>): Promise<void> => {
8
12
  for (const file of files) {
@@ -1,3 +1,4 @@
1
+ /* eslint-disable require-atomic-updates */
1
2
  import { spawn } from 'child_process';
2
3
  import {
3
4
  createPromise,
@@ -14,39 +15,59 @@ const DEBUG = false as boolean;
14
15
 
15
16
  /**
16
17
  * Executes a npm script across multiple packages in parallel with a concurrency
17
- * limit.
18
+ * limit. Uses fail-fast behavior - stops execution immediately when any package
19
+ * fails.
18
20
  *
19
21
  * @param packages - Array of Package objects to execute the script in
20
22
  * @param scriptName - The name of the npm script to execute
21
23
  * @param concurrency - Maximum number of packages to process simultaneously
22
24
  * (default: 3)
23
- * @returns A promise that resolves to an array of execution results
25
+ * @returns A promise that resolves to an array of execution results, or rejects
26
+ * immediately on first failure
24
27
  */
25
28
  export const executeParallel = async (
26
29
  packages: readonly Package[],
27
30
  scriptName: string,
28
31
  concurrency: number = 3,
29
- ): Promise<
30
- readonly Result<Readonly<{ code?: number; skipped?: boolean }>, Error>[]
31
- > => {
32
+ ): Promise<readonly Readonly<{ code?: number; skipped?: boolean }>[]> => {
32
33
  const mut_resultPromises: Promise<
33
- Result<Readonly<{ code?: number; skipped?: boolean }>, Error>
34
+ Readonly<{ code?: number; skipped?: boolean }>
34
35
  >[] = [];
35
36
 
36
37
  const mut_executing = new Set<Promise<unknown>>();
38
+ let mut_failed = false as boolean;
37
39
 
38
40
  for (const pkg of packages) {
39
- const promise = executeScript(pkg, scriptName);
40
-
41
- mut_resultPromises.push(promise);
41
+ // Stop starting new processes if any has failed
42
+ if (mut_failed) {
43
+ break;
44
+ }
42
45
 
43
- const wrappedPromise = promise.finally(() => {
44
- mut_executing.delete(wrappedPromise);
45
- if (DEBUG) {
46
- console.debug('executing size', mut_executing.size);
46
+ // eslint-disable-next-line @typescript-eslint/no-loop-func
47
+ const promise = executeScript(pkg, scriptName).then((result) => {
48
+ // Check for failure immediately
49
+ if (Result.isErr(result)) {
50
+ mut_failed = true;
51
+ throw result.value; // Throw the error to trigger fail-fast
47
52
  }
53
+ return result.value; // Return the unwrapped value for success
48
54
  });
49
55
 
56
+ mut_resultPromises.push(promise);
57
+
58
+ const wrappedPromise = promise
59
+ // eslint-disable-next-line @typescript-eslint/no-loop-func
60
+ .catch((error) => {
61
+ mut_failed = true;
62
+ throw error; // Re-throw to ensure fail-fast propagation
63
+ })
64
+ .finally(() => {
65
+ mut_executing.delete(wrappedPromise);
66
+ if (DEBUG) {
67
+ console.debug('executing size', mut_executing.size);
68
+ }
69
+ });
70
+
50
71
  mut_executing.add(wrappedPromise);
51
72
 
52
73
  if (DEBUG) {
@@ -55,24 +76,35 @@ export const executeParallel = async (
55
76
 
56
77
  // If we reach concurrency limit, wait for one to finish
57
78
  if (mut_executing.size >= concurrency) {
58
- // eslint-disable-next-line no-await-in-loop
59
- await Promise.race(mut_executing);
79
+ try {
80
+ // eslint-disable-next-line no-await-in-loop
81
+ await Promise.race(mut_executing);
82
+ } catch (error) {
83
+ // If any process fails, cancel remaining processes and throw immediately
84
+ // eslint-disable-next-line no-useless-assignment
85
+ mut_failed = true;
86
+ throw error;
87
+ }
60
88
  }
61
89
  }
62
90
 
91
+ // Wait for all started processes to complete
92
+ // This will throw immediately if any process fails (fail-fast)
63
93
  return Promise.all(mut_resultPromises);
64
94
  };
65
95
 
66
96
  /**
67
97
  * Executes a npm script across packages in dependency order stages. Packages
68
98
  * are grouped into stages where each stage contains packages whose dependencies
69
- * have been completed in previous stages.
99
+ * have been completed in previous stages. Uses fail-fast behavior - stops
100
+ * execution immediately when any package fails.
70
101
  *
71
102
  * @param packages - Array of Package objects to execute the script in
72
103
  * @param scriptName - The name of the npm script to execute
73
104
  * @param concurrency - Maximum number of packages to process simultaneously
74
105
  * within each stage (default: 3)
75
- * @returns A promise that resolves when all stages are complete
106
+ * @returns A promise that resolves when all stages are complete, or rejects
107
+ * immediately on first failure
76
108
  */
77
109
  export const executeStages = async (
78
110
  packages: readonly Package[],
@@ -110,13 +142,30 @@ export const executeStages = async (
110
142
  }
111
143
  }
112
144
 
113
- console.log(`\nExecuting ${scriptName} in ${mut_stages.length} stages...\n`);
145
+ console.log(
146
+ `\nExecuting ${scriptName} in ${mut_stages.length} stages (fail-fast mode)...\n`,
147
+ );
114
148
 
115
149
  for (const [i, stage] of mut_stages.entries()) {
116
150
  if (stage.length > 0) {
117
151
  console.log(`Stage ${i + 1}: ${stage.map((p) => p.name).join(', ')}`);
118
- // eslint-disable-next-line no-await-in-loop
119
- await executeParallel(stage, scriptName, concurrency);
152
+ try {
153
+ // eslint-disable-next-line no-await-in-loop
154
+ const results = await executeParallel(stage, scriptName, concurrency);
155
+
156
+ // Log successful completion of the stage
157
+ // All results are successful because executeParallel throws on any failure
158
+ console.log(
159
+ `✅ Stage ${i + 1} completed successfully (${results.length}/${stage.length} packages)`,
160
+ );
161
+ } catch (error) {
162
+ // executeParallel will throw immediately on any failure (fail-fast)
163
+ const errorMessage =
164
+ error instanceof Error ? error.message : String(error);
165
+ console.error(`\n❌ Stage ${i + 1} failed (fail-fast):`);
166
+ console.error(errorMessage);
167
+ throw new Error(`Stage ${i + 1} failed: ${errorMessage}`);
168
+ }
120
169
  }
121
170
  }
122
171
  };
@@ -172,8 +221,11 @@ const executeScript = (
172
221
  });
173
222
 
174
223
  proc.on('close', (code: number | null) => {
175
- if (code === 0) {
176
- resolve({ code });
224
+ if (DEBUG) {
225
+ console.debug(`${pkg.name} process closed with code: ${code}`);
226
+ }
227
+ if (code === 0 || code === null) {
228
+ resolve({ code: code ?? 0 });
177
229
  } else {
178
230
  reject(new Error(`${pkg.name} exited with code ${code}`));
179
231
  }
@@ -4,7 +4,8 @@ import { executeParallel } from './execute-parallel.mjs';
4
4
  import { getWorkspacePackages } from './get-workspace-packages.mjs';
5
5
 
6
6
  /**
7
- * Executes a npm script command across all workspace packages in parallel.
7
+ * Executes a npm script command across all workspace packages in parallel. Uses
8
+ * fail-fast behavior - stops execution immediately when any package fails.
8
9
  *
9
10
  * @param options - Configuration options for the parallel execution
10
11
  * @param options.rootPackageJsonDir - The directory containing the root
@@ -15,6 +16,7 @@ import { getWorkspacePackages } from './get-workspace-packages.mjs';
15
16
  * @param options.filterWorkspacePattern - Optional function to filter packages
16
17
  * by name
17
18
  * @returns A promise that resolves when all packages have completed execution
19
+ * successfully, or rejects immediately on first failure
18
20
  */
19
21
  export const runCmdInParallelAcrossWorkspaces = async ({
20
22
  rootPackageJsonDir,
@@ -35,13 +37,16 @@ export const runCmdInParallelAcrossWorkspaces = async ({
35
37
  ? packages
36
38
  : packages.filter((pkg) => filterWorkspacePattern(pkg.name));
37
39
 
40
+ console.log(
41
+ `\nStarting ${cmd} across ${filteredPackages.length} packages (fail-fast parallel mode)...`,
42
+ );
38
43
  await executeParallel(filteredPackages, cmd, concurrency);
39
- console.log(`\n✅ ${cmd} completed successfully`);
44
+ console.log(`\n✅ ${cmd} completed successfully (all packages)`);
40
45
  } catch (error) {
41
- console.error(
42
- `\n❌ ${cmd} failed:`,
43
- error instanceof Error ? error.message : (error?.toString() ?? ''),
44
- );
46
+ const errorMessage =
47
+ error instanceof Error ? error.message : (error?.toString() ?? '');
48
+ console.error(`\n❌ ${cmd} failed (fail-fast mode stopped execution):`);
49
+ console.error(errorMessage);
45
50
  process.exit(1);
46
51
  }
47
52
  };
@@ -6,7 +6,8 @@ import { getWorkspacePackages } from './get-workspace-packages.mjs';
6
6
  /**
7
7
  * Executes a npm script command across all workspace packages in dependency
8
8
  * order stages. Packages are grouped into stages where each stage contains
9
- * packages whose dependencies have been completed in previous stages.
9
+ * packages whose dependencies have been completed in previous stages. Uses
10
+ * fail-fast behavior - stops execution immediately when any package fails.
10
11
  *
11
12
  * @param options - Configuration options for the staged execution
12
13
  * @param options.rootPackageJsonDir - The directory containing the root
@@ -17,6 +18,7 @@ import { getWorkspacePackages } from './get-workspace-packages.mjs';
17
18
  * @param options.filterWorkspacePattern - Optional function to filter packages
18
19
  * by name
19
20
  * @returns A promise that resolves when all stages have completed execution
21
+ * successfully, or rejects immediately on first failure
20
22
  */
21
23
  export const runCmdInStagesAcrossWorkspaces = async ({
22
24
  rootPackageJsonDir,
@@ -37,13 +39,16 @@ export const runCmdInStagesAcrossWorkspaces = async ({
37
39
  ? packages
38
40
  : packages.filter((pkg) => filterWorkspacePattern(pkg.name));
39
41
 
42
+ console.log(
43
+ `\nStarting ${cmd} across ${filteredPackages.length} packages (fail-fast mode)...`,
44
+ );
40
45
  await executeStages(filteredPackages, cmd, concurrency);
41
- console.log(`\n✅ ${cmd} completed successfully`);
46
+ console.log(`\n✅ ${cmd} completed successfully (all stages)`);
42
47
  } catch (error) {
43
- console.error(
44
- `\n❌ ${cmd} failed:`,
45
- error instanceof Error ? error.message : (error?.toString() ?? ''),
46
- );
48
+ const errorMessage =
49
+ error instanceof Error ? error.message : (error?.toString() ?? '');
50
+ console.error(`\n❌ ${cmd} failed (fail-fast mode stopped execution):`);
51
+ console.error(errorMessage);
47
52
  process.exit(1);
48
53
  }
49
54
  };
package/src/index.mts CHANGED
@@ -1 +1,3 @@
1
1
  export * from './functions/index.mjs';
2
+
3
+ export { Result } from 'ts-data-forge';