apextestlist 1.14.3 → 1.15.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/CHANGELOG.md +14 -0
- package/README.md +30 -3
- package/lib/commands/apextests/list.d.ts +1 -0
- package/lib/commands/apextests/list.js +11 -1
- package/lib/commands/apextests/list.js.map +1 -1
- package/lib/core/listTests.js +4 -1
- package/lib/core/listTests.js.map +1 -1
- package/lib/utils/formatters.d.ts +1 -1
- package/lib/utils/formatters.js +4 -1
- package/lib/utils/formatters.js.map +1 -1
- package/lib/utils/types.d.ts +1 -0
- package/messages/apextests.list.md +13 -0
- package/oclif.manifest.json +12 -2
- package/package.json +35 -8
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,20 @@
|
|
|
5
5
|
|
|
6
6
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
7
7
|
|
|
8
|
+
## [1.15.0](https://github.com/wisefoxme/apex-test-list/compare/v1.14.4...v1.15.0) (2026-09-16)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* add manifest-aware --fail-on-empty flag ([#420](https://github.com/wisefoxme/apex-test-list/issues/420)) ([8fef2b5](https://github.com/wisefoxme/apex-test-list/commit/8fef2b54d169e4b474a340ea97b44642c9bd6815))
|
|
14
|
+
|
|
15
|
+
## [1.14.4](https://github.com/wisefoxme/apex-test-list/compare/v1.14.3...v1.14.4) (2026-09-13)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* **deps:** bump @salesforce/core in the dependencies group ([#417](https://github.com/wisefoxme/apex-test-list/issues/417)) ([a6c1385](https://github.com/wisefoxme/apex-test-list/commit/a6c13857d405798831b5a626781eb97af0df4010))
|
|
21
|
+
|
|
8
22
|
## [1.14.3](https://github.com/wisefoxme/apex-test-list/compare/v1.14.2...v1.14.3) (2026-09-06)
|
|
9
23
|
|
|
10
24
|
|
package/README.md
CHANGED
|
@@ -22,6 +22,7 @@ A plugin that generates a list of tests that your automated process should run,
|
|
|
22
22
|
- [Running the Tool](#running-the-tool)
|
|
23
23
|
- [Handling Missing Tests](#handling-missing-tests)
|
|
24
24
|
- [Handling Missing Annotations](#handling-missing-annotations)
|
|
25
|
+
- [Failing When No Tests Are Found](#failing-when-no-tests-are-found)
|
|
25
26
|
- [GitHub Action](#github-action)
|
|
26
27
|
- [Command Reference](#command-reference)
|
|
27
28
|
- [Issues](#issues)
|
|
@@ -162,6 +163,28 @@ To remove these warnings from the terminal, use:
|
|
|
162
163
|
sf apextests list --no-warnings
|
|
163
164
|
```
|
|
164
165
|
|
|
166
|
+
### Failing When No Tests Are Found
|
|
167
|
+
|
|
168
|
+
By default, the command exits with code `0` even when no test methods are found — it just prints an empty result and a warning. To have it fail the run instead, use:
|
|
169
|
+
|
|
170
|
+
```sh
|
|
171
|
+
sf apextests list --fail-on-empty
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Combined with `-x`/`--manifest`, this is manifest-aware: it only fails when the manifest actually declares `ApexClass`/`ApexTrigger` members but no tests could be resolved for them. If the manifest contains no Apex at all (e.g., a delta package with only non-Apex metadata), the command still exits `0`, since there's nothing to test.
|
|
175
|
+
|
|
176
|
+
```sh
|
|
177
|
+
# Exits 0: package.xml has no ApexClass/ApexTrigger members, nothing to check
|
|
178
|
+
sf apextests list --manifest package.xml --fail-on-empty
|
|
179
|
+
|
|
180
|
+
# Exits 1: package.xml declares Apex, but no tests were found for it
|
|
181
|
+
sf apextests list --manifest package.xml --fail-on-empty
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
This is useful as a CI guardrail: skip the deploy/validate step cleanly when a manifest has no Apex changes, but fail loudly when Apex changed and no tests cover it.
|
|
185
|
+
|
|
186
|
+
The GitHub Action's `fail-on-empty` input behaves the same way — see [Inputs](#inputs).
|
|
187
|
+
|
|
165
188
|
## GitHub Action
|
|
166
189
|
|
|
167
190
|
For GitHub Actions, this is also available as a native Action — no `sf` CLI or plugin install required:
|
|
@@ -188,7 +211,7 @@ For GitHub Actions, this is also available as a native Action — no `sf` CLI or
|
|
|
188
211
|
| `ignore-package-directory` | Directory to ignore when searching for test annotations, one per line. | No | |
|
|
189
212
|
| `no-warnings` | Do not print warnings for each Apex file missing annotations. | No | `false` |
|
|
190
213
|
| `filter-by-metadata` | Only include tests that explicitly declare metadata dependencies matching changed metadata. Requires `manifest`. | No | `false` |
|
|
191
|
-
| `fail-on-empty` | Fail the action if no test methods are found.
|
|
214
|
+
| `fail-on-empty` | Fail the action if no test methods are found. Manifest-aware when `manifest` is set — see [Failing When No Tests Are Found](#failing-when-no-tests-are-found). | No | `false` |
|
|
192
215
|
|
|
193
216
|
### Outputs
|
|
194
217
|
|
|
@@ -203,7 +226,7 @@ For GitHub Actions, this is also available as a native Action — no `sf` CLI or
|
|
|
203
226
|
|
|
204
227
|
```
|
|
205
228
|
USAGE
|
|
206
|
-
$ sf apextests list -f <value> -x <value> -s -n -d <value> -m [--json]
|
|
229
|
+
$ sf apextests list -f <value> -x <value> -s -n -d <value> -m -e [--json]
|
|
207
230
|
|
|
208
231
|
FLAGS
|
|
209
232
|
-f, --format=<value> Output format. Available options:
|
|
@@ -216,7 +239,7 @@ FLAGS
|
|
|
216
239
|
Should match how they are declared in "sfdx-project.json".
|
|
217
240
|
Can be declared multiple times.
|
|
218
241
|
-m, --filter-by-metadata [default: false] When enabled with `manifest`, test selection is based on metadata changes (e.g., Flow, CustomObject) rather than Apex annotations.
|
|
219
|
-
|
|
242
|
+
-e, --fail-on-empty [default: false] Exit with code 1 if no test methods are found. With `--manifest`, exits 0 instead when the manifest has no ApexClass/ApexTrigger members.
|
|
220
243
|
|
|
221
244
|
GLOBAL FLAGS
|
|
222
245
|
--json Format output as JSON.
|
|
@@ -242,6 +265,10 @@ EXAMPLES
|
|
|
242
265
|
|
|
243
266
|
$ sf apextests list -d "force-app"
|
|
244
267
|
|
|
268
|
+
Fail with exit code 1 if a manifest declares Apex but no tests are found for it (exit 0 if the manifest has no Apex at all):
|
|
269
|
+
|
|
270
|
+
$ sf apextests list --format sf --manifest package.xml --fail-on-empty
|
|
271
|
+
|
|
245
272
|
List test annotations without printing warnings for each file missing annotations:
|
|
246
273
|
|
|
247
274
|
$ sf apextests list -n
|
|
@@ -11,6 +11,7 @@ export default class ApextestsList extends SfCommand<ApextestsListResult> {
|
|
|
11
11
|
'ignore-package-directory': import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
12
|
'no-warnings': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
13
|
'filter-by-metadata': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
|
+
'fail-on-empty': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
15
|
};
|
|
15
16
|
run(): Promise<ApextestsListResult>;
|
|
16
17
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
import { Messages } from '@salesforce/core';
|
|
2
|
+
import { Messages, SfError } from '@salesforce/core';
|
|
3
3
|
import { Flags, SfCommand } from '@salesforce/sf-plugins-core';
|
|
4
4
|
import { listTests } from '../../core/listTests.js';
|
|
5
5
|
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
@@ -50,6 +50,13 @@ export default class ApextestsList extends SfCommand {
|
|
|
50
50
|
required: false,
|
|
51
51
|
default: false,
|
|
52
52
|
}),
|
|
53
|
+
'fail-on-empty': Flags.boolean({
|
|
54
|
+
summary: messages.getMessage('flags.fail-on-empty.summary'),
|
|
55
|
+
description: messages.getMessage('flags.fail-on-empty.description'),
|
|
56
|
+
char: 'e',
|
|
57
|
+
required: false,
|
|
58
|
+
default: false,
|
|
59
|
+
}),
|
|
53
60
|
};
|
|
54
61
|
async run() {
|
|
55
62
|
const { flags } = await this.parse(ApextestsList);
|
|
@@ -62,6 +69,9 @@ export default class ApextestsList extends SfCommand {
|
|
|
62
69
|
filterByMetadata: flags['filter-by-metadata'],
|
|
63
70
|
warn: this.warn.bind(this),
|
|
64
71
|
});
|
|
72
|
+
if (flags['fail-on-empty'] && result.tests.length === 0 && (!flags.manifest || result.manifestHasApex)) {
|
|
73
|
+
throw new SfError(messages.getMessage('errors.noTestsFound'));
|
|
74
|
+
}
|
|
65
75
|
this.log(result.command);
|
|
66
76
|
return result;
|
|
67
77
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/commands/apextests/list.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/commands/apextests/list.ts"],"names":[],"mappings":"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"}
|
package/lib/core/listTests.js
CHANGED
|
@@ -14,9 +14,11 @@ export async function listTests({ format = 'sf', manifest, ignoreMissingTests =
|
|
|
14
14
|
const testSuitesNames = [];
|
|
15
15
|
const allTestClasses = [];
|
|
16
16
|
const warnings = [];
|
|
17
|
+
let manifestHasApex = false;
|
|
17
18
|
const { metadataPaths: packageDirectories, repoRoot } = await getPackageDirectories(ignoreDirs);
|
|
18
19
|
if (manifest) {
|
|
19
20
|
const manifestMetadata = await extractTypeNamesFromManifestFile(manifest);
|
|
21
|
+
manifestHasApex = manifestMetadata.some((name) => name.startsWith('ApexClass:') || name.startsWith('ApexTrigger:'));
|
|
20
22
|
testClassesNames = manifestMetadata.filter((name) => !name.endsWith('testSuite-meta.xml'));
|
|
21
23
|
if (filterByMetadata) {
|
|
22
24
|
const ymlConfigPath = resolve(repoRoot, METADATA_FILTER_CONFIG);
|
|
@@ -57,8 +59,9 @@ export async function listTests({ format = 'sf', manifest, ignoreMissingTests =
|
|
|
57
59
|
return {
|
|
58
60
|
tests: [],
|
|
59
61
|
command: '',
|
|
62
|
+
manifestHasApex,
|
|
60
63
|
};
|
|
61
64
|
}
|
|
62
|
-
return formatList(format, finalTestMethods);
|
|
65
|
+
return formatList(format, finalTestMethods, manifestHasApex);
|
|
63
66
|
}
|
|
64
67
|
//# sourceMappingURL=listTests.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listTests.js","sourceRoot":"","sources":["../../src/core/listTests.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,gCAAgC,EAAE,MAAM,8BAA8B,CAAC;AAChF,OAAO,EAAE,4BAA4B,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACvG,OAAO,EAAE,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAAE,uCAAuC,EAAE,MAAM,iCAAiC,CAAC;AAC1F,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAE1E,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE1D,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,EAC9B,MAAM,GAAG,IAAI,EACb,QAAQ,EACR,kBAAkB,GAAG,KAAK,EAC1B,UAAU,GAAG,EAAE,EACf,UAAU,GAAG,KAAK,EAClB,gBAAgB,GAAG,KAAK,EACxB,IAAI,GAAG,GAAS,EAAE;IAChB,gBAAgB;AAClB,CAAC,GACgB;IACjB,IAAI,gBAAgB,GAAoB,IAAI,CAAC;IAC7C,MAAM,eAAe,GAAa,EAAE,CAAC;IACrC,MAAM,cAAc,GAAa,EAAE,CAAC;IACpC,MAAM,QAAQ,GAAa,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"listTests.js","sourceRoot":"","sources":["../../src/core/listTests.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { ApextestsListResult } from '../utils/types.js';
|
|
2
|
-
export declare function formatList(format: string, tests: string[]): Promise<ApextestsListResult>;
|
|
2
|
+
export declare function formatList(format: string, tests: string[], manifestHasApex?: boolean): Promise<ApextestsListResult>;
|
package/lib/utils/formatters.js
CHANGED
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
const TESTS_FLAG = '--tests ';
|
|
3
|
-
export async function formatList(format, tests) {
|
|
3
|
+
export async function formatList(format, tests, manifestHasApex = false) {
|
|
4
4
|
switch (format) {
|
|
5
5
|
case 'sf':
|
|
6
6
|
return Promise.resolve({
|
|
7
7
|
tests,
|
|
8
8
|
command: TESTS_FLAG + tests.join(` ${TESTS_FLAG}`),
|
|
9
|
+
manifestHasApex,
|
|
9
10
|
});
|
|
10
11
|
case 'sfdx':
|
|
11
12
|
return Promise.resolve({
|
|
12
13
|
tests,
|
|
13
14
|
command: TESTS_FLAG + tests.join(' '),
|
|
15
|
+
manifestHasApex,
|
|
14
16
|
});
|
|
15
17
|
case 'csv':
|
|
16
18
|
return Promise.resolve({
|
|
17
19
|
tests,
|
|
18
20
|
command: tests.join(','),
|
|
21
|
+
manifestHasApex,
|
|
19
22
|
});
|
|
20
23
|
default:
|
|
21
24
|
throw new Error('Invalid format.');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatters.js","sourceRoot":"","sources":["../../src/utils/formatters.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAGb,MAAM,UAAU,GAAG,UAAU,CAAC;AAE9B,MAAM,CAAC,KAAK,UAAU,UAAU,
|
|
1
|
+
{"version":3,"file":"formatters.js","sourceRoot":"","sources":["../../src/utils/formatters.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAGb,MAAM,UAAU,GAAG,UAAU,CAAC;AAE9B,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,MAAc,EACd,KAAe,EACf,eAAe,GAAG,KAAK;IAEvB,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,IAAI;YACP,OAAO,OAAO,CAAC,OAAO,CAAC;gBACrB,KAAK;gBACL,OAAO,EAAE,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,UAAU,EAAE,CAAC;gBAClD,eAAe;aAChB,CAAC,CAAC;QACL,KAAK,MAAM;YACT,OAAO,OAAO,CAAC,OAAO,CAAC;gBACrB,KAAK;gBACL,OAAO,EAAE,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;gBACrC,eAAe;aAChB,CAAC,CAAC;QACL,KAAK,KAAK;YACR,OAAO,OAAO,CAAC,OAAO,CAAC;gBACrB,KAAK;gBACL,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;gBACxB,eAAe;aAChB,CAAC,CAAC;QACL;YACE,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACvC,CAAC;AACH,CAAC"}
|
package/lib/utils/types.d.ts
CHANGED
|
@@ -54,6 +54,18 @@ Only include tests that explicitly declare metadata dependencies matching change
|
|
|
54
54
|
|
|
55
55
|
When enabled with `manifest`, test selection is based on metadata changes (e.g., Flow, CustomObject) rather than Apex annotations.
|
|
56
56
|
|
|
57
|
+
# flags.fail-on-empty.summary
|
|
58
|
+
|
|
59
|
+
Fail with exit code 1 if no test methods are found.
|
|
60
|
+
|
|
61
|
+
# flags.fail-on-empty.description
|
|
62
|
+
|
|
63
|
+
If provided, the command exits with code 1 when no test methods are found. When combined with `--manifest`, the command still exits with code 0 if the manifest contains no `ApexClass` or `ApexTrigger` members, since there is nothing to test in that case.
|
|
64
|
+
|
|
65
|
+
# errors.noTestsFound
|
|
66
|
+
|
|
67
|
+
No test methods found.
|
|
68
|
+
|
|
57
69
|
# examples
|
|
58
70
|
|
|
59
71
|
- <%= config.bin %> <%= command.id %> --format csv
|
|
@@ -61,3 +73,4 @@ When enabled with `manifest`, test selection is based on metadata changes (e.g.,
|
|
|
61
73
|
- <%= config.bin %> <%= command.id %> --format sf --manifest package.xml
|
|
62
74
|
- <%= config.bin %> <%= command.id %> --format sf --manifest package.xml --ignore-missing-tests
|
|
63
75
|
- <%= config.bin %> <%= command.id %> --format sf --manifest package.xml -d "force-app"
|
|
76
|
+
- <%= config.bin %> <%= command.id %> --format sf --manifest package.xml --fail-on-empty
|
package/oclif.manifest.json
CHANGED
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"<%= config.bin %> <%= command.id %> --format sf",
|
|
10
10
|
"<%= config.bin %> <%= command.id %> --format sf --manifest package.xml",
|
|
11
11
|
"<%= config.bin %> <%= command.id %> --format sf --manifest package.xml --ignore-missing-tests",
|
|
12
|
-
"<%= config.bin %> <%= command.id %> --format sf --manifest package.xml -d \"force-app\""
|
|
12
|
+
"<%= config.bin %> <%= command.id %> --format sf --manifest package.xml -d \"force-app\"",
|
|
13
|
+
"<%= config.bin %> <%= command.id %> --format sf --manifest package.xml --fail-on-empty"
|
|
13
14
|
],
|
|
14
15
|
"flags": {
|
|
15
16
|
"json": {
|
|
@@ -84,6 +85,15 @@
|
|
|
84
85
|
"summary": "Only include tests that explicitly declare metadata dependencies matching changed metadata.",
|
|
85
86
|
"allowNo": false,
|
|
86
87
|
"type": "boolean"
|
|
88
|
+
},
|
|
89
|
+
"fail-on-empty": {
|
|
90
|
+
"char": "e",
|
|
91
|
+
"description": "If provided, the command exits with code 1 when no test methods are found. When combined with `--manifest`, the command still exits with code 0 if the manifest contains no `ApexClass` or `ApexTrigger` members, since there is nothing to test in that case.",
|
|
92
|
+
"name": "fail-on-empty",
|
|
93
|
+
"required": false,
|
|
94
|
+
"summary": "Fail with exit code 1 if no test methods are found.",
|
|
95
|
+
"allowNo": false,
|
|
96
|
+
"type": "boolean"
|
|
87
97
|
}
|
|
88
98
|
},
|
|
89
99
|
"hasDynamicHelp": false,
|
|
@@ -109,5 +119,5 @@
|
|
|
109
119
|
]
|
|
110
120
|
}
|
|
111
121
|
},
|
|
112
|
-
"version": "1.
|
|
122
|
+
"version": "1.15.0"
|
|
113
123
|
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "apextestlist",
|
|
3
3
|
"description": "A plugin that generates a list of apex test and test suite names for use in CI/CD pipelines.",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.15.0",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@oclif/core": "5.0.0",
|
|
7
|
-
"@salesforce/core": "9.1.
|
|
7
|
+
"@salesforce/core": "9.1.11",
|
|
8
8
|
"@salesforce/sf-plugins-core": "13.0.4"
|
|
9
9
|
},
|
|
10
10
|
"devDependencies": {
|
|
@@ -16,20 +16,21 @@
|
|
|
16
16
|
"@salesforce/dev-config": "4.3.3",
|
|
17
17
|
"@stryker-mutator/core": "10.0.0",
|
|
18
18
|
"@stryker-mutator/vitest-runner": "10.0.0",
|
|
19
|
-
"@types/node": "26.
|
|
19
|
+
"@types/node": "26.5.1",
|
|
20
20
|
"@vitest/coverage-v8": "5.0.0",
|
|
21
21
|
"esbuild": "0.28.2",
|
|
22
22
|
"husky": "9.1.7",
|
|
23
|
-
"
|
|
24
|
-
"
|
|
23
|
+
"knip": "6.35.1",
|
|
24
|
+
"lint-staged": "17.5.0",
|
|
25
|
+
"ls-engines": "0.10.1",
|
|
26
|
+
"oclif": "5.0.1",
|
|
25
27
|
"shx": "0.4.0",
|
|
26
|
-
"ts-node": "10.9.2",
|
|
27
28
|
"typescript": "7.0.2",
|
|
28
29
|
"vitest": "5.0.0",
|
|
29
30
|
"wireit": "0.14.13"
|
|
30
31
|
},
|
|
31
32
|
"engines": {
|
|
32
|
-
"node": ">=22 <=26"
|
|
33
|
+
"node": ">=22.19.0 <=26"
|
|
33
34
|
},
|
|
34
35
|
"files": [
|
|
35
36
|
"/lib",
|
|
@@ -73,6 +74,8 @@
|
|
|
73
74
|
"format": "wireit",
|
|
74
75
|
"link-check": "wireit",
|
|
75
76
|
"lint": "wireit",
|
|
77
|
+
"lint:dependencies": "wireit",
|
|
78
|
+
"lint:engine": "wireit",
|
|
76
79
|
"postpack": "shx rm -f oclif.manifest.json oclif.lock",
|
|
77
80
|
"prepack": "wireit",
|
|
78
81
|
"prepare": "husky",
|
|
@@ -169,6 +172,27 @@
|
|
|
169
172
|
],
|
|
170
173
|
"output": []
|
|
171
174
|
},
|
|
175
|
+
"lint:dependencies": {
|
|
176
|
+
"command": "knip",
|
|
177
|
+
"files": [
|
|
178
|
+
"src/**/*.ts",
|
|
179
|
+
"test/**/*.ts",
|
|
180
|
+
"knip.config.ts",
|
|
181
|
+
"package.json"
|
|
182
|
+
],
|
|
183
|
+
"output": [],
|
|
184
|
+
"dependencies": [
|
|
185
|
+
"lint"
|
|
186
|
+
]
|
|
187
|
+
},
|
|
188
|
+
"lint:engine": {
|
|
189
|
+
"command": "ls-engines --no-current --no-dev --mode=virtual",
|
|
190
|
+
"files": [
|
|
191
|
+
"package.json",
|
|
192
|
+
"package-lock.json"
|
|
193
|
+
],
|
|
194
|
+
"output": []
|
|
195
|
+
},
|
|
172
196
|
"prepack": {
|
|
173
197
|
"command": "oclif manifest && oclif readme",
|
|
174
198
|
"files": [
|
|
@@ -269,5 +293,8 @@
|
|
|
269
293
|
},
|
|
270
294
|
"exports": "./lib/index.js",
|
|
271
295
|
"type": "module",
|
|
272
|
-
"author": "Renato Oliveira"
|
|
296
|
+
"author": "Renato Oliveira",
|
|
297
|
+
"allowScripts": {
|
|
298
|
+
"esbuild@0.28.2": true
|
|
299
|
+
}
|
|
273
300
|
}
|