ts-repo-utils 5.0.2 → 5.2.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.
- package/dist/functions/assert-ext.d.mts +12 -7
- package/dist/functions/assert-ext.d.mts.map +1 -1
- package/dist/functions/assert-ext.mjs +17 -12
- package/dist/functions/assert-ext.mjs.map +1 -1
- package/dist/functions/assert-path-exists.d.mts +2 -0
- package/dist/functions/assert-path-exists.d.mts.map +1 -1
- package/dist/functions/assert-path-exists.mjs +2 -0
- package/dist/functions/assert-path-exists.mjs.map +1 -1
- package/dist/functions/assert-repo-is-clean.d.mts +3 -2
- package/dist/functions/assert-repo-is-clean.d.mts.map +1 -1
- package/dist/functions/assert-repo-is-clean.mjs +4 -2
- package/dist/functions/assert-repo-is-clean.mjs.map +1 -1
- package/dist/functions/diff.d.mts +2 -6
- package/dist/functions/diff.d.mts.map +1 -1
- package/dist/functions/diff.mjs +2 -6
- package/dist/functions/diff.mjs.map +1 -1
- package/dist/functions/exec-async.d.mts +1 -0
- package/dist/functions/exec-async.d.mts.map +1 -1
- package/dist/functions/exec-async.mjs +2 -0
- package/dist/functions/exec-async.mjs.map +1 -1
- package/dist/functions/format.d.mts +10 -3
- package/dist/functions/format.d.mts.map +1 -1
- package/dist/functions/format.mjs +10 -3
- package/dist/functions/format.mjs.map +1 -1
- package/dist/functions/gen-index.d.mts +19 -6
- package/dist/functions/gen-index.d.mts.map +1 -1
- package/dist/functions/gen-index.mjs +63 -42
- package/dist/functions/gen-index.mjs.map +1 -1
- package/dist/functions/should-run.d.mts +8 -5
- package/dist/functions/should-run.d.mts.map +1 -1
- package/dist/functions/should-run.mjs +8 -5
- package/dist/functions/should-run.mjs.map +1 -1
- package/dist/functions/workspace-utils/execute-parallel.d.mts +11 -6
- package/dist/functions/workspace-utils/execute-parallel.d.mts.map +1 -1
- package/dist/functions/workspace-utils/execute-parallel.mjs +50 -38
- package/dist/functions/workspace-utils/execute-parallel.mjs.map +1 -1
- package/dist/functions/workspace-utils/get-workspace-packages.d.mts +7 -4
- package/dist/functions/workspace-utils/get-workspace-packages.d.mts.map +1 -1
- package/dist/functions/workspace-utils/get-workspace-packages.mjs +7 -4
- package/dist/functions/workspace-utils/get-workspace-packages.mjs.map +1 -1
- package/dist/functions/workspace-utils/run-cmd-in-parallel.d.mts +7 -3
- package/dist/functions/workspace-utils/run-cmd-in-parallel.d.mts.map +1 -1
- package/dist/functions/workspace-utils/run-cmd-in-parallel.mjs +9 -5
- package/dist/functions/workspace-utils/run-cmd-in-parallel.mjs.map +1 -1
- package/dist/functions/workspace-utils/run-cmd-in-stages.d.mts +10 -6
- package/dist/functions/workspace-utils/run-cmd-in-stages.d.mts.map +1 -1
- package/dist/functions/workspace-utils/run-cmd-in-stages.mjs +12 -8
- package/dist/functions/workspace-utils/run-cmd-in-stages.mjs.map +1 -1
- package/dist/globals.d.mts +1 -0
- package/dist/node-global.d.mts.map +1 -1
- package/dist/node-global.mjs +1 -0
- package/dist/node-global.mjs.map +1 -1
- package/package.json +19 -8
- package/src/functions/assert-ext.mts +38 -19
- package/src/functions/assert-path-exists.mts +2 -0
- package/src/functions/assert-repo-is-clean.mts +4 -2
- package/src/functions/diff.mts +2 -6
- package/src/functions/diff.test.mts +31 -24
- package/src/functions/exec-async.mts +2 -0
- package/src/functions/format.mts +10 -3
- package/src/functions/format.test.mts +8 -4
- package/src/functions/gen-index.mts +146 -62
- package/src/functions/should-run.mts +8 -5
- package/src/functions/workspace-utils/execute-parallel.mts +52 -39
- package/src/functions/workspace-utils/get-workspace-packages.mts +7 -4
- package/src/functions/workspace-utils/run-cmd-in-parallel.mts +9 -5
- package/src/functions/workspace-utils/run-cmd-in-stages.mts +12 -8
- package/src/globals.d.mts +1 -0
- package/src/node-global.mts +3 -0
- package/src/functions/gen-index.test.mts +0 -18
|
@@ -4,11 +4,15 @@ import { getWorkspacePackages } from './get-workspace-packages.mjs';
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Executes a npm script command across all workspace packages in parallel.
|
|
7
|
+
*
|
|
7
8
|
* @param options - Configuration options for the parallel execution
|
|
8
|
-
* @param options.rootPackageJsonDir - The directory containing the root
|
|
9
|
+
* @param options.rootPackageJsonDir - The directory containing the root
|
|
10
|
+
* package.json file
|
|
9
11
|
* @param options.cmd - The npm script command to execute in each package
|
|
10
|
-
* @param options.concurrency - Maximum number of packages to process
|
|
11
|
-
*
|
|
12
|
+
* @param options.concurrency - Maximum number of packages to process
|
|
13
|
+
* simultaneously (default: 3)
|
|
14
|
+
* @param options.filterWorkspacePattern - Optional function to filter packages
|
|
15
|
+
* by name
|
|
12
16
|
* @returns A promise that resolves when all packages have completed execution
|
|
13
17
|
*/
|
|
14
18
|
const runCmdInParallelAcrossWorkspaces = async ({ rootPackageJsonDir, cmd, concurrency = 3, filterWorkspacePattern, }) => {
|
|
@@ -20,8 +24,8 @@ const runCmdInParallelAcrossWorkspaces = async ({ rootPackageJsonDir, cmd, concu
|
|
|
20
24
|
await executeParallel(filteredPackages, cmd, concurrency);
|
|
21
25
|
console.log(`\n✅ ${cmd} completed successfully`);
|
|
22
26
|
}
|
|
23
|
-
catch (
|
|
24
|
-
console.error(`\n❌ ${cmd} failed:`,
|
|
27
|
+
catch (error) {
|
|
28
|
+
console.error(`\n❌ ${cmd} failed:`, error instanceof Error ? error.message : (error?.toString() ?? ''));
|
|
25
29
|
process.exit(1);
|
|
26
30
|
}
|
|
27
31
|
};
|
|
@@ -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
|
|
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,13 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
2
|
/**
|
|
3
|
-
* Executes a npm script command across all workspace packages in dependency
|
|
4
|
-
* Packages are grouped into stages where each stage contains
|
|
5
|
-
* dependencies have been completed in previous stages.
|
|
3
|
+
* Executes a npm script command across all workspace packages in dependency
|
|
4
|
+
* order stages. Packages are grouped into stages where each stage contains
|
|
5
|
+
* packages whose dependencies have been completed in previous stages.
|
|
6
|
+
*
|
|
6
7
|
* @param options - Configuration options for the staged execution
|
|
7
|
-
* @param options.rootPackageJsonDir - The directory containing the root
|
|
8
|
+
* @param options.rootPackageJsonDir - The directory containing the root
|
|
9
|
+
* package.json file
|
|
8
10
|
* @param options.cmd - The npm script command to execute in each package
|
|
9
|
-
* @param options.concurrency - Maximum number of packages to process
|
|
10
|
-
*
|
|
11
|
+
* @param options.concurrency - Maximum number of packages to process
|
|
12
|
+
* simultaneously within each stage (default: 3)
|
|
13
|
+
* @param options.filterWorkspacePattern - Optional function to filter packages
|
|
14
|
+
* by name
|
|
11
15
|
* @returns A promise that resolves when all stages have completed execution
|
|
12
16
|
*/
|
|
13
17
|
export declare const runCmdInStagesAcrossWorkspaces: ({ rootPackageJsonDir, cmd, concurrency, filterWorkspacePattern, }: Readonly<{
|
|
@@ -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
|
|
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"}
|
|
@@ -3,14 +3,18 @@ import { executeStages } 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 dependency
|
|
7
|
-
* Packages are grouped into stages where each stage contains
|
|
8
|
-
* dependencies have been completed in previous stages.
|
|
6
|
+
* Executes a npm script command across all workspace packages in dependency
|
|
7
|
+
* order stages. Packages are grouped into stages where each stage contains
|
|
8
|
+
* packages whose dependencies have been completed in previous stages.
|
|
9
|
+
*
|
|
9
10
|
* @param options - Configuration options for the staged execution
|
|
10
|
-
* @param options.rootPackageJsonDir - The directory containing the root
|
|
11
|
+
* @param options.rootPackageJsonDir - The directory containing the root
|
|
12
|
+
* package.json file
|
|
11
13
|
* @param options.cmd - The npm script command to execute in each package
|
|
12
|
-
* @param options.concurrency - Maximum number of packages to process
|
|
13
|
-
*
|
|
14
|
+
* @param options.concurrency - Maximum number of packages to process
|
|
15
|
+
* simultaneously within each stage (default: 3)
|
|
16
|
+
* @param options.filterWorkspacePattern - Optional function to filter packages
|
|
17
|
+
* by name
|
|
14
18
|
* @returns A promise that resolves when all stages have completed execution
|
|
15
19
|
*/
|
|
16
20
|
const runCmdInStagesAcrossWorkspaces = async ({ rootPackageJsonDir, cmd, concurrency = 3, filterWorkspacePattern, }) => {
|
|
@@ -22,8 +26,8 @@ const runCmdInStagesAcrossWorkspaces = async ({ rootPackageJsonDir, cmd, concurr
|
|
|
22
26
|
await executeStages(filteredPackages, cmd, concurrency);
|
|
23
27
|
console.log(`\n✅ ${cmd} completed successfully`);
|
|
24
28
|
}
|
|
25
|
-
catch (
|
|
26
|
-
console.error(`\n❌ ${cmd} failed:`,
|
|
29
|
+
catch (error) {
|
|
30
|
+
console.error(`\n❌ ${cmd} failed:`, error instanceof Error ? error.message : (error?.toString() ?? ''));
|
|
27
31
|
process.exit(1);
|
|
28
32
|
}
|
|
29
33
|
};
|
|
@@ -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
|
|
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;;;;"}
|
package/dist/globals.d.mts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-global.d.mts","sourceRoot":"","sources":["../src/node-global.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,GAAG,MAAM,kBAAkB,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"node-global.d.mts","sourceRoot":"","sources":["../src/node-global.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,GAAG,MAAM,kBAAkB,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,WAAW,CAAC;AAGnC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,MAAM,4BAA4B,CAAC;AAcrD,OAAO,CAAC,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;IACnB,MAAM,IAAI,EAAE,OAAO,OAAO,CAAC,GAAG,CAAC;IAE/B,MAAM,IAAI,EAAE,OAAO,KAAK,CAAC;IACzB,MAAM,EAAE,EAAE,OAAO,GAAG,CAAC;IACrB,MAAM,IAAI,EAAE,OAAO,KAAK,CAAC;CAC1B"}
|
package/dist/node-global.mjs
CHANGED
package/dist/node-global.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-global.mjs","sources":["../src/node-global.mts"],"sourcesContent":[null],"names":["$_"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"node-global.mjs","sources":["../src/node-global.mts"],"sourcesContent":[null],"names":["$_"],"mappings":";;;;;AAOA,MAAM,UAAU,GAAG;AACjB,IAAA,CAAC,EAAEA,CAAE;IACL,IAAI,EAAE,OAAO,CAAC,GAAG;AAEjB,IAAA,IAAI,EAAE,KAAK;AACX,IAAA,EAAE,EAAE,GAAG;AACP,IAAA,IAAI,EAAE,KAAK;CACH;AAEV;AACA,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,UAAU,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ts-repo-utils",
|
|
3
|
-
"version": "5.0
|
|
3
|
+
"version": "5.2.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript"
|
|
@@ -16,13 +16,13 @@
|
|
|
16
16
|
"exports": {
|
|
17
17
|
".": {
|
|
18
18
|
"import": {
|
|
19
|
-
"types": "./dist/
|
|
19
|
+
"types": "./dist/type.d.mts",
|
|
20
20
|
"default": "./dist/index.mjs"
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
24
|
"module": "./dist/index.mjs",
|
|
25
|
-
"types": "./dist/
|
|
25
|
+
"types": "./dist/type.d.mts",
|
|
26
26
|
"files": [
|
|
27
27
|
"src",
|
|
28
28
|
"dist",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"test:ui": "npm run z:vitest -- --ui",
|
|
48
48
|
"testw": "npm run z:vitest -- watch",
|
|
49
49
|
"tsc": "tsc --noEmit",
|
|
50
|
-
"tscw": "tsc --noEmit --watch",
|
|
50
|
+
"tscw": "tsc --noEmit --watch -p ./tsconfig.json",
|
|
51
51
|
"type-check": "tsc --noEmit",
|
|
52
52
|
"update-packages": "npx npm-check-updates -u --install always",
|
|
53
53
|
"z:vitest": "vitest --config ./configs/vitest.config.ts"
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"fast-glob": "^3.3.3",
|
|
58
58
|
"micromatch": "^4.0.8",
|
|
59
59
|
"prettier": "^3.6.2",
|
|
60
|
-
"ts-data-forge": "^3.0.
|
|
60
|
+
"ts-data-forge": "^3.0.4"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
63
|
"@eslint/js": "^9.31.0",
|
|
@@ -69,21 +69,32 @@
|
|
|
69
69
|
"@semantic-release/exec": "^7.1.0",
|
|
70
70
|
"@semantic-release/git": "^10.0.1",
|
|
71
71
|
"@semantic-release/github": "^11.0.3",
|
|
72
|
-
"@semantic-release/npm": "^12.0.
|
|
72
|
+
"@semantic-release/npm": "^12.0.2",
|
|
73
73
|
"@semantic-release/release-notes-generator": "^14.0.3",
|
|
74
74
|
"@types/node": "^24.1.0",
|
|
75
75
|
"@vitest/coverage-v8": "^3.2.4",
|
|
76
76
|
"@vitest/ui": "^3.2.4",
|
|
77
77
|
"conventional-changelog-conventionalcommits": "^9.1.0",
|
|
78
|
-
"cspell": "^9.
|
|
78
|
+
"cspell": "^9.2.0",
|
|
79
79
|
"dedent": "^1.6.0",
|
|
80
|
-
"eslint": "^9.
|
|
80
|
+
"eslint": "^9.32.0",
|
|
81
|
+
"eslint-import-resolver-typescript": "4.4.4",
|
|
82
|
+
"eslint-plugin-array-func": "5.0.2",
|
|
83
|
+
"eslint-plugin-functional": "9.0.2",
|
|
84
|
+
"eslint-plugin-import": "2.32.0",
|
|
85
|
+
"eslint-plugin-prefer-arrow-functions": "3.6.2",
|
|
86
|
+
"eslint-plugin-promise": "7.2.1",
|
|
87
|
+
"eslint-plugin-security": "3.0.1",
|
|
88
|
+
"eslint-plugin-unicorn": "60.0.0",
|
|
89
|
+
"eslint-plugin-vitest": "0.5.4",
|
|
81
90
|
"markdownlint-cli2": "^0.18.1",
|
|
91
|
+
"prettier-plugin-jsdoc": "^1.3.3",
|
|
82
92
|
"prettier-plugin-organize-imports": "^4.2.0",
|
|
83
93
|
"prettier-plugin-packagejson": "^2.5.19",
|
|
84
94
|
"rollup": "^4.45.1",
|
|
85
95
|
"semantic-release": "^24.2.7",
|
|
86
96
|
"ts-type-forge": "^2.1.1",
|
|
97
|
+
"tslib": "^2.8.1",
|
|
87
98
|
"tsx": "^4.20.3",
|
|
88
99
|
"typedoc": "^0.28.7",
|
|
89
100
|
"typedoc-plugin-markdown": "^4.7.1",
|
|
@@ -1,27 +1,32 @@
|
|
|
1
|
-
import { isString } from 'ts-data-forge';
|
|
1
|
+
import { Arr, type IMap, isString } from 'ts-data-forge';
|
|
2
2
|
import '../node-global.mjs';
|
|
3
3
|
import { assertPathExists } from './assert-path-exists.mjs';
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
* Configuration for directory extension checking.
|
|
7
|
-
*/
|
|
5
|
+
/** Configuration for directory extension checking. */
|
|
8
6
|
export type CheckExtConfig = DeepReadonly<{
|
|
9
7
|
/** Array of directory paths and their expected extensions */
|
|
10
8
|
directories: {
|
|
11
9
|
/** Directory path to check */
|
|
12
10
|
path: string;
|
|
13
11
|
|
|
14
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* Expected file extension(s) (including the dot). Can be a single extension
|
|
14
|
+
* or an array of valid extensions
|
|
15
|
+
*/
|
|
15
16
|
extension: `.${string}` | `.${string}`[];
|
|
16
17
|
|
|
17
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* Optional glob patterns to ignore (defaults to ['tsconfig.json',
|
|
20
|
+
* 'globals.d.*'])
|
|
21
|
+
*/
|
|
18
22
|
ignorePatterns?: string[];
|
|
19
23
|
}[];
|
|
20
24
|
}>;
|
|
21
25
|
|
|
22
26
|
/**
|
|
23
|
-
* Validates that all files in specified directories have the correct
|
|
24
|
-
* Exits with code 1 if any files have incorrect extensions.
|
|
27
|
+
* Validates that all files in specified directories have the correct
|
|
28
|
+
* extensions. Exits with code 1 if any files have incorrect extensions.
|
|
29
|
+
*
|
|
25
30
|
* @param config - Configuration specifying directories and expected extensions.
|
|
26
31
|
*/
|
|
27
32
|
export const assertExt = async (config: CheckExtConfig): Promise<void> => {
|
|
@@ -47,22 +52,35 @@ export const assertExt = async (config: CheckExtConfig): Promise<void> => {
|
|
|
47
52
|
if (allIncorrectFiles.length > 0) {
|
|
48
53
|
const generateErrorMessage = (): string => {
|
|
49
54
|
// Group directories by extension for a cleaner message
|
|
50
|
-
const extensionGroups
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
|
|
55
|
+
const extensionGroups: IMap<
|
|
56
|
+
string,
|
|
57
|
+
readonly Readonly<{
|
|
58
|
+
relativePath: string;
|
|
59
|
+
extKey: string;
|
|
60
|
+
}>[]
|
|
61
|
+
> = Arr.groupBy(
|
|
62
|
+
config.directories.map(({ path: dirPath, extension }) => {
|
|
63
|
+
const relativePath = path.relative(process.cwd(), dirPath);
|
|
64
|
+
const extKey = isString(extension)
|
|
65
|
+
? extension
|
|
66
|
+
: extension.join(' or ');
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
relativePath,
|
|
70
|
+
extKey,
|
|
71
|
+
};
|
|
72
|
+
}),
|
|
73
|
+
({ extKey }) => extKey,
|
|
74
|
+
);
|
|
60
75
|
|
|
61
76
|
// Generate message parts for each extension
|
|
62
77
|
const messageParts = Array.from(
|
|
63
78
|
extensionGroups.entries(),
|
|
64
79
|
([ext, dirs]) => {
|
|
65
|
-
const dirList =
|
|
80
|
+
const dirList =
|
|
81
|
+
dirs.length === 1
|
|
82
|
+
? dirs[0]?.relativePath
|
|
83
|
+
: dirs.map((d) => d.relativePath).join(', ');
|
|
66
84
|
return `${dirList} should have ${ext} extension`;
|
|
67
85
|
},
|
|
68
86
|
);
|
|
@@ -86,6 +104,7 @@ export const assertExt = async (config: CheckExtConfig): Promise<void> => {
|
|
|
86
104
|
|
|
87
105
|
/**
|
|
88
106
|
* Checks if all files in a directory have the expected extension.
|
|
107
|
+
*
|
|
89
108
|
* @param dir - The directory to check.
|
|
90
109
|
* @param expectedExtensions - The expected file extensions.
|
|
91
110
|
* @param ignorePatterns - Optional glob patterns to ignore.
|
|
@@ -2,6 +2,7 @@ import '../node-global.mjs';
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Checks if a file or directory exists.
|
|
5
|
+
*
|
|
5
6
|
* @param filePath - The path to check.
|
|
6
7
|
* @returns True if the path exists.
|
|
7
8
|
*/
|
|
@@ -16,6 +17,7 @@ export const pathExists = async (filePath: string): Promise<boolean> => {
|
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* Validates that a path exists and exits with code 1 if it doesn't.
|
|
20
|
+
*
|
|
19
21
|
* @param filePath - The path to validate.
|
|
20
22
|
* @param description - Description for error message (defaults to 'Path').
|
|
21
23
|
*/
|
|
@@ -3,6 +3,7 @@ import '../node-global.mjs';
|
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Checks if the repository has uncommitted changes.
|
|
6
|
+
*
|
|
6
7
|
* @returns True if the repo is dirty, false otherwise.
|
|
7
8
|
* @throws Error if git command fails.
|
|
8
9
|
*/
|
|
@@ -14,8 +15,8 @@ export const repoIsDirty = async (
|
|
|
14
15
|
};
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
|
-
* Checks if the repository is clean and exits with code 1 if it is dirty.
|
|
18
|
-
*
|
|
18
|
+
* Checks if the repository is clean and exits with code 1 if it is dirty. Shows
|
|
19
|
+
* git status and diff output before exiting.
|
|
19
20
|
*/
|
|
20
21
|
export const assertRepoIsClean = async (
|
|
21
22
|
options?: Readonly<{ silent?: boolean }>,
|
|
@@ -56,6 +57,7 @@ export const assertRepoIsClean = async (
|
|
|
56
57
|
|
|
57
58
|
/**
|
|
58
59
|
* Gets the git status of the repository.
|
|
60
|
+
*
|
|
59
61
|
* @returns An object containing status information.
|
|
60
62
|
*/
|
|
61
63
|
const getGitStatus = async (
|
package/src/functions/diff.mts
CHANGED
|
@@ -2,9 +2,7 @@ import { type ExecException } from 'node:child_process';
|
|
|
2
2
|
import { Result } from 'ts-data-forge';
|
|
3
3
|
import '../node-global.mjs';
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
* Get files that have been changed (git status).
|
|
7
|
-
*/
|
|
5
|
+
/** Get files that have been changed (git status). */
|
|
8
6
|
export const getUntrackedFiles = async (
|
|
9
7
|
options?: Readonly<{
|
|
10
8
|
/** @default true */
|
|
@@ -42,9 +40,7 @@ export const getUntrackedFiles = async (
|
|
|
42
40
|
return Result.ok(files);
|
|
43
41
|
};
|
|
44
42
|
|
|
45
|
-
/**
|
|
46
|
-
* Get files that differ from the specified base branch or commit
|
|
47
|
-
*/
|
|
43
|
+
/** Get files that differ from the specified base branch or commit */
|
|
48
44
|
export const getDiffFrom = async (
|
|
49
45
|
base: string,
|
|
50
46
|
options?: Readonly<{
|
|
@@ -3,12 +3,9 @@ import '../node-global.mjs';
|
|
|
3
3
|
import { getDiffFrom, getUntrackedFiles } from './diff.mjs';
|
|
4
4
|
|
|
5
5
|
describe('diff', () => {
|
|
6
|
-
//
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
afterEach(async () => {
|
|
10
|
-
// Clean up test files
|
|
11
|
-
for (const file of testFiles) {
|
|
6
|
+
// Helper function to clean up test files
|
|
7
|
+
const cleanupTestFiles = async (files: Set<string>): Promise<void> => {
|
|
8
|
+
for (const file of files) {
|
|
12
9
|
try {
|
|
13
10
|
// eslint-disable-next-line no-await-in-loop
|
|
14
11
|
await fs.rm(file, { force: true });
|
|
@@ -16,8 +13,7 @@ describe('diff', () => {
|
|
|
16
13
|
// Ignore cleanup errors
|
|
17
14
|
}
|
|
18
15
|
}
|
|
19
|
-
|
|
20
|
-
});
|
|
16
|
+
};
|
|
21
17
|
|
|
22
18
|
describe('getUntrackedFiles', () => {
|
|
23
19
|
test('should return empty array when no files are changed', async () => {
|
|
@@ -30,10 +26,12 @@ describe('diff', () => {
|
|
|
30
26
|
});
|
|
31
27
|
|
|
32
28
|
test('should detect newly created files', async () => {
|
|
29
|
+
const mut_testFiles = new Set<string>();
|
|
30
|
+
|
|
33
31
|
// Create a new file in project root
|
|
34
32
|
const testFileName = 'test-new-file.tmp';
|
|
35
33
|
const testFilePath = path.join(process.cwd(), testFileName);
|
|
36
|
-
|
|
34
|
+
mut_testFiles.add(testFilePath);
|
|
37
35
|
|
|
38
36
|
await fs.writeFile(testFilePath, 'test content');
|
|
39
37
|
|
|
@@ -42,42 +40,51 @@ describe('diff', () => {
|
|
|
42
40
|
expect(Result.isOk(result)).toBe(true);
|
|
43
41
|
if (Result.isOk(result)) {
|
|
44
42
|
const files = result.value;
|
|
45
|
-
expect(files.
|
|
43
|
+
expect(files).toContain(testFileName);
|
|
46
44
|
}
|
|
45
|
+
|
|
46
|
+
await cleanupTestFiles(mut_testFiles);
|
|
47
47
|
});
|
|
48
48
|
|
|
49
49
|
test('should detect modified existing files', async () => {
|
|
50
|
+
const mut_testFiles = new Set<string>();
|
|
51
|
+
|
|
50
52
|
// Use an existing file in the project that we can modify safely
|
|
51
53
|
const testFileName = 'test-modify-file.tmp';
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
+
const mut_testFilePath = path.join(process.cwd(), testFileName);
|
|
55
|
+
mut_testFiles.add(mut_testFilePath);
|
|
54
56
|
|
|
55
57
|
// Create and commit the file first
|
|
56
|
-
await fs.writeFile(
|
|
58
|
+
await fs.writeFile(mut_testFilePath, 'initial content');
|
|
57
59
|
|
|
58
60
|
// Add to git to track it
|
|
59
61
|
await $(`git add ${testFileName}`, { silent: true });
|
|
60
62
|
|
|
61
63
|
// Modify the file
|
|
62
|
-
await fs.writeFile(
|
|
64
|
+
await fs.writeFile(mut_testFilePath, 'modified content');
|
|
63
65
|
|
|
64
66
|
const result = await getUntrackedFiles({ silent: true });
|
|
65
67
|
|
|
66
68
|
expect(Result.isOk(result)).toBe(true);
|
|
67
69
|
if (Result.isOk(result)) {
|
|
68
70
|
const files = result.value;
|
|
69
|
-
expect(files.
|
|
71
|
+
expect(files).not.toContain(testFileName);
|
|
70
72
|
}
|
|
71
73
|
|
|
72
74
|
// Reset git state
|
|
73
75
|
await $(`git reset HEAD ${testFileName}`, { silent: true });
|
|
76
|
+
|
|
77
|
+
await cleanupTestFiles(mut_testFiles);
|
|
74
78
|
});
|
|
75
79
|
|
|
76
80
|
test('should detect multiple types of changes', async () => {
|
|
81
|
+
const mut_testFiles = new Set<string>();
|
|
82
|
+
|
|
77
83
|
// Create multiple test files
|
|
78
84
|
const newFile = path.join(process.cwd(), 'test-new-file.tmp');
|
|
79
85
|
const modifyFile = path.join(process.cwd(), 'test-modify-file.tmp');
|
|
80
|
-
|
|
86
|
+
mut_testFiles.add(newFile);
|
|
87
|
+
mut_testFiles.add(modifyFile);
|
|
81
88
|
|
|
82
89
|
// Create new file
|
|
83
90
|
await fs.writeFile(newFile, 'new file content');
|
|
@@ -94,14 +101,14 @@ describe('diff', () => {
|
|
|
94
101
|
expect(Result.isOk(result)).toBe(true);
|
|
95
102
|
if (Result.isOk(result)) {
|
|
96
103
|
const files = result.value;
|
|
97
|
-
expect(files.
|
|
98
|
-
expect(files.
|
|
99
|
-
false,
|
|
100
|
-
);
|
|
104
|
+
expect(files).toContain('test-new-file.tmp');
|
|
105
|
+
expect(files).not.toContain('test-modify-file.tmp');
|
|
101
106
|
}
|
|
102
107
|
|
|
103
108
|
// Reset git state
|
|
104
109
|
await $(`git reset HEAD test-modify-file.tmp`, { silent: true });
|
|
110
|
+
|
|
111
|
+
await cleanupTestFiles(mut_testFiles);
|
|
105
112
|
});
|
|
106
113
|
|
|
107
114
|
test('should exclude deleted files from results', async () => {
|
|
@@ -113,10 +120,10 @@ describe('diff', () => {
|
|
|
113
120
|
if (Result.isOk(result)) {
|
|
114
121
|
const files = result.value;
|
|
115
122
|
// Verify no deleted files are included (status 'D')
|
|
116
|
-
|
|
123
|
+
for (const file of files) {
|
|
117
124
|
expect(typeof file).toBe('string');
|
|
118
125
|
expect(file.length).toBeGreaterThan(0);
|
|
119
|
-
}
|
|
126
|
+
}
|
|
120
127
|
}
|
|
121
128
|
});
|
|
122
129
|
|
|
@@ -137,11 +144,11 @@ describe('diff', () => {
|
|
|
137
144
|
const files = result.value;
|
|
138
145
|
|
|
139
146
|
// Each file should be a non-empty string
|
|
140
|
-
|
|
147
|
+
for (const file of files) {
|
|
141
148
|
expect(typeof file).toBe('string');
|
|
142
149
|
expect(file.trim()).toBe(file); // No leading/trailing whitespace
|
|
143
150
|
expect(file.length).toBeGreaterThan(0);
|
|
144
|
-
}
|
|
151
|
+
}
|
|
145
152
|
}
|
|
146
153
|
});
|
|
147
154
|
|
|
@@ -3,6 +3,7 @@ import { Result } from 'ts-data-forge';
|
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Executes a shell command asynchronously.
|
|
6
|
+
*
|
|
6
7
|
* @param cmd - The command to execute.
|
|
7
8
|
* @param options - Optional configuration for command execution.
|
|
8
9
|
* @returns A promise that resolves with the command result.
|
|
@@ -22,6 +23,7 @@ export const $ = (
|
|
|
22
23
|
return new Promise((resolve) => {
|
|
23
24
|
const execOptions = { timeout };
|
|
24
25
|
|
|
26
|
+
// eslint-disable-next-line security/detect-child-process
|
|
25
27
|
exec(cmd, execOptions, (error, stdout, stderr) => {
|
|
26
28
|
if (!silent) {
|
|
27
29
|
if (stdout !== '') {
|
package/src/functions/format.mts
CHANGED
|
@@ -5,6 +5,7 @@ import { getDiffFrom, getUntrackedFiles } from './diff.mjs';
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Format a list of files using Prettier
|
|
8
|
+
*
|
|
8
9
|
* @param files - Array of file paths to format
|
|
9
10
|
* @returns 'ok' if successful, 'err' if any errors occurred
|
|
10
11
|
*/
|
|
@@ -74,6 +75,7 @@ export const formatFilesList = async (
|
|
|
74
75
|
|
|
75
76
|
/**
|
|
76
77
|
* Format files matching the given glob pattern using Prettier
|
|
78
|
+
*
|
|
77
79
|
* @param pathGlob - Glob pattern to match files
|
|
78
80
|
* @returns 'ok' if successful, 'err' if any errors occurred
|
|
79
81
|
*/
|
|
@@ -107,6 +109,7 @@ export const formatFiles = async (
|
|
|
107
109
|
|
|
108
110
|
/**
|
|
109
111
|
* Format only files that have been changed (git status)
|
|
112
|
+
*
|
|
110
113
|
* @param options - Options for formatting
|
|
111
114
|
* @returns 'ok' if successful, 'err' if any errors occurred
|
|
112
115
|
*/
|
|
@@ -169,10 +172,14 @@ export const formatUntracked = async (
|
|
|
169
172
|
|
|
170
173
|
/**
|
|
171
174
|
* Format only files that differ from the specified base branch or commit
|
|
172
|
-
*
|
|
175
|
+
*
|
|
176
|
+
* @param base - Base branch name or commit hash to compare against (defaults to
|
|
177
|
+
* 'main')
|
|
173
178
|
* @param options - Options for formatting
|
|
174
|
-
* @param options.includeUntracked - Include untracked files in addition to diff
|
|
175
|
-
*
|
|
179
|
+
* @param options.includeUntracked - Include untracked files in addition to diff
|
|
180
|
+
* files (default is true)
|
|
181
|
+
* @param options.silent - Silent mode to suppress command output (default is
|
|
182
|
+
* false)
|
|
176
183
|
* @returns 'ok' if successful, 'err' if any errors occurred
|
|
177
184
|
*/
|
|
178
185
|
export const formatDiffFrom = async (
|
|
@@ -27,6 +27,7 @@ describe('formatFiles', () => {
|
|
|
27
27
|
fs.readFile(filePath, 'utf8');
|
|
28
28
|
|
|
29
29
|
test('should format files matching glob pattern', async () => {
|
|
30
|
+
vi.clearAllMocks();
|
|
30
31
|
// Setup test directory
|
|
31
32
|
await fs.mkdir(testDir, { recursive: true });
|
|
32
33
|
|
|
@@ -84,6 +85,7 @@ describe('formatFiles', () => {
|
|
|
84
85
|
});
|
|
85
86
|
|
|
86
87
|
test('should return ok when no files match pattern', async () => {
|
|
88
|
+
vi.clearAllMocks();
|
|
87
89
|
const result = await formatFiles('/non-existent-path/*.ts', {
|
|
88
90
|
silent: true,
|
|
89
91
|
});
|
|
@@ -91,6 +93,7 @@ describe('formatFiles', () => {
|
|
|
91
93
|
});
|
|
92
94
|
|
|
93
95
|
test('should handle nested directories with glob pattern', async () => {
|
|
96
|
+
vi.clearAllMocks();
|
|
94
97
|
// Setup test directory with nested structure
|
|
95
98
|
await fs.mkdir(path.join(testDir, 'src', 'utils'), { recursive: true });
|
|
96
99
|
|
|
@@ -143,6 +146,7 @@ describe('formatFilesList', () => {
|
|
|
143
146
|
fs.readFile(filePath, 'utf8');
|
|
144
147
|
|
|
145
148
|
test('should format a list of files', async () => {
|
|
149
|
+
vi.clearAllMocks();
|
|
146
150
|
await fs.mkdir(testDir, { recursive: true });
|
|
147
151
|
|
|
148
152
|
try {
|
|
@@ -189,6 +193,7 @@ describe('formatFilesList', () => {
|
|
|
189
193
|
});
|
|
190
194
|
|
|
191
195
|
test('should return ok for empty file list', async () => {
|
|
196
|
+
vi.clearAllMocks();
|
|
192
197
|
const result = await formatFilesList([], {
|
|
193
198
|
silent: true,
|
|
194
199
|
});
|
|
@@ -211,11 +216,8 @@ describe('formatDiffFrom', () => {
|
|
|
211
216
|
const readTestFile = async (filePath: string): Promise<string> =>
|
|
212
217
|
fs.readFile(filePath, 'utf8');
|
|
213
218
|
|
|
214
|
-
beforeEach(() => {
|
|
215
|
-
vi.clearAllMocks();
|
|
216
|
-
});
|
|
217
|
-
|
|
218
219
|
test('should format files from diff', async () => {
|
|
220
|
+
vi.clearAllMocks();
|
|
219
221
|
await fs.mkdir(testDir, { recursive: true });
|
|
220
222
|
|
|
221
223
|
try {
|
|
@@ -250,6 +252,7 @@ describe('formatDiffFrom', () => {
|
|
|
250
252
|
});
|
|
251
253
|
|
|
252
254
|
test('should include untracked files when option is set', async () => {
|
|
255
|
+
vi.clearAllMocks();
|
|
253
256
|
await fs.mkdir(testDir, { recursive: true });
|
|
254
257
|
|
|
255
258
|
try {
|
|
@@ -302,6 +305,7 @@ describe('formatDiffFrom', () => {
|
|
|
302
305
|
});
|
|
303
306
|
|
|
304
307
|
test('should deduplicate files when including untracked', async () => {
|
|
308
|
+
vi.clearAllMocks();
|
|
305
309
|
await fs.mkdir(testDir, { recursive: true });
|
|
306
310
|
|
|
307
311
|
try {
|