ts-repo-utils 10.1.8 → 10.3.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/README.md +73 -11
- package/dist/cmd/assert-repo-is-clean.mjs +0 -0
- package/dist/cmd/check-should-run-type-checks.mjs +0 -0
- package/dist/cmd/check-should-run.d.mts +3 -0
- package/dist/cmd/check-should-run.d.mts.map +1 -0
- package/dist/cmd/check-should-run.mjs +44 -0
- package/dist/cmd/check-should-run.mjs.map +1 -0
- package/dist/cmd/format-diff-from.mjs +0 -0
- package/dist/cmd/format-uncommitted.mjs +0 -0
- package/dist/cmd/gen-index-ts.mjs +1 -0
- package/dist/cmd/gen-index-ts.mjs.map +1 -1
- package/dist/entry-point.mjs +2 -1
- package/dist/entry-point.mjs.map +1 -1
- package/dist/functions/index.mjs +2 -1
- package/dist/functions/index.mjs.map +1 -1
- package/dist/functions/should-run.d.mts +62 -1
- package/dist/functions/should-run.d.mts.map +1 -1
- package/dist/functions/should-run.mjs +38 -34
- package/dist/functions/should-run.mjs.map +1 -1
- package/dist/functions/workspace-utils/get-workspace-packages.d.mts +5 -2
- package/dist/functions/workspace-utils/get-workspace-packages.d.mts.map +1 -1
- package/dist/functions/workspace-utils/get-workspace-packages.mjs +9 -11
- package/dist/functions/workspace-utils/get-workspace-packages.mjs.map +1 -1
- package/dist/functions/workspace-utils/index.mjs +1 -0
- package/dist/functions/workspace-utils/index.mjs.map +1 -1
- package/dist/functions/workspace-utils/run-cmd-in-stages.d.mts +7 -1
- package/dist/functions/workspace-utils/run-cmd-in-stages.d.mts.map +1 -1
- package/dist/functions/workspace-utils/run-cmd-in-stages.mjs +7 -2
- package/dist/functions/workspace-utils/run-cmd-in-stages.mjs.map +1 -1
- package/dist/functions/workspace-utils/types.d.mts +13 -0
- package/dist/functions/workspace-utils/types.d.mts.map +1 -1
- package/dist/functions/workspace-utils/types.mjs +6 -0
- package/dist/functions/workspace-utils/types.mjs.map +1 -1
- package/dist/index.mjs +2 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +60 -81
- package/src/cmd/assert-repo-is-clean.mts +0 -0
- package/src/cmd/check-should-run-type-checks.mts +0 -0
- package/src/cmd/check-should-run.mts +45 -0
- package/src/cmd/format-diff-from.mts +0 -0
- package/src/cmd/format-uncommitted.mts +0 -0
- package/src/cmd/gen-index-ts.mts +0 -0
- package/src/functions/should-run.mts +134 -59
- package/src/functions/should-run.test.mts +196 -0
- package/src/functions/workspace-utils/get-workspace-packages.mts +17 -16
- package/src/functions/workspace-utils/run-cmd-in-stages.mts +11 -1
- package/src/functions/workspace-utils/types.mts +20 -0
package/README.md
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
- API reference: <https://noshiro-pf.github.io/ts-repo-utils/>
|
|
8
8
|
|
|
9
9
|
[](https://www.npmjs.com/package/ts-repo-utils)
|
|
10
|
-
[](
|
|
11
|
-
[](https://github.com/noshiro-pf/mono/blob/main/libs/ts-repo-utils/LICENSE)
|
|
11
|
+
[](https://codecov.io/gh/noshiro-pf/mono)
|
|
12
12
|
|
|
13
13
|
Utilities for TypeScript Repositories.
|
|
14
14
|
|
|
@@ -161,10 +161,56 @@ npm exec -- gen-index-ts ./src --target-ext .mts --index-ext .mts --export-ext .
|
|
|
161
161
|
- `--min-depth` - Minimum depth to start generating index files (default: 0)
|
|
162
162
|
- `--silent` - Suppress output messages (optional)
|
|
163
163
|
|
|
164
|
+
### `check-should-run`
|
|
165
|
+
|
|
166
|
+
Checks whether a CI step should run, based on which files differ from the base branch. Reports `false` when every changed file matches one of the `--paths-ignore` patterns, so a step can be skipped when nothing it checks has changed.
|
|
167
|
+
|
|
168
|
+
Prefer this over a workflow-level `paths-ignore` trigger filter: a workflow that a path filter skips never reports a status check, so a pull request that changed only the filtered paths waits forever on a required check that never arrives. Gating the individual steps keeps the workflow running — and reporting — while doing no work.
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
# Skip when the diff only touches a directory nothing checks
|
|
172
|
+
npm exec -- check-should-run --paths-ignore 'experimental/'
|
|
173
|
+
|
|
174
|
+
# Several patterns, and a custom base branch
|
|
175
|
+
npm exec -- check-should-run \
|
|
176
|
+
--paths-ignore 'experimental/' \
|
|
177
|
+
--paths-ignore 'docs/' \
|
|
178
|
+
--paths-ignore '**.md' \
|
|
179
|
+
--base-branch origin/develop
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
```yaml
|
|
183
|
+
# Example in GitHub Actions
|
|
184
|
+
- name: Check diff
|
|
185
|
+
id: check_diff
|
|
186
|
+
run: npm exec -- check-should-run --paths-ignore 'experimental/'
|
|
187
|
+
|
|
188
|
+
- name: Run the checks
|
|
189
|
+
if: steps.check_diff.outputs.should_run == 'true'
|
|
190
|
+
run: npm run check
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**Options:**
|
|
194
|
+
|
|
195
|
+
- `--paths-ignore` - Patterns whose files do not affect the gated step (optional, can be specified multiple times). Matched with [micromatch](https://github.com/micromatch/micromatch) (with `dot: true`) against paths relative to the repository root, with one shorthand: a pattern ending with `/` is a directory prefix.
|
|
196
|
+
- Exact file matches: `.editorconfig`
|
|
197
|
+
- Directory prefixes: `docs/` (the same as `docs/**`)
|
|
198
|
+
- Globs: `**.md`, `libs/*/samples/**`
|
|
199
|
+
- Default: `[]` — nothing is ignored, so the step always runs when anything changed
|
|
200
|
+
- `--base-branch` - Base branch to compare against for determining changed files (default: `origin/main`)
|
|
201
|
+
|
|
202
|
+
An empty diff reads as "nothing changed", so it reports `should_run=false`. On a push to the base branch itself the diff against that branch is empty for that reason; pass the commit the branch pointed at before the push as `--base-branch` there.
|
|
203
|
+
|
|
204
|
+
**GitHub Actions Integration:**
|
|
205
|
+
|
|
206
|
+
When running in GitHub Actions, the command appends `should_run=true` or `should_run=false` to the file named by the `GITHUB_OUTPUT` environment variable, which can be used in subsequent steps.
|
|
207
|
+
|
|
164
208
|
### `check-should-run-type-checks`
|
|
165
209
|
|
|
166
210
|
Checks whether TypeScript type checks should run based on file changes from the base branch. Optimizes CI/CD pipelines by skipping type checks when only non-TypeScript files have changed. The determination of "non-TypeScript files" is based on configurable ignore patterns, which can be specified using the `--paths-ignore` option.
|
|
167
211
|
|
|
212
|
+
This is [`check-should-run`](#check-should-run) with a default ignore list of the files a TypeScript project typically has but never type-checks. For a step that is not a type check, use `check-should-run` and state its paths.
|
|
213
|
+
|
|
168
214
|
```bash
|
|
169
215
|
# Basic usage (compares against origin/main)
|
|
170
216
|
npm exec -- check-should-run-type-checks
|
|
@@ -193,11 +239,11 @@ npm exec -- check-should-run-type-checks \
|
|
|
193
239
|
|
|
194
240
|
**Options:**
|
|
195
241
|
|
|
196
|
-
- `--paths-ignore` - Patterns to ignore when checking if type checks should run (optional, can be specified multiple times)
|
|
242
|
+
- `--paths-ignore` - Patterns to ignore when checking if type checks should run (optional, can be specified multiple times). Matched as described for [`check-should-run`](#check-should-run); passing it replaces the default list rather than adding to it.
|
|
197
243
|
- Supports exact file matches: `.cspell.config.yaml`
|
|
198
244
|
- Directory prefixes: `docs/` (matches any file in docs directory)
|
|
199
245
|
- File extensions: `**.md` (matches any markdown file)
|
|
200
|
-
- Default: `['LICENSE', '.editorconfig', '.gitignore', '.cspell.config.yaml', '.markdownlint-cli2.mjs', '.npmignore', '.prettierignore', '.prettierrc', 'docs/', '**.md', '**.txt']`
|
|
246
|
+
- Default: `['LICENSE', '.editorconfig', '.gitignore', '.cspell.json', '.cspell.config.yaml', '.markdownlint-cli2.mjs', '.npmignore', '.prettierignore', '.prettierrc', 'docs/', '**.md', '**.txt']`
|
|
201
247
|
- `--base-branch` - Base branch to compare against for determining changed files (default: `origin/main`)
|
|
202
248
|
|
|
203
249
|
**GitHub Actions Integration:**
|
|
@@ -498,13 +544,27 @@ type Ret = Result<
|
|
|
498
544
|
|
|
499
545
|
#### Build Optimization Utilities
|
|
500
546
|
|
|
547
|
+
##### `checkShouldRun(options?): Promise<boolean>`
|
|
548
|
+
|
|
549
|
+
Checks whether a CI step should run, based on which files differ from the base branch. Reports `false` when every changed file matches one of the ignored patterns.
|
|
550
|
+
(Function version of the `check-should-run` command)
|
|
551
|
+
|
|
501
552
|
##### `checkShouldRunTypeChecks(options?): Promise<boolean>`
|
|
502
553
|
|
|
503
|
-
|
|
554
|
+
`checkShouldRun` with a default ignore list of the files a TypeScript project typically has but never type-checks. Optimizes CI/CD pipelines by skipping type checks when only non-TypeScript files have changed.
|
|
504
555
|
(Function version of the `check-should-run-type-checks` command)
|
|
505
556
|
|
|
506
557
|
```tsx
|
|
507
|
-
import { $, checkShouldRunTypeChecks } from 'ts-repo-utils';
|
|
558
|
+
import { $, checkShouldRun, checkShouldRunTypeChecks } from 'ts-repo-utils';
|
|
559
|
+
|
|
560
|
+
// Gate any step on the paths it cares about
|
|
561
|
+
const shouldRunStyleChecks = await checkShouldRun({
|
|
562
|
+
pathsIgnore: ['experimental/'],
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
if (shouldRunStyleChecks) {
|
|
566
|
+
await $('npm run fmt:check');
|
|
567
|
+
}
|
|
508
568
|
|
|
509
569
|
// Use default settings (compare against origin/main)
|
|
510
570
|
const shouldRun = await checkShouldRunTypeChecks();
|
|
@@ -520,15 +580,17 @@ const shouldRun2 = await checkShouldRunTypeChecks({
|
|
|
520
580
|
});
|
|
521
581
|
```
|
|
522
582
|
|
|
523
|
-
**Options:**
|
|
583
|
+
**Options (both functions):**
|
|
524
584
|
|
|
525
|
-
- `pathsIgnore?` - Patterns to
|
|
585
|
+
- `pathsIgnore?` - Patterns whose files do not affect the gated step. Matched with [micromatch](https://github.com/micromatch/micromatch) (with `dot: true`) against paths relative to the repository root, with a trailing `/` as the shorthand for a directory:
|
|
526
586
|
- Exact file matches: `.cspell.config.yaml`
|
|
527
|
-
- Directory prefixes: `docs/` (
|
|
528
|
-
-
|
|
529
|
-
- Default: `['LICENSE', '.editorconfig', '.gitignore', '.cspell.config.yaml', '.markdownlint-cli2.mjs', '.npmignore', '.prettierignore', '.prettierrc', 'docs/', '**.md', '**.txt']`
|
|
587
|
+
- Directory prefixes: `docs/` (the same as `docs/**`)
|
|
588
|
+
- Globs: `**.md` (matches any markdown file), `libs/*/samples/**`
|
|
589
|
+
- Default: `[]` for `checkShouldRun`; for `checkShouldRunTypeChecks`, `['LICENSE', '.editorconfig', '.gitignore', '.cspell.json', '.cspell.config.yaml', '.markdownlint-cli2.mjs', '.npmignore', '.prettierignore', '.prettierrc', 'docs/', '**.md', '**.txt']` — passing the option replaces that list rather than adding to it
|
|
530
590
|
- `baseBranch?` - Base branch to compare against (default: `origin/main`)
|
|
531
591
|
|
|
592
|
+
Both return whether the step should run, and, in GitHub Actions, append `should_run=<result>` to the file named by `GITHUB_OUTPUT`. An empty diff reads as "nothing changed" and so returns `false`.
|
|
593
|
+
|
|
532
594
|
### Code Formatting Utilities
|
|
533
595
|
|
|
534
596
|
#### `formatFilesGlob(pathGlob: string, options?): Promise<Result<undefined, unknown>>`
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-should-run.d.mts","sourceRoot":"","sources":["../../src/cmd/check-should-run.mts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import * as cmd from 'cmd-ts';
|
|
3
|
+
import { Arr } from 'ts-data-forge';
|
|
4
|
+
import 'node:path';
|
|
5
|
+
import 'node:fs/promises';
|
|
6
|
+
import 'fast-glob';
|
|
7
|
+
import 'node:child_process';
|
|
8
|
+
import 'prettier';
|
|
9
|
+
import 'micromatch';
|
|
10
|
+
import 'node:fs';
|
|
11
|
+
import 'node:url';
|
|
12
|
+
import { checkShouldRun } from '../functions/should-run.mjs';
|
|
13
|
+
import '@sindresorhus/is';
|
|
14
|
+
|
|
15
|
+
const cmdDef = cmd.command({
|
|
16
|
+
name: "check-should-run-cli",
|
|
17
|
+
version: "10.2.0",
|
|
18
|
+
args: {
|
|
19
|
+
pathsIgnore: cmd.multioption({
|
|
20
|
+
long: "paths-ignore",
|
|
21
|
+
type: cmd.optional(cmd.array(cmd.string)),
|
|
22
|
+
description: 'Patterns whose files do not affect the gated step. Matched with micromatch against repository-relative paths, with a trailing "/" as the shorthand for a directory (e.g. "experimental/", ".editorconfig", "**.md"). Defaults to ignoring nothing.'
|
|
23
|
+
}),
|
|
24
|
+
baseBranch: cmd.option({
|
|
25
|
+
long: "base-branch",
|
|
26
|
+
type: cmd.optional(cmd.string),
|
|
27
|
+
description: 'Base branch to compare against for determining changed files. Defaults to "origin/main"'
|
|
28
|
+
})
|
|
29
|
+
},
|
|
30
|
+
handler: (args) => {
|
|
31
|
+
main(args).catch((error) => {
|
|
32
|
+
console.error("An error occurred:", error);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
const main = async (args) => {
|
|
38
|
+
await checkShouldRun({
|
|
39
|
+
pathsIgnore: args.pathsIgnore,
|
|
40
|
+
baseBranch: args.baseBranch
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
await cmd.run(cmdDef, Arr.skip(process.argv, 2));
|
|
44
|
+
//# sourceMappingURL=check-should-run.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-should-run.mjs","sources":["../../src/cmd/check-should-run.mts"],"sourcesContent":["#!/usr/bin/env node\n\nimport * as cmd from 'cmd-ts';\nimport { Arr } from 'ts-data-forge';\nimport { checkShouldRun } from '../functions/index.mjs';\n\nconst cmdDef = cmd.command({\n name: 'check-should-run-cli',\n version: '10.2.0',\n args: {\n pathsIgnore: cmd.multioption({\n long: 'paths-ignore',\n type: cmd.optional(cmd.array(cmd.string)),\n description:\n 'Patterns whose files do not affect the gated step. Matched with micromatch against repository-relative paths, with a trailing \"/\" as the shorthand for a directory (e.g. \"experimental/\", \".editorconfig\", \"**.md\"). Defaults to ignoring nothing.',\n }),\n baseBranch: cmd.option({\n long: 'base-branch',\n type: cmd.optional(cmd.string),\n description:\n 'Base branch to compare against for determining changed files. Defaults to \"origin/main\"',\n }),\n },\n handler: (args) => {\n main(args).catch((error: unknown) => {\n console.error('An error occurred:', error);\n\n process.exit(1);\n });\n },\n});\n\nconst main = async (\n args: Readonly<{\n pathsIgnore?: readonly string[];\n baseBranch?: string;\n }>,\n): Promise<void> => {\n await checkShouldRun({\n pathsIgnore: args.pathsIgnore,\n baseBranch: args.baseBranch,\n });\n};\n\nawait cmd.run(cmdDef, Arr.skip(process.argv, 2));\n"],"names":[],"mappings":";;;;;;;;;;;;;;AAMA,MAAM,MAAA,GAAS,IAAI,OAAA,CAAQ;AAAA,EACzB,IAAA,EAAM,sBAAA;AAAA,EACN,OAAA,EAAS,QAAA;AAAA,EACT,IAAA,EAAM;AAAA,IACJ,WAAA,EAAa,IAAI,WAAA,CAAY;AAAA,MAC3B,IAAA,EAAM,cAAA;AAAA,MACN,MAAM,GAAA,CAAI,QAAA,CAAS,IAAI,KAAA,CAAM,GAAA,CAAI,MAAM,CAAC,CAAA;AAAA,MACxC,WAAA,EACE;AAAA,KACH,CAAA;AAAA,IACD,UAAA,EAAY,IAAI,MAAA,CAAO;AAAA,MACrB,IAAA,EAAM,aAAA;AAAA,MACN,IAAA,EAAM,GAAA,CAAI,QAAA,CAAS,GAAA,CAAI,MAAM,CAAA;AAAA,MAC7B,WAAA,EACE;AAAA,KACH;AAAA,GACH;AAAA,EACA,OAAA,EAAS,CAAC,IAAA,KAAS;AACjB,IAAA,IAAA,CAAK,IAAI,CAAA,CAAE,KAAA,CAAM,CAAC,KAAA,KAAmB;AACnC,MAAA,OAAA,CAAQ,KAAA,CAAM,sBAAsB,KAAK,CAAA;AAEzC,MAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,IAChB,CAAC,CAAA;AAAA,EACH;AACF,CAAC,CAAA;AAED,MAAM,IAAA,GAAO,OACX,IAAA,KAIkB;AAClB,EAAA,MAAM,cAAA,CAAe;AAAA,IACnB,aAAa,IAAA,CAAK,WAAA;AAAA,IAClB,YAAY,IAAA,CAAK;AAAA,GAClB,CAAA;AACH,CAAA;AAEA,MAAM,GAAA,CAAI,IAAI,MAAA,EAAQ,GAAA,CAAI,KAAK,OAAA,CAAQ,IAAA,EAAM,CAAC,CAAC,CAAA"}
|
|
File without changes
|
|
File without changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gen-index-ts.mjs","sources":["../../src/cmd/gen-index-ts.mts"],"sourcesContent":["#!/usr/bin/env node\n\n/* transformer-ignore convert-to-readonly */\n\nimport * as cmd from 'cmd-ts';\nimport { Arr, expectType } from 'ts-data-forge';\n// eslint-disable-next-line import-x/no-internal-modules, import-x/extensions\nimport { type InputOf, type OutputOf } from 'cmd-ts/dist/esm/from.js';\nimport { type NonEmptyArray } from 'ts-type-forge';\nimport { genIndex } from '../functions/index.mjs';\n\ntype Ext = `.${string}`;\n\nconst extensionType = cmd.extendType(cmd.string, {\n from: (s) => {\n if (!s.startsWith('.')) {\n throw new Error(`ext should start with '.'`);\n }\n\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return Promise.resolve(s as Ext);\n },\n});\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst nonEmptyArray = <T extends cmd.Type<any, any>>(\n t: T,\n commandName: string,\n): cmd.Type<readonly InputOf<T>[], NonEmptyArray<OutputOf<T>>> =>\n cmd.extendType(\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n cmd.array(t) as cmd.Type<readonly InputOf<T>[], OutputOf<T>[]>,\n {\n from: (arr) => {\n if (Arr.isEmpty(arr)) {\n throw new Error(\n `No value provided for --${commandName}. At least one value is required.`,\n );\n }\n\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return Promise.resolve(arr as unknown as NonEmptyArray<OutputOf<T>>);\n },\n },\n );\n\nconst cmdDef = cmd.command({\n name: 'gen-index-ts-cli',\n version: '10.1.8',\n args: {\n // required args\n targetDirectory: cmd.positional({\n type: cmd.string,\n displayName: 'target-directory',\n description:\n 'Directory where the index file will be generated (Comma-separated list can be used)',\n }),\n\n targetExtensions: cmd.multioption({\n long: 'target-ext',\n type: nonEmptyArray(extensionType, 'target-ext'),\n description: 'File extensions to include in the index file',\n }),\n indexFileExtension: cmd.option({\n long: 'index-ext',\n type: extensionType,\n description: 'Extension of the index file to be generated',\n }),\n exportStatementExtension: cmd.option({\n long: 'export-ext',\n type: cmd.union([\n extensionType,\n cmd.extendType(cmd.string, {\n from: (s) => {\n if (s !== 'none') {\n throw new Error(\n `export-ext should be 'none' or a valid extension`,\n );\n }\n\n return Promise.resolve('none' as const);\n },\n }),\n ]),\n description: 'Extension of the export statements in the index file',\n }),\n\n // optional args\n exclude: cmd.multioption({\n long: 'exclude',\n type: cmd.optional(cmd.array(cmd.string)),\n description:\n 'Glob patterns of files to exclude from the index file (e.g., \"*.d.mts\", \"*.test.mts\")',\n }),\n formatCommand: cmd.option({\n long: 'fmt',\n type: cmd.optional(cmd.string),\n description:\n 'Command to format after generating the index file (e.g., \"npm run fmt\")',\n }),\n silent: cmd.flag({\n long: 'silent',\n type: cmd.optional(cmd.boolean),\n description: 'If true, suppresses output messages (default: false)',\n }),\n minDepth: cmd.option({\n long: 'min-depth',\n type: cmd.optional(cmd.number),\n description: 'Minimum depth to start generating index files (default: 0)',\n }),\n },\n handler: (args) => {\n expectType<typeof args.targetDirectory, string>('=');\n\n expectType<typeof args.targetExtensions, NonEmptyArray<Ext>>('=');\n\n expectType<typeof args.exportStatementExtension, Ext | 'none'>('=');\n\n expectType<typeof args.indexFileExtension, Ext>('=');\n\n expectType<typeof args.exclude, string[] | undefined>('=');\n\n expectType<typeof args.formatCommand, string | undefined>('=');\n\n expectType<typeof args.silent, boolean | undefined>('=');\n\n expectType<typeof args.minDepth, number | undefined>('=');\n\n main(args).catch((error: unknown) => {\n console.error('An error occurred:', error);\n\n process.exit(1);\n });\n },\n});\n\nconst main = async ({\n targetDirectory,\n targetExtensions,\n exportStatementExtension,\n indexFileExtension,\n exclude,\n formatCommand,\n silent,\n minDepth,\n}: Readonly<{\n targetDirectory: string;\n targetExtensions: readonly Ext[];\n exportStatementExtension: Ext | 'none';\n indexFileExtension: Ext;\n exclude?: readonly string[] | undefined;\n formatCommand?: string | undefined;\n silent?: boolean | undefined;\n minDepth?: number | undefined;\n}>): Promise<void> => {\n await genIndex({\n targetDirectory: targetDirectory.includes(',')\n ? targetDirectory.split(',').map((dir) => dir.trim())\n : targetDirectory,\n exportStatementExtension,\n targetExtensions,\n exclude,\n indexFileExtension,\n formatCommand,\n silent,\n minDepth,\n });\n};\n\nawait cmd.run(cmdDef, Arr.skip(process.argv, 2));\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"gen-index-ts.mjs","sources":["../../src/cmd/gen-index-ts.mts"],"sourcesContent":["#!/usr/bin/env node\n\n/* transformer-ignore convert-to-readonly */\n\nimport * as cmd from 'cmd-ts';\nimport { Arr, expectType } from 'ts-data-forge';\n// eslint-disable-next-line import-x/no-internal-modules, import-x/extensions\nimport { type InputOf, type OutputOf } from 'cmd-ts/dist/esm/from.js';\nimport { type NonEmptyArray } from 'ts-type-forge';\nimport { genIndex } from '../functions/index.mjs';\n\ntype Ext = `.${string}`;\n\nconst extensionType = cmd.extendType(cmd.string, {\n from: (s) => {\n if (!s.startsWith('.')) {\n throw new Error(`ext should start with '.'`);\n }\n\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return Promise.resolve(s as Ext);\n },\n});\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst nonEmptyArray = <T extends cmd.Type<any, any>>(\n t: T,\n commandName: string,\n): cmd.Type<readonly InputOf<T>[], NonEmptyArray<OutputOf<T>>> =>\n cmd.extendType(\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n cmd.array(t) as cmd.Type<readonly InputOf<T>[], OutputOf<T>[]>,\n {\n from: (arr) => {\n if (Arr.isEmpty(arr)) {\n throw new Error(\n `No value provided for --${commandName}. At least one value is required.`,\n );\n }\n\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return Promise.resolve(arr as unknown as NonEmptyArray<OutputOf<T>>);\n },\n },\n );\n\nconst cmdDef = cmd.command({\n name: 'gen-index-ts-cli',\n version: '10.1.8',\n args: {\n // required args\n targetDirectory: cmd.positional({\n type: cmd.string,\n displayName: 'target-directory',\n description:\n 'Directory where the index file will be generated (Comma-separated list can be used)',\n }),\n\n targetExtensions: cmd.multioption({\n long: 'target-ext',\n type: nonEmptyArray(extensionType, 'target-ext'),\n description: 'File extensions to include in the index file',\n }),\n indexFileExtension: cmd.option({\n long: 'index-ext',\n type: extensionType,\n description: 'Extension of the index file to be generated',\n }),\n exportStatementExtension: cmd.option({\n long: 'export-ext',\n type: cmd.union([\n extensionType,\n cmd.extendType(cmd.string, {\n from: (s) => {\n if (s !== 'none') {\n throw new Error(\n `export-ext should be 'none' or a valid extension`,\n );\n }\n\n return Promise.resolve('none' as const);\n },\n }),\n ]),\n description: 'Extension of the export statements in the index file',\n }),\n\n // optional args\n exclude: cmd.multioption({\n long: 'exclude',\n type: cmd.optional(cmd.array(cmd.string)),\n description:\n 'Glob patterns of files to exclude from the index file (e.g., \"*.d.mts\", \"*.test.mts\")',\n }),\n formatCommand: cmd.option({\n long: 'fmt',\n type: cmd.optional(cmd.string),\n description:\n 'Command to format after generating the index file (e.g., \"npm run fmt\")',\n }),\n silent: cmd.flag({\n long: 'silent',\n type: cmd.optional(cmd.boolean),\n description: 'If true, suppresses output messages (default: false)',\n }),\n minDepth: cmd.option({\n long: 'min-depth',\n type: cmd.optional(cmd.number),\n description: 'Minimum depth to start generating index files (default: 0)',\n }),\n },\n handler: (args) => {\n expectType<typeof args.targetDirectory, string>('=');\n\n expectType<typeof args.targetExtensions, NonEmptyArray<Ext>>('=');\n\n expectType<typeof args.exportStatementExtension, Ext | 'none'>('=');\n\n expectType<typeof args.indexFileExtension, Ext>('=');\n\n expectType<typeof args.exclude, string[] | undefined>('=');\n\n expectType<typeof args.formatCommand, string | undefined>('=');\n\n expectType<typeof args.silent, boolean | undefined>('=');\n\n expectType<typeof args.minDepth, number | undefined>('=');\n\n main(args).catch((error: unknown) => {\n console.error('An error occurred:', error);\n\n process.exit(1);\n });\n },\n});\n\nconst main = async ({\n targetDirectory,\n targetExtensions,\n exportStatementExtension,\n indexFileExtension,\n exclude,\n formatCommand,\n silent,\n minDepth,\n}: Readonly<{\n targetDirectory: string;\n targetExtensions: readonly Ext[];\n exportStatementExtension: Ext | 'none';\n indexFileExtension: Ext;\n exclude?: readonly string[] | undefined;\n formatCommand?: string | undefined;\n silent?: boolean | undefined;\n minDepth?: number | undefined;\n}>): Promise<void> => {\n await genIndex({\n targetDirectory: targetDirectory.includes(',')\n ? targetDirectory.split(',').map((dir) => dir.trim())\n : targetDirectory,\n exportStatementExtension,\n targetExtensions,\n exclude,\n indexFileExtension,\n formatCommand,\n silent,\n minDepth,\n });\n};\n\nawait cmd.run(cmdDef, Arr.skip(process.argv, 2));\n"],"names":[],"mappings":"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"}
|
package/dist/entry-point.mjs
CHANGED
|
@@ -10,9 +10,10 @@ export { genIndex } from './functions/gen-index.mjs';
|
|
|
10
10
|
export { glob } from './functions/glob.mjs';
|
|
11
11
|
export { isDirectlyExecuted } from './functions/is-directly-executed.mjs';
|
|
12
12
|
export { makeEmptyDir } from './functions/make-empty-dir.mjs';
|
|
13
|
-
export { checkShouldRunTypeChecks } from './functions/should-run.mjs';
|
|
13
|
+
export { checkShouldRun, checkShouldRunTypeChecks } from './functions/should-run.mjs';
|
|
14
14
|
export { executeParallel, executeStages } from './functions/workspace-utils/execute-parallel.mjs';
|
|
15
15
|
export { getWorkspacePackages } from './functions/workspace-utils/get-workspace-packages.mjs';
|
|
16
16
|
export { runCmdInParallelAcrossWorkspaces } from './functions/workspace-utils/run-cmd-in-parallel.mjs';
|
|
17
17
|
export { runCmdInStagesAcrossWorkspaces } from './functions/workspace-utils/run-cmd-in-stages.mjs';
|
|
18
|
+
export { defaultDependencyFields } from './functions/workspace-utils/types.mjs';
|
|
18
19
|
//# sourceMappingURL=entry-point.mjs.map
|
package/dist/entry-point.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry-point.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"entry-point.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;"}
|
package/dist/functions/index.mjs
CHANGED
|
@@ -9,9 +9,10 @@ export { genIndex } from './gen-index.mjs';
|
|
|
9
9
|
export { glob } from './glob.mjs';
|
|
10
10
|
export { isDirectlyExecuted } from './is-directly-executed.mjs';
|
|
11
11
|
export { makeEmptyDir } from './make-empty-dir.mjs';
|
|
12
|
-
export { checkShouldRunTypeChecks } from './should-run.mjs';
|
|
12
|
+
export { checkShouldRun, checkShouldRunTypeChecks } from './should-run.mjs';
|
|
13
13
|
export { executeParallel, executeStages } from './workspace-utils/execute-parallel.mjs';
|
|
14
14
|
export { getWorkspacePackages } from './workspace-utils/get-workspace-packages.mjs';
|
|
15
15
|
export { runCmdInParallelAcrossWorkspaces } from './workspace-utils/run-cmd-in-parallel.mjs';
|
|
16
16
|
export { runCmdInStagesAcrossWorkspaces } from './workspace-utils/run-cmd-in-stages.mjs';
|
|
17
|
+
export { defaultDependencyFields } from './workspace-utils/types.mjs';
|
|
17
18
|
//# 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":";;;;;;;;;;;;;;;;"}
|
|
@@ -1,7 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks whether a CI step should run, based on which files differ from a base
|
|
3
|
+
* branch. Reports `false` when every changed file matches one of the ignored
|
|
4
|
+
* patterns.
|
|
5
|
+
*
|
|
6
|
+
* This is the general form of {@link checkShouldRunTypeChecks}: it carries no
|
|
7
|
+
* default ignore list, so the caller states exactly which paths are irrelevant
|
|
8
|
+
* to the step being gated.
|
|
9
|
+
*
|
|
10
|
+
* Prefer gating the individual steps of a workflow with this over a
|
|
11
|
+
* `paths-ignore` trigger filter: a workflow that a path filter skips never
|
|
12
|
+
* reports a status check, so a pull request that changed only the filtered
|
|
13
|
+
* paths waits forever on a required check that will never arrive.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* // Skip when the diff only touches a directory nothing checks
|
|
18
|
+
* await checkShouldRun({ pathsIgnore: ['experimental/'] });
|
|
19
|
+
*
|
|
20
|
+
* // Custom base branch
|
|
21
|
+
* await checkShouldRun({
|
|
22
|
+
* pathsIgnore: ['docs/', '**.md'],
|
|
23
|
+
* baseBranch: 'origin/develop',
|
|
24
|
+
* });
|
|
25
|
+
* ```;
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* GitHub Actions usage
|
|
29
|
+
* ```yaml
|
|
30
|
+
* - name: Check diff
|
|
31
|
+
* id: check_diff
|
|
32
|
+
* run: npm exec -- check-should-run --paths-ignore 'experimental/'
|
|
33
|
+
*
|
|
34
|
+
* - name: Run the checks
|
|
35
|
+
* if: steps.check_diff.outputs.should_run == 'true'
|
|
36
|
+
* run: npm run check
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* @param options - Configuration options
|
|
40
|
+
* @param options.pathsIgnore - Patterns whose files do not affect the step.
|
|
41
|
+
* Matched with micromatch (with `dot: true`) against paths relative to the
|
|
42
|
+
* repository root, with one shorthand: a pattern ending with `/` is a
|
|
43
|
+
* directory prefix, so `docs/` is `docs/**`. Exact file names
|
|
44
|
+
* (`.editorconfig`) and ordinary globs (`**.md`, `docs/**`) both work.
|
|
45
|
+
* Defaults to `[]`, which ignores nothing.
|
|
46
|
+
* @param options.baseBranch - Base branch to compare against for determining
|
|
47
|
+
* changed files. Defaults to `'origin/main'`
|
|
48
|
+
* @returns Whether the step should run. An empty diff reads as "nothing
|
|
49
|
+
* changed" and so returns `false`. When running in GitHub Actions, also
|
|
50
|
+
* appends `should_run=true` or `should_run=false` to the file named by the
|
|
51
|
+
* `GITHUB_OUTPUT` environment variable.
|
|
52
|
+
*/
|
|
53
|
+
export declare const checkShouldRun: (options?: Readonly<{
|
|
54
|
+
pathsIgnore?: readonly string[];
|
|
55
|
+
baseBranch?: string;
|
|
56
|
+
}>) => Promise<boolean>;
|
|
1
57
|
/**
|
|
2
58
|
* Checks if TypeScript type checks should run based on the diff from a base
|
|
3
59
|
* branch. Skips type checks if all changed files match the ignored patterns.
|
|
4
60
|
*
|
|
61
|
+
* This is {@link checkShouldRun} with an ignore list of the files that a
|
|
62
|
+
* TypeScript project typically has but never type-checks — documentation,
|
|
63
|
+
* tooling configuration, license text. Pass `pathsIgnore` to replace that list,
|
|
64
|
+
* or call {@link checkShouldRun} directly for a step that is not a type check.
|
|
65
|
+
*
|
|
5
66
|
* This function is typically used in CI/CD pipelines to determine whether
|
|
6
67
|
* expensive type checking operations should be performed. If all changed files
|
|
7
68
|
* are documentation, configuration, or other non-TypeScript files, type checks
|
|
@@ -37,7 +98,7 @@
|
|
|
37
98
|
*
|
|
38
99
|
* @param options - Configuration options
|
|
39
100
|
* @param options.pathsIgnore - Array of patterns to ignore when determining if
|
|
40
|
-
* type checks should run.
|
|
101
|
+
* type checks should run. Matched as described in {@link checkShouldRun}:
|
|
41
102
|
*
|
|
42
103
|
* - **Exact file matches**: e.g., `.cspell.config.yaml` matches only that file
|
|
43
104
|
* - **Directory prefixes**: e.g., `docs/` matches any file in docs directory
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"should-run.d.mts","sourceRoot":"","sources":["../../src/functions/should-run.mts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"should-run.d.mts","sourceRoot":"","sources":["../../src/functions/should-run.mts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,eAAO,MAAM,cAAc,aACf,QAAQ,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC,KACD,OAAO,CAAC,OAAO,CAyCjB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,eAAO,MAAM,wBAAwB,aACzB,QAAQ,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC,KACD,OAAO,CAAC,OAAO,CAId,CAAC"}
|
|
@@ -1,51 +1,55 @@
|
|
|
1
|
+
import micromatch from 'micromatch';
|
|
1
2
|
import * as fs from 'node:fs/promises';
|
|
2
3
|
import * as path from 'node:path';
|
|
3
|
-
import { Result } from 'ts-data-forge';
|
|
4
|
-
import { getDiffFrom } from './diff.mjs';
|
|
4
|
+
import { Result, castMutable } from 'ts-data-forge';
|
|
5
|
+
import { getGitRoot, getDiffFrom } from './diff.mjs';
|
|
5
6
|
|
|
6
|
-
const
|
|
7
|
-
const pathsIgnore = options?.pathsIgnore ?? [
|
|
8
|
-
"LICENSE",
|
|
9
|
-
".editorconfig",
|
|
10
|
-
".gitignore",
|
|
11
|
-
".cspell.json",
|
|
12
|
-
".cspell.config.yaml",
|
|
13
|
-
".markdownlint-cli2.mjs",
|
|
14
|
-
".npmignore",
|
|
15
|
-
".prettierignore",
|
|
16
|
-
".prettierrc",
|
|
17
|
-
"docs/",
|
|
18
|
-
"**.md",
|
|
19
|
-
"**.txt"
|
|
20
|
-
];
|
|
7
|
+
const checkShouldRun = async (options) => {
|
|
8
|
+
const pathsIgnore = options?.pathsIgnore ?? [];
|
|
21
9
|
const baseBranch = options?.baseBranch ?? "origin/main";
|
|
22
10
|
const GITHUB_OUTPUT = process.env["GITHUB_OUTPUT"];
|
|
11
|
+
const gitRoot = await getGitRoot();
|
|
12
|
+
if (Result.isErr(gitRoot)) {
|
|
13
|
+
console.error("Error getting the git root:", gitRoot.value);
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
23
16
|
const files = await getDiffFrom(baseBranch);
|
|
24
17
|
if (Result.isErr(files)) {
|
|
25
18
|
console.error("Error getting diff:", files.value);
|
|
26
19
|
process.exit(1);
|
|
27
20
|
}
|
|
28
|
-
const
|
|
29
|
-
(file) =>
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
return true;
|
|
35
|
-
}
|
|
36
|
-
if (pattern.startsWith("**.")) {
|
|
37
|
-
const extension = pattern.slice(2);
|
|
38
|
-
return path.basename(file).endsWith(extension);
|
|
39
|
-
}
|
|
40
|
-
return false;
|
|
41
|
-
})
|
|
21
|
+
const changedFiles = files.value.map(
|
|
22
|
+
(file) => path.relative(gitRoot.value, file).split(path.sep).join("/")
|
|
23
|
+
);
|
|
24
|
+
const patterns = pathsIgnore.map(toMatchPattern);
|
|
25
|
+
const shouldRun = changedFiles.some(
|
|
26
|
+
(file) => !micromatch.isMatch(file, castMutable(patterns), { dot: true })
|
|
42
27
|
);
|
|
43
28
|
if (GITHUB_OUTPUT !== void 0) {
|
|
44
|
-
await fs.appendFile(GITHUB_OUTPUT, `should_run=${
|
|
29
|
+
await fs.appendFile(GITHUB_OUTPUT, `should_run=${shouldRun}
|
|
45
30
|
`);
|
|
46
31
|
}
|
|
47
|
-
return
|
|
32
|
+
return shouldRun;
|
|
48
33
|
};
|
|
34
|
+
const checkShouldRunTypeChecks = async (options) => checkShouldRun({
|
|
35
|
+
pathsIgnore: options?.pathsIgnore ?? defaultTypeCheckPathsIgnore,
|
|
36
|
+
baseBranch: options?.baseBranch
|
|
37
|
+
});
|
|
38
|
+
const defaultTypeCheckPathsIgnore = [
|
|
39
|
+
"LICENSE",
|
|
40
|
+
".editorconfig",
|
|
41
|
+
".gitignore",
|
|
42
|
+
".cspell.json",
|
|
43
|
+
".cspell.config.yaml",
|
|
44
|
+
".markdownlint-cli2.mjs",
|
|
45
|
+
".npmignore",
|
|
46
|
+
".prettierignore",
|
|
47
|
+
".prettierrc",
|
|
48
|
+
"docs/",
|
|
49
|
+
"**.md",
|
|
50
|
+
"**.txt"
|
|
51
|
+
];
|
|
52
|
+
const toMatchPattern = (pattern) => pattern.endsWith("/") ? `${pattern}**` : pattern;
|
|
49
53
|
|
|
50
|
-
export { checkShouldRunTypeChecks };
|
|
54
|
+
export { checkShouldRun, checkShouldRunTypeChecks };
|
|
51
55
|
//# sourceMappingURL=should-run.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"should-run.mjs","sources":["../../src/functions/should-run.mts"],"sourcesContent":["import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { Result } from 'ts-data-forge';\nimport { getDiffFrom } from './diff.mjs';\n\n/**\n * Checks if TypeScript type checks should run based on the diff from a base\n * branch. Skips type checks if all changed files match the ignored patterns.\n *\n * This function is typically used in CI/CD pipelines to determine whether\n * expensive type checking operations should be performed. If all changed files\n * are documentation, configuration, or other non-TypeScript files, type checks\n * can be safely skipped to improve build performance.\n *\n * @example\n * ```typescript\n * // Use default settings (compare against origin/main, ignore docs/md/txt files)\n * await checkShouldRunTypeChecks();\n *\n * // Custom ignore patterns\n * await checkShouldRunTypeChecks({\n * pathsIgnore: ['.eslintrc.json', 'docs/', '**.md', 'scripts/'],\n * });\n *\n * // Custom base branch\n * await checkShouldRunTypeChecks({\n * baseBranch: 'origin/develop',\n * });\n * ```;\n *\n * @example\n * GitHub Actions usage\n * ```yaml\n * - name: Check if type checks should run\n * id: check_diff\n * run: npm exec check-should-run-type-checks\n *\n * - name: Run type checks\n * if: steps.check_diff.outputs.should_run == 'true'\n * run: npm run type-check\n * ```\n *\n * @param options - Configuration options\n * @param options.pathsIgnore - Array of patterns to ignore when determining if\n * type checks should run.
|
|
1
|
+
{"version":3,"file":"should-run.mjs","sources":["../../src/functions/should-run.mts"],"sourcesContent":["import micromatch from 'micromatch';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { castMutable, Result } from 'ts-data-forge';\nimport { getDiffFrom, getGitRoot } from './diff.mjs';\n\n/**\n * Checks whether a CI step should run, based on which files differ from a base\n * branch. Reports `false` when every changed file matches one of the ignored\n * patterns.\n *\n * This is the general form of {@link checkShouldRunTypeChecks}: it carries no\n * default ignore list, so the caller states exactly which paths are irrelevant\n * to the step being gated.\n *\n * Prefer gating the individual steps of a workflow with this over a\n * `paths-ignore` trigger filter: a workflow that a path filter skips never\n * reports a status check, so a pull request that changed only the filtered\n * paths waits forever on a required check that will never arrive.\n *\n * @example\n * ```typescript\n * // Skip when the diff only touches a directory nothing checks\n * await checkShouldRun({ pathsIgnore: ['experimental/'] });\n *\n * // Custom base branch\n * await checkShouldRun({\n * pathsIgnore: ['docs/', '**.md'],\n * baseBranch: 'origin/develop',\n * });\n * ```;\n *\n * @example\n * GitHub Actions usage\n * ```yaml\n * - name: Check diff\n * id: check_diff\n * run: npm exec -- check-should-run --paths-ignore 'experimental/'\n *\n * - name: Run the checks\n * if: steps.check_diff.outputs.should_run == 'true'\n * run: npm run check\n * ```\n *\n * @param options - Configuration options\n * @param options.pathsIgnore - Patterns whose files do not affect the step.\n * Matched with micromatch (with `dot: true`) against paths relative to the\n * repository root, with one shorthand: a pattern ending with `/` is a\n * directory prefix, so `docs/` is `docs/**`. Exact file names\n * (`.editorconfig`) and ordinary globs (`**.md`, `docs/**`) both work.\n * Defaults to `[]`, which ignores nothing.\n * @param options.baseBranch - Base branch to compare against for determining\n * changed files. Defaults to `'origin/main'`\n * @returns Whether the step should run. An empty diff reads as \"nothing\n * changed\" and so returns `false`. When running in GitHub Actions, also\n * appends `should_run=true` or `should_run=false` to the file named by the\n * `GITHUB_OUTPUT` environment variable.\n */\nexport const checkShouldRun = async (\n options?: Readonly<{\n pathsIgnore?: readonly string[];\n baseBranch?: string;\n }>,\n): Promise<boolean> => {\n const pathsIgnore = options?.pathsIgnore ?? [];\n\n const baseBranch = options?.baseBranch ?? 'origin/main';\n\n const GITHUB_OUTPUT = process.env['GITHUB_OUTPUT'];\n\n const gitRoot = await getGitRoot();\n\n if (Result.isErr(gitRoot)) {\n console.error('Error getting the git root:', gitRoot.value);\n\n process.exit(1);\n }\n\n const files = await getDiffFrom(baseBranch);\n\n if (Result.isErr(files)) {\n console.error('Error getting diff:', files.value);\n\n process.exit(1);\n }\n\n // `getDiffFrom` returns absolute paths, while the patterns are written\n // relative to the repository root.\n const changedFiles = files.value.map((file) =>\n path.relative(gitRoot.value, file).split(path.sep).join('/'),\n );\n\n const patterns = pathsIgnore.map(toMatchPattern);\n\n const shouldRun: boolean = changedFiles.some(\n (file) => !micromatch.isMatch(file, castMutable(patterns), { dot: true }),\n );\n\n if (GITHUB_OUTPUT !== undefined) {\n // eslint-disable-next-line security/detect-non-literal-fs-filename\n await fs.appendFile(GITHUB_OUTPUT, `should_run=${shouldRun}\\n`);\n }\n\n return shouldRun;\n};\n\n/**\n * Checks if TypeScript type checks should run based on the diff from a base\n * branch. Skips type checks if all changed files match the ignored patterns.\n *\n * This is {@link checkShouldRun} with an ignore list of the files that a\n * TypeScript project typically has but never type-checks — documentation,\n * tooling configuration, license text. Pass `pathsIgnore` to replace that list,\n * or call {@link checkShouldRun} directly for a step that is not a type check.\n *\n * This function is typically used in CI/CD pipelines to determine whether\n * expensive type checking operations should be performed. If all changed files\n * are documentation, configuration, or other non-TypeScript files, type checks\n * can be safely skipped to improve build performance.\n *\n * @example\n * ```typescript\n * // Use default settings (compare against origin/main, ignore docs/md/txt files)\n * await checkShouldRunTypeChecks();\n *\n * // Custom ignore patterns\n * await checkShouldRunTypeChecks({\n * pathsIgnore: ['.eslintrc.json', 'docs/', '**.md', 'scripts/'],\n * });\n *\n * // Custom base branch\n * await checkShouldRunTypeChecks({\n * baseBranch: 'origin/develop',\n * });\n * ```;\n *\n * @example\n * GitHub Actions usage\n * ```yaml\n * - name: Check if type checks should run\n * id: check_diff\n * run: npm exec check-should-run-type-checks\n *\n * - name: Run type checks\n * if: steps.check_diff.outputs.should_run == 'true'\n * run: npm run type-check\n * ```\n *\n * @param options - Configuration options\n * @param options.pathsIgnore - Array of patterns to ignore when determining if\n * type checks should run. Matched as described in {@link checkShouldRun}:\n *\n * - **Exact file matches**: e.g., `.cspell.config.yaml` matches only that file\n * - **Directory prefixes**: e.g., `docs/` matches any file in docs directory\n * - **File extensions**: e.g., `**.md` matches any markdown file Defaults to:\n * `['LICENSE', '.editorconfig', '.gitignore', '.cspell.json', '.cspell.config.yaml',\n * '.markdownlint-cli2.mjs', '.npmignore', '.prettierignore',\n * '.prettierrc', 'docs/', '**.md', '**.txt']`\n *\n * @param options.baseBranch - Base branch to compare against for determining\n * changed files. Defaults to `'origin/main'`\n * @returns A promise that resolves when the check is complete. The function\n * will set the GITHUB_OUTPUT environment variable with `should_run=true` or\n * `should_run=false` if running in GitHub Actions environment.\n */\nexport const checkShouldRunTypeChecks = async (\n options?: Readonly<{\n pathsIgnore?: readonly string[];\n baseBranch?: string;\n }>,\n): Promise<boolean> =>\n checkShouldRun({\n pathsIgnore: options?.pathsIgnore ?? defaultTypeCheckPathsIgnore,\n baseBranch: options?.baseBranch,\n });\n\nconst defaultTypeCheckPathsIgnore = [\n 'LICENSE',\n '.editorconfig',\n '.gitignore',\n '.cspell.json',\n '.cspell.config.yaml',\n '.markdownlint-cli2.mjs',\n '.npmignore',\n '.prettierignore',\n '.prettierrc',\n 'docs/',\n '**.md',\n '**.txt',\n] as const;\n\n/**\n * Expands the trailing-slash shorthand for a directory into the glob\n * micromatch needs. Every other pattern is already one.\n */\nconst toMatchPattern = (pattern: string): string =>\n pattern.endsWith('/') ? (`${pattern}**` as const) : pattern;\n"],"names":[],"mappings":";;;;;;AA0DO,MAAM,cAAA,GAAiB,OAC5B,OAAA,KAIqB;AACrB,EAAA,MAAM,WAAA,GAAc,OAAA,EAAS,WAAA,IAAe,EAAC;AAE7C,EAAA,MAAM,UAAA,GAAa,SAAS,UAAA,IAAc,aAAA;AAE1C,EAAA,MAAM,aAAA,GAAgB,OAAA,CAAQ,GAAA,CAAI,eAAe,CAAA;AAEjD,EAAA,MAAM,OAAA,GAAU,MAAM,UAAA,EAAW;AAEjC,EAAA,IAAI,MAAA,CAAO,KAAA,CAAM,OAAO,CAAA,EAAG;AACzB,IAAA,OAAA,CAAQ,KAAA,CAAM,6BAAA,EAA+B,OAAA,CAAQ,KAAK,CAAA;AAE1D,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AAEA,EAAA,MAAM,KAAA,GAAQ,MAAM,WAAA,CAAY,UAAU,CAAA;AAE1C,EAAA,IAAI,MAAA,CAAO,KAAA,CAAM,KAAK,CAAA,EAAG;AACvB,IAAA,OAAA,CAAQ,KAAA,CAAM,qBAAA,EAAuB,KAAA,CAAM,KAAK,CAAA;AAEhD,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AAIA,EAAA,MAAM,YAAA,GAAe,MAAM,KAAA,CAAM,GAAA;AAAA,IAAI,CAAC,IAAA,KACpC,IAAA,CAAK,QAAA,CAAS,OAAA,CAAQ,KAAA,EAAO,IAAI,CAAA,CAAE,KAAA,CAAM,IAAA,CAAK,GAAG,CAAA,CAAE,KAAK,GAAG;AAAA,GAC7D;AAEA,EAAA,MAAM,QAAA,GAAW,WAAA,CAAY,GAAA,CAAI,cAAc,CAAA;AAE/C,EAAA,MAAM,YAAqB,YAAA,CAAa,IAAA;AAAA,IACtC,CAAC,IAAA,KAAS,CAAC,UAAA,CAAW,OAAA,CAAQ,IAAA,EAAM,WAAA,CAAY,QAAQ,CAAA,EAAG,EAAE,GAAA,EAAK,IAAA,EAAM;AAAA,GAC1E;AAEA,EAAA,IAAI,kBAAkB,MAAA,EAAW;AAE/B,IAAA,MAAM,EAAA,CAAG,UAAA,CAAW,aAAA,EAAe,CAAA,WAAA,EAAc,SAAS;AAAA,CAAI,CAAA;AAAA,EAChE;AAEA,EAAA,OAAO,SAAA;AACT;AA6DO,MAAM,wBAAA,GAA2B,OACtC,OAAA,KAKA,cAAA,CAAe;AAAA,EACb,WAAA,EAAa,SAAS,WAAA,IAAe,2BAAA;AAAA,EACrC,YAAY,OAAA,EAAS;AACvB,CAAC;AAEH,MAAM,2BAAA,GAA8B;AAAA,EAClC,SAAA;AAAA,EACA,eAAA;AAAA,EACA,YAAA;AAAA,EACA,cAAA;AAAA,EACA,qBAAA;AAAA,EACA,wBAAA;AAAA,EACA,YAAA;AAAA,EACA,iBAAA;AAAA,EACA,aAAA;AAAA,EACA,OAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAA;AAMA,MAAM,cAAA,GAAiB,CAAC,OAAA,KACtB,OAAA,CAAQ,SAAS,GAAG,CAAA,GAAK,CAAA,EAAG,OAAO,CAAA,EAAA,CAAA,GAAiB,OAAA;;;;"}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import { type Package } from './types.mjs';
|
|
1
|
+
import { type DependencyField, type Package } from './types.mjs';
|
|
2
2
|
/**
|
|
3
3
|
* Retrieves all workspace packages from a monorepo based on the workspace
|
|
4
4
|
* patterns defined in the root package.json file.
|
|
5
5
|
*
|
|
6
6
|
* @param rootPackageJsonDir - The directory containing the root package.json
|
|
7
7
|
* file
|
|
8
|
+
* @param dependencyFields - Which `package.json` fields contribute to each
|
|
9
|
+
* package's `dependencies` map. Defaults to
|
|
10
|
+
* {@link defaultDependencyFields}.
|
|
8
11
|
* @returns A promise that resolves to an array of Package objects containing
|
|
9
12
|
* package metadata
|
|
10
13
|
*/
|
|
11
|
-
export declare const getWorkspacePackages: (rootPackageJsonDir: string) => Promise<readonly Package[]>;
|
|
14
|
+
export declare const getWorkspacePackages: (rootPackageJsonDir: string, dependencyFields?: readonly DependencyField[]) => Promise<readonly Package[]>;
|
|
12
15
|
//# sourceMappingURL=get-workspace-packages.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-workspace-packages.d.mts","sourceRoot":"","sources":["../../../src/functions/workspace-utils/get-workspace-packages.mts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"get-workspace-packages.d.mts","sourceRoot":"","sources":["../../../src/functions/workspace-utils/get-workspace-packages.mts"],"names":[],"mappings":"AAcA,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,OAAO,EACb,MAAM,aAAa,CAAC;AAErB;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,oBAAoB,uBACX,MAAM,qBACR,SAAS,eAAe,EAAE,KAC3C,OAAO,CAAC,SAAS,OAAO,EAAE,CAqE5B,CAAC"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import * as fs from 'node:fs/promises';
|
|
2
2
|
import * as path from 'node:path';
|
|
3
|
-
import { Result, Json, isNotUndefined, isRecord, hasKey, Arr, isString } from 'ts-data-forge';
|
|
3
|
+
import { Result, Json, isNotUndefined, isRecord, hasKey, Arr, isString, Obj } from 'ts-data-forge';
|
|
4
4
|
import { glob } from '../glob.mjs';
|
|
5
|
+
import { defaultDependencyFields } from './types.mjs';
|
|
5
6
|
|
|
6
|
-
const getWorkspacePackages = async (rootPackageJsonDir) => {
|
|
7
|
+
const getWorkspacePackages = async (rootPackageJsonDir, dependencyFields = defaultDependencyFields) => {
|
|
7
8
|
const rootPackageJson = JSON.parse(
|
|
8
9
|
// eslint-disable-next-line security/detect-non-literal-fs-filename
|
|
9
10
|
await fs.readFile(path.join(rootPackageJsonDir, "package.json"), "utf8")
|
|
@@ -40,11 +41,11 @@ const getWorkspacePackages = async (rootPackageJsonDir) => {
|
|
|
40
41
|
name: getStrFromJsonValue(packageJson, "name"),
|
|
41
42
|
path: path.dirname(packagePath),
|
|
42
43
|
packageJson,
|
|
43
|
-
dependencies:
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
dependencies: Object.fromEntries(
|
|
45
|
+
dependencyFields.flatMap(
|
|
46
|
+
(field) => Object.entries(getKeyValueRecordFromJsonValue(packageJson, field))
|
|
47
|
+
)
|
|
48
|
+
)
|
|
48
49
|
}));
|
|
49
50
|
return packageInfos;
|
|
50
51
|
});
|
|
@@ -62,10 +63,7 @@ const getKeyValueRecordFromJsonValue = (value, key) => {
|
|
|
62
63
|
if (!isRecord(obj)) {
|
|
63
64
|
return {};
|
|
64
65
|
}
|
|
65
|
-
|
|
66
|
-
(entry) => isString(entry[1])
|
|
67
|
-
);
|
|
68
|
-
return Object.fromEntries(entries);
|
|
66
|
+
return Obj.filter(obj, isString);
|
|
69
67
|
};
|
|
70
68
|
|
|
71
69
|
export { getWorkspacePackages };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-workspace-packages.mjs","sources":["../../../src/functions/workspace-utils/get-workspace-packages.mts"],"sourcesContent":["import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport {\n Arr,\n hasKey,\n isNotUndefined,\n isRecord,\n isString,\n Json,\n Result,\n} from 'ts-data-forge';\nimport {
|
|
1
|
+
{"version":3,"file":"get-workspace-packages.mjs","sources":["../../../src/functions/workspace-utils/get-workspace-packages.mts"],"sourcesContent":["import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport {\n Arr,\n hasKey,\n isNotUndefined,\n isRecord,\n isString,\n Json,\n Obj,\n Result,\n} from 'ts-data-forge';\nimport { type JsonValue, type ReadonlyRecord } from 'ts-type-forge';\nimport { glob } from '../glob.mjs';\nimport {\n defaultDependencyFields,\n type DependencyField,\n type Package,\n} from './types.mjs';\n\n/**\n * Retrieves all workspace packages from a monorepo based on the workspace\n * patterns defined in the root package.json file.\n *\n * @param rootPackageJsonDir - The directory containing the root package.json\n * file\n * @param dependencyFields - Which `package.json` fields contribute to each\n * package's `dependencies` map. Defaults to\n * {@link defaultDependencyFields}.\n * @returns A promise that resolves to an array of Package objects containing\n * package metadata\n */\nexport const getWorkspacePackages = async (\n rootPackageJsonDir: string,\n dependencyFields: readonly DependencyField[] = defaultDependencyFields,\n): Promise<readonly Package[]> => {\n // Read root package.json\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const rootPackageJson: JsonValue = JSON.parse(\n // eslint-disable-next-line security/detect-non-literal-fs-filename\n await fs.readFile(path.join(rootPackageJsonDir, 'package.json'), 'utf8'),\n );\n\n const workspacePatterns: readonly string[] = getStrArrayFromJsonValue(\n rootPackageJson,\n 'workspaces',\n );\n\n const packagePromises = workspacePatterns.map(async (pattern) => {\n const globResult = await glob(pattern, {\n cwd: rootPackageJsonDir,\n ignore: ['**/node_modules/**'],\n onlyDirectories: true,\n absolute: true,\n });\n\n if (Result.isErr(globResult)) {\n return [];\n }\n\n const matches = globResult.value;\n\n const packageJsonList: readonly (\n readonly [string, JsonValue] | undefined\n )[] = await Promise.all(\n matches.map(async (match) => {\n const maybePackagePath = path.join(match, 'package.json');\n\n const result = await Result.fromPromise(\n // eslint-disable-next-line security/detect-non-literal-fs-filename\n fs.readFile(maybePackagePath, 'utf8'),\n );\n\n if (Result.isErr(result)) return undefined;\n\n const parsed = Json.parse(result.value);\n\n if (Result.isErr(parsed)) return undefined;\n\n return [maybePackagePath, parsed.value] as const;\n }),\n );\n\n const packageInfos: readonly Package[] = packageJsonList\n .filter(isNotUndefined)\n .map(([packagePath, packageJson]) => ({\n name: getStrFromJsonValue(packageJson, 'name'),\n path: path.dirname(packagePath),\n packageJson,\n dependencies: Object.fromEntries(\n dependencyFields.flatMap((field) =>\n Object.entries(getKeyValueRecordFromJsonValue(packageJson, field)),\n ),\n ),\n }));\n\n return packageInfos;\n });\n\n const allPackageArrays = await Promise.all(packagePromises);\n\n const finalPackages = allPackageArrays.flat();\n\n return finalPackages;\n};\n\nconst getStrFromJsonValue = (value: JsonValue, key: string): string =>\n isRecord(value) && hasKey(value, key) && isString(value[key])\n ? value[key]\n : '';\n\nconst getStrArrayFromJsonValue = (\n value: JsonValue,\n key: string,\n): readonly string[] =>\n isRecord(value) &&\n hasKey(value, key) &&\n Arr.isArray(value[key]) &&\n value[key].every(isString)\n ? value[key]\n : ([] as const);\n\nconst getKeyValueRecordFromJsonValue = (\n value: JsonValue,\n key: string,\n): ReadonlyRecord<string, string> => {\n if (!isRecord(value) || !hasKey(value, key)) {\n return {};\n }\n\n const obj = value[key];\n\n if (!isRecord(obj)) {\n return {};\n }\n\n return Obj.filter(obj, isString);\n};\n"],"names":[],"mappings":"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"}
|