pastoralist 1.8.2 → 1.8.4
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/LICENSE +55 -21
- package/README.md +70 -20
- package/dist/cli/index.d.ts +9 -2
- package/dist/cli/parser/constants.d.ts +1 -1
- package/dist/core/packageJSON.d.ts +2 -1
- package/dist/core/security/providers/osv.d.ts +2 -0
- package/dist/core/security/providers/snyk.d.ts +2 -0
- package/dist/core/security/providers/socket.d.ts +2 -0
- package/dist/core/security/types.d.ts +1 -0
- package/dist/core/update/types.d.ts +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +34 -32
- package/dist/types.d.ts +22 -0
- package/dist/utils/logger.d.ts +3 -1
- package/dist/utils/spinner.d.ts +1 -0
- package/dist/utils/types.d.ts +2 -0
- package/package.json +5 -5
package/LICENSE
CHANGED
|
@@ -1,21 +1,55 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
1
|
+
Elastic License 2.0
|
|
2
|
+
|
|
3
|
+
URL: https://www.elastic.co/licensing/elastic-license
|
|
4
|
+
|
|
5
|
+
## Acceptance
|
|
6
|
+
|
|
7
|
+
By using the software, you agree to all of the terms and conditions below.
|
|
8
|
+
|
|
9
|
+
## Copyright License
|
|
10
|
+
|
|
11
|
+
The licensor grants you a non-exclusive, royalty-free, worldwide, non-sublicensable, non-transferable license to use, copy, distribute, make available, and prepare derivative works of the software, in each case subject to the limitations and conditions below.
|
|
12
|
+
|
|
13
|
+
## Limitations
|
|
14
|
+
|
|
15
|
+
You may not provide the software to third parties as a hosted or managed service, where the service provides users with access to any substantial set of the features or functionality of the software.
|
|
16
|
+
|
|
17
|
+
You may not move, change, disable, or circumvent the license key functionality in the software, and you may not remove or obscure any functionality in the software that is protected by the license key.
|
|
18
|
+
|
|
19
|
+
You may not alter, remove, or obscure any licensing, copyright, or other notices of the licensor in the software. Any use of the licensor's trademarks is subject to applicable law.
|
|
20
|
+
|
|
21
|
+
## Patents
|
|
22
|
+
|
|
23
|
+
The licensor grants you a license, under any patent claims the licensor can license, or becomes able to license, to make, have made, use, sell, offer for sale, import and have imported the software, subject to the limitations and conditions in this license. This license does not cover any patent claims that you cause to be infringed by modifications or additions to the software. If you or your company make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.
|
|
24
|
+
|
|
25
|
+
## Notices
|
|
26
|
+
|
|
27
|
+
You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms.
|
|
28
|
+
|
|
29
|
+
If you modify the software, you must include in any modified copies of the software prominent notices stating that you have modified the software.
|
|
30
|
+
|
|
31
|
+
## No Other Rights
|
|
32
|
+
|
|
33
|
+
These terms do not imply any licenses other than those expressly granted in these terms.
|
|
34
|
+
|
|
35
|
+
## Termination
|
|
36
|
+
|
|
37
|
+
If you use the software in violation of these terms, such use is not licensed, and your licenses will automatically terminate. If the licensor provides you with a notice of your violation, and you cease all violation of this license no later than 30 days after you receive that notice, your licenses will be reinstated retroactively. However, if you violate these terms after such reinstatement, any additional violation of these terms will cause your licenses to terminate automatically and permanently.
|
|
38
|
+
|
|
39
|
+
## No Liability
|
|
40
|
+
|
|
41
|
+
*As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.*
|
|
42
|
+
|
|
43
|
+
## Definitions
|
|
44
|
+
|
|
45
|
+
The **licensor** is the entity offering these terms, and the **software** is the software the licensor makes available under these terms, including any portion of it.
|
|
46
|
+
|
|
47
|
+
**you** refers to the individual or entity agreeing to these terms.
|
|
48
|
+
|
|
49
|
+
**your company** is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization. **control** means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.
|
|
50
|
+
|
|
51
|
+
**your licenses** are all the licenses granted to you for the software under these terms.
|
|
52
|
+
|
|
53
|
+
**use** means anything you do with the software requiring one of your licenses.
|
|
54
|
+
|
|
55
|
+
**trademark** means trademarks, service marks, and similar rights.
|
package/README.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
[](https://badge.fury.io/js/pastoralist)
|
|
4
4
|

|
|
5
5
|
[](https://codecov.io/gh/yowainwright/pastoralist)
|
|
6
|
+
<img referrerpolicy="no-referrer-when-downgrade" src="https://static.scarf.sh/a.png?x-pxid=6f41d7dd-fce9-49ea-ae43-040a51f458bd" />
|
|
6
7
|
|
|
7
8
|
Pastoralist provides a dead simple way to singularly maintain node module overrides AND security issues in dependencies.
|
|
8
9
|
|
|
@@ -111,9 +112,9 @@ No more mysteries. Every override is tracked.
|
|
|
111
112
|
```mermaid
|
|
112
113
|
flowchart LR
|
|
113
114
|
Install[npm install] --> Auto[Pastoralist runs]
|
|
114
|
-
Auto --> Track[
|
|
115
|
-
Auto --> Scan[
|
|
116
|
-
Auto --> Clean[
|
|
115
|
+
Auto --> Track[Tracks deps]
|
|
116
|
+
Auto --> Scan[Scans security]
|
|
117
|
+
Auto --> Clean[Cleans unused]
|
|
117
118
|
Track --> Done[✓ Done]
|
|
118
119
|
Scan --> Done
|
|
119
120
|
Clean --> Done
|
|
@@ -240,8 +241,8 @@ flowchart TD
|
|
|
240
241
|
|
|
241
242
|
- **OSV** (default) - No auth required
|
|
242
243
|
- **GitHub** - Requires token
|
|
243
|
-
- **Snyk** - Requires CLI
|
|
244
|
-
- **Socket** - Requires CLI
|
|
244
|
+
- **Snyk** [EXPERIMENTAL] - Requires CLI and token
|
|
245
|
+
- **Socket** [EXPERIMENTAL] - Requires CLI and token
|
|
245
246
|
|
|
246
247
|
### 3. Automatic Cleanup
|
|
247
248
|
|
|
@@ -283,12 +284,12 @@ Works seamlessly with `patch-package`. Automatically links patches to overrides
|
|
|
283
284
|
|
|
284
285
|
```mermaid
|
|
285
286
|
flowchart LR
|
|
286
|
-
You[You add override
|
|
287
|
+
You[You add override] --> Install[npm install]
|
|
287
288
|
Install --> Pastor[Pastoralist runs]
|
|
288
289
|
Pastor --> Track[Tracks it]
|
|
289
|
-
Pastor --> Scan[
|
|
290
|
-
Pastor --> Clean[
|
|
291
|
-
Track --> Chill[
|
|
290
|
+
Pastor --> Scan[Scans it]
|
|
291
|
+
Pastor --> Clean[Cleans if unused]
|
|
292
|
+
Track --> Chill[Back to coding]
|
|
292
293
|
Scan --> Chill
|
|
293
294
|
Clean --> Chill
|
|
294
295
|
|
|
@@ -556,16 +557,16 @@ When both external config files and `package.json` configuration exist:
|
|
|
556
557
|
|
|
557
558
|
#### Security Configuration
|
|
558
559
|
|
|
559
|
-
| Option | Type | Description
|
|
560
|
-
| ---------------------------- | ------------------------------------------------- |
|
|
561
|
-
| `enabled` | `boolean` | Enable/disable security checks
|
|
562
|
-
| `provider` | `"osv"` \| `"github"` \| `"snyk"` \| `"socket"` | Security provider: `osv` (free
|
|
563
|
-
| `autoFix` | `boolean` | Automatically apply security fixes
|
|
564
|
-
| `interactive` | `boolean` | Use interactive mode for security fixes
|
|
565
|
-
| `securityProviderToken` | `string` | API token for providers that require auth
|
|
566
|
-
| `severityThreshold` | `"low"` \| `"medium"` \| `"high"` \| `"critical"` | Minimum severity level to report
|
|
567
|
-
| `excludePackages` | `string[]` | Packages to exclude from security checks
|
|
568
|
-
| `hasWorkspaceSecurityChecks` | `boolean` | Include workspace packages in scans
|
|
560
|
+
| Option | Type | Description |
|
|
561
|
+
| ---------------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
562
|
+
| `enabled` | `boolean` | Enable/disable security checks |
|
|
563
|
+
| `provider` | `"osv"` \| `"github"` \| `"snyk"` \| `"socket"` | Security provider: `osv` (free, recommended), `github` (requires token, includes transitive deps), `snyk` [EXPERIMENTAL], `socket` [EXPERIMENTAL] |
|
|
564
|
+
| `autoFix` | `boolean` | Automatically apply security fixes |
|
|
565
|
+
| `interactive` | `boolean` | Use interactive mode for security fixes |
|
|
566
|
+
| `securityProviderToken` | `string` | API token for providers that require auth |
|
|
567
|
+
| `severityThreshold` | `"low"` \| `"medium"` \| `"high"` \| `"critical"` | Minimum severity level to report |
|
|
568
|
+
| `excludePackages` | `string[]` | Packages to exclude from security checks |
|
|
569
|
+
| `hasWorkspaceSecurityChecks` | `boolean` | Include workspace packages in scans |
|
|
569
570
|
|
|
570
571
|
### Security Tracking in Appendix
|
|
571
572
|
|
|
@@ -679,10 +680,59 @@ The workflow file is created at `.github/workflows/pastoralist.yml`. Commit it t
|
|
|
679
680
|
|
|
680
681
|
---
|
|
681
682
|
|
|
683
|
+
## GitHub Action
|
|
684
|
+
|
|
685
|
+
Pastoralist provides a GitHub Action for CI/CD integration.
|
|
686
|
+
|
|
687
|
+
### Quick Start
|
|
688
|
+
|
|
689
|
+
```yaml
|
|
690
|
+
name: Override Check
|
|
691
|
+
on: [pull_request]
|
|
692
|
+
|
|
693
|
+
jobs:
|
|
694
|
+
check:
|
|
695
|
+
runs-on: ubuntu-latest
|
|
696
|
+
steps:
|
|
697
|
+
- uses: actions/checkout@v4
|
|
698
|
+
- uses: yowainwright/pastoralist@v1
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
### Scheduled Security Maintenance
|
|
702
|
+
|
|
703
|
+
```yaml
|
|
704
|
+
name: Override Maintenance
|
|
705
|
+
on:
|
|
706
|
+
schedule:
|
|
707
|
+
- cron: "0 0 * * 1" # Weekly on Monday
|
|
708
|
+
|
|
709
|
+
jobs:
|
|
710
|
+
maintain:
|
|
711
|
+
runs-on: ubuntu-latest
|
|
712
|
+
steps:
|
|
713
|
+
- uses: actions/checkout@v4
|
|
714
|
+
- uses: yowainwright/pastoralist@v1
|
|
715
|
+
with:
|
|
716
|
+
mode: pr
|
|
717
|
+
pr-title: "chore(deps): update dependency overrides"
|
|
718
|
+
```
|
|
719
|
+
|
|
720
|
+
### Modes
|
|
721
|
+
|
|
722
|
+
| Mode | Description |
|
|
723
|
+
| -------- | ------------------------------------------------------ |
|
|
724
|
+
| `check` | Validate only - reports issues without modifying files |
|
|
725
|
+
| `update` | Modify package.json (default) - you handle commits |
|
|
726
|
+
| `pr` | Create pull request with changes |
|
|
727
|
+
|
|
728
|
+
See [ACTION.md](.github/ACTION.md) for full documentation including all inputs, outputs, and examples.
|
|
729
|
+
|
|
730
|
+
---
|
|
731
|
+
|
|
682
732
|
## Thanks
|
|
683
733
|
|
|
684
734
|
Shout out to [Bryant Cabrera](https://github.com/bryantcabrera) and the infamous [Mardin](https://github.com/mardinyadegar) for all the fun conversation, insights, and pairing around this topic.
|
|
685
735
|
|
|
686
736
|
---
|
|
687
737
|
|
|
688
|
-
Made by [@yowainwright](https://github.com/yowainwright) for fun with passion!
|
|
738
|
+
Made by [@yowainwright](https://github.com/yowainwright) for fun with passion! [Elastic-2.0](LICENSE), 2022
|
package/dist/cli/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createSpinner } from "../utils";
|
|
3
|
-
import { Options, PastoralistJSON, SecurityAlert, SecurityOverride, SecurityOverrideDetail } from "../types";
|
|
3
|
+
import { Options, PastoralistJSON, PastoralistResult, SecurityAlert, SecurityOverride, SecurityOverrideDetail } from "../types";
|
|
4
|
+
import { update } from "../core/update";
|
|
4
5
|
import { logger as createLogger } from "../utils";
|
|
5
6
|
import { SecurityChecker } from "../core/security";
|
|
6
7
|
import { initCommand } from "./cmds/init/index";
|
|
@@ -25,11 +26,17 @@ export declare const runSecurityCheck: (config: PastoralistJSON, mergedOptions:
|
|
|
25
26
|
export declare const handleSecurityResults: (alerts: SecurityAlert[], securityOverrides: SecurityOverride[], securityChecker: SecurityChecker, spinner: ReturnType<typeof createSpinner>, mergedOptions: Options, updates?: import("../types").OverrideUpdate[]) => void;
|
|
26
27
|
export declare const formatUpdateReport: (updates: import("../types").OverrideUpdate[]) => string;
|
|
27
28
|
export declare function determineSecurityScanPaths(config: PastoralistJSON | undefined, mergedOptions: Options, log?: ReturnType<typeof createLogger>): string[];
|
|
29
|
+
export declare const createEmptyResult: () => PastoralistResult;
|
|
30
|
+
export declare const createErrorResult: (error: unknown) => PastoralistResult;
|
|
31
|
+
export declare const buildSecurityResult: (alerts: SecurityAlert[]) => Pick<PastoralistResult, "hasSecurityIssues" | "securityAlertCount" | "securityAlerts">;
|
|
32
|
+
export declare const buildUpdateResult: (updateResult: ReturnType<typeof update>, config: PastoralistJSON | undefined, isDryRun: boolean) => Pick<PastoralistResult, "overrideCount" | "appliedOverrides" | "updated">;
|
|
33
|
+
export declare const outputResult: (result: PastoralistResult, isJsonOutput: boolean) => void;
|
|
28
34
|
export declare function action(options?: Options, deps?: {
|
|
29
35
|
createLogger: ({ file, isLogging }: import("../utils").LoggerOptions) => {
|
|
30
36
|
debug: (msg: string, caller?: string, ...args: unknown[]) => void;
|
|
31
37
|
error: (msg: string, caller?: string, ...args: unknown[]) => void;
|
|
32
38
|
info: (msg: string, caller?: string, ...args: unknown[]) => void;
|
|
39
|
+
warn: (msg: string, caller?: string, ...args: unknown[]) => void;
|
|
33
40
|
};
|
|
34
41
|
handleTestMode: (isTestingCLI: boolean, log: ReturnType<typeof createLogger>, options: Options) => boolean;
|
|
35
42
|
handleInitMode: (init: boolean, options: Options, rest: Omit<Options, "isTestingCLI" | "init">, deps?: {
|
|
@@ -54,5 +61,5 @@ export declare function action(options?: Options, deps?: {
|
|
|
54
61
|
green: (text: string) => string;
|
|
55
62
|
update: (options: Options) => import("../types").UpdateContext;
|
|
56
63
|
processExit: (code: number) => never;
|
|
57
|
-
}): Promise<
|
|
64
|
+
}): Promise<PastoralistResult>;
|
|
58
65
|
export declare const run: (argv?: string[]) => Promise<void>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { OptionDefinition } from "./types";
|
|
2
2
|
export declare const OPTION_DEFINITIONS: OptionDefinition[];
|
|
3
|
-
export declare const HELP_TEXT = "\nPastoralist - A utility CLI to manage your dependency overrides\n\nUsage: pastoralist [command] [options]\n\nCommands:\n init Initialize Pastoralist configuration interactively\n\nOptions:\n --debug Enable debug mode\n --dry-run Preview changes without writing to package.json\n -p, --path <path> Specifies a path to a package.json (default: \"package.json\")\n -d, --depPaths [paths...] Specifies glob paths to package.jsons\n --ignore [paths...] Specifies glob paths to ignore\n -r, --root <root> Specifies a root path\n -t, --isTestingCLI Enable CLI testing (no scripts run)\n --isTesting Enable testing mode (no scripts run)\n --init Initialize Pastoralist configuration interactively\n --checkSecurity Check for security vulnerabilities and generate overrides\n --forceSecurityRefactor Automatically apply security overrides without prompting\n --securityProvider <provider...> Security provider(s) to use (osv, github, snyk, npm, socket)\n --securityProviderToken <token> Security provider token for API access\n --interactive Run security checks in interactive mode\n --hasWorkspaceSecurityChecks Include workspace packages in security scan\n --promptForReasons Prompt for reasons when adding manual overrides\n";
|
|
3
|
+
export declare const HELP_TEXT = "\nPastoralist - A utility CLI to manage your dependency overrides\n\nUsage: pastoralist [command] [options]\n\nCommands:\n init Initialize Pastoralist configuration interactively\n\nOptions:\n --debug Enable debug mode\n --dry-run Preview changes without writing to package.json\n --outputFormat <format> Output format: text (default) or json\n -p, --path <path> Specifies a path to a package.json (default: \"package.json\")\n -d, --depPaths [paths...] Specifies glob paths to package.jsons\n --ignore [paths...] Specifies glob paths to ignore\n -r, --root <root> Specifies a root path\n -t, --isTestingCLI Enable CLI testing (no scripts run)\n --isTesting Enable testing mode (no scripts run)\n --init Initialize Pastoralist configuration interactively\n --checkSecurity Check for security vulnerabilities and generate overrides\n --forceSecurityRefactor Automatically apply security overrides without prompting\n --securityProvider <provider...> Security provider(s) to use (osv, github, snyk, npm, socket)\n --securityProviderToken <token> Security provider token for API access\n --interactive Run security checks in interactive mode\n --hasWorkspaceSecurityChecks Include workspace packages in security scan\n --promptForReasons Prompt for reasons when adding manual overrides\n --strict Fail on any security check errors (network failures, API errors)\n";
|
|
4
4
|
export declare const ARGS_START_INDEX = 2;
|
|
@@ -10,7 +10,7 @@ export declare const getExistingOverrideField: (config: PastoralistJSON) => "res
|
|
|
10
10
|
export declare const getOverrideFieldForPackageManager: (packageManager: "npm" | "yarn" | "pnpm" | "bun") => "resolutions" | "overrides" | "pnpm";
|
|
11
11
|
export declare const applyOverridesToConfig: (config: PastoralistJSON, overrides: Record<string, OverrideValue> | Record<string, string>, fieldType: "resolutions" | "overrides" | "pnpm" | null) => PastoralistJSON;
|
|
12
12
|
export declare const resolveJSON: (path: string) => PastoralistJSON | undefined;
|
|
13
|
-
export declare const updatePackageJSON: ({ appendix, path, config, overrides, isTesting, dryRun, }: UpdatePackageJSONOptions) => PastoralistJSON | void;
|
|
13
|
+
export declare const updatePackageJSON: ({ appendix, path, config, overrides, isTesting, dryRun, silent, }: UpdatePackageJSONOptions) => PastoralistJSON | void;
|
|
14
14
|
export declare const parseNpmLsOutput: (stdout: string) => Record<string, boolean>;
|
|
15
15
|
export declare const executeNpmLs: () => Promise<string>;
|
|
16
16
|
export declare const getDependencyTree: () => Promise<Record<string, boolean>>;
|
|
@@ -19,4 +19,5 @@ export declare const findPackageJsonFiles: (depPaths: string[], ignore?: string[
|
|
|
19
19
|
debug: (msg: string, caller?: string, ...args: unknown[]) => void;
|
|
20
20
|
error: (msg: string, caller?: string, ...args: unknown[]) => void;
|
|
21
21
|
info: (msg: string, caller?: string, ...args: unknown[]) => void;
|
|
22
|
+
warn: (msg: string, caller?: string, ...args: unknown[]) => void;
|
|
22
23
|
}) => string[];
|
|
@@ -4,12 +4,14 @@ export declare class OSVProvider {
|
|
|
4
4
|
protected debug: boolean;
|
|
5
5
|
protected isIRLFix: boolean;
|
|
6
6
|
protected isIRLCatch: boolean;
|
|
7
|
+
protected strict: boolean;
|
|
7
8
|
protected log: ReturnType<typeof logger>;
|
|
8
9
|
protected retryOptions: RetryOptions;
|
|
9
10
|
constructor(options?: {
|
|
10
11
|
debug?: boolean;
|
|
11
12
|
isIRLFix?: boolean;
|
|
12
13
|
isIRLCatch?: boolean;
|
|
14
|
+
strict?: boolean;
|
|
13
15
|
retryOptions?: RetryOptions;
|
|
14
16
|
});
|
|
15
17
|
isAvailable(): Promise<boolean>;
|
|
@@ -3,9 +3,11 @@ export declare class SnykCLIProvider {
|
|
|
3
3
|
private log;
|
|
4
4
|
private installer;
|
|
5
5
|
private token?;
|
|
6
|
+
private strict;
|
|
6
7
|
constructor(options?: {
|
|
7
8
|
debug?: boolean;
|
|
8
9
|
token?: string;
|
|
10
|
+
strict?: boolean;
|
|
9
11
|
});
|
|
10
12
|
ensureInstalled(): Promise<boolean>;
|
|
11
13
|
isAuthenticated(): Promise<boolean>;
|
|
@@ -3,9 +3,11 @@ export declare class SocketCLIProvider {
|
|
|
3
3
|
private log;
|
|
4
4
|
private installer;
|
|
5
5
|
private token?;
|
|
6
|
+
private strict;
|
|
6
7
|
constructor(options?: {
|
|
7
8
|
debug?: boolean;
|
|
8
9
|
token?: string;
|
|
10
|
+
strict?: boolean;
|
|
9
11
|
});
|
|
10
12
|
ensureInstalled(): Promise<boolean>;
|
|
11
13
|
isAuthenticated(): Promise<boolean>;
|
package/dist/index.d.ts
CHANGED
|
@@ -8,5 +8,5 @@ export { detectPatches, attachPatchesToAppendix, findUnusedPatches, } from "./co
|
|
|
8
8
|
export { SecurityChecker } from "./core/security";
|
|
9
9
|
export { loadConfig, loadExternalConfig, mergeConfigs, clearConfigCache, } from "./config";
|
|
10
10
|
export { logMethod, logger } from "./utils";
|
|
11
|
-
export type { Options, PastoralistJSON, PastoralistConfig, Appendix, AppendixItem, OverridesType, OverrideValue, SecurityOverrideDetail, UpdatePackageJSONOptions, SecurityAlert, SecurityCheckOptions, SecurityOverride, SecurityProvider, } from "./types";
|
|
11
|
+
export type { Options, PastoralistJSON, PastoralistConfig, PastoralistResult, Appendix, AppendixItem, OverridesType, OverrideValue, SecurityOverrideDetail, UpdatePackageJSONOptions, SecurityAlert, SecurityCheckOptions, SecurityOverride, SecurityProvider, } from "./types";
|
|
12
12
|
export declare const findRemovableAppendixItems: (appendix: import("./types").Appendix) => Array<string>;
|
package/dist/index.js
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{createRequire as
|
|
3
|
-
`)},
|
|
4
|
-
`},
|
|
5
|
-
`).length},
|
|
6
|
-
[DRY RUN] Would write to package.json:`),console.log(
|
|
7
|
-
${
|
|
2
|
+
import{createRequire as Pn}from"node:module";var mn=Object.create;var{getPrototypeOf:bn,defineProperty:G,getOwnPropertyNames:mt,getOwnPropertyDescriptor:vn}=Object,bt=Object.prototype.hasOwnProperty;var Sn=(e,t,r)=>{r=e!=null?mn(bn(e)):{};let n=t||!e||!e.__esModule?G(r,"default",{value:e,enumerable:!0}):r;for(let i of mt(e))if(!bt.call(n,i))G(n,i,{get:()=>e[i],enumerable:!0});return n},yt=new WeakMap,On=(e)=>{var t=yt.get(e),r;if(t)return t;if(t=G({},"__esModule",{value:!0}),e&&typeof e==="object"||typeof e==="function")mt(e).map((n)=>!bt.call(t,n)&&G(t,n,{get:()=>e[n],enumerable:!(r=vn(e,n))||r.enumerable}));return yt.set(e,t),t};var vt=(e,t)=>{for(var r in t)G(e,r,{get:t[r],enumerable:!0,configurable:!0,set:(n)=>t[r]=()=>n})};var f=(e,t)=>()=>(e&&(t=e(e=0)),t);var St=Pn(import.meta.url);var k,Ce="\uD83D\uDC11 \uD83D\uDC69\uD83C\uDFFD\uD83C\uDF3E Pastoralist:",ne,we,Re,An,kn,xn,Cn,wn,Rn,Tn,Ot,Pt,At,Te;var T=f(()=>{k=process.env.DEBUG==="true"||!1,ne={MOCK_MODE:"PASTORALIST_MOCK_SECURITY",FORCE_VULNERABLE:"MOCK_FORCE_VULNERABLE",MOCK_FILE:"MOCK_ALERTS_FILE",GITHUB_TOKEN:"GITHUB_TOKEN"},we={ecosystem:"npm",name:"lodash"},Re={ecosystem:"npm",name:"minimist"},An={package:we,manifest_path:"package.json",scope:"runtime"},kn={package:we,vulnerable_version_range:"< 4.17.21",first_patched_version:{identifier:"4.17.21"}},xn={package:Re,vulnerable_version_range:"< 1.2.6",first_patched_version:{identifier:"1.2.6"}},Cn={severity:"high",summary:"Mock vulnerability in lodash",description:"Mock description",vulnerabilities:[kn]},wn={severity:"medium",summary:"Mock vulnerability in minimist",description:"Mock description",vulnerabilities:[xn]},Rn={package:we,severity:"high",vulnerable_version_range:"< 4.17.21",first_patched_version:{identifier:"4.17.21"}},Tn={package:Re,severity:"medium",vulnerable_version_range:"< 1.2.6",first_patched_version:{identifier:"1.2.6"}},Ot={url:"https://mock.url",html_url:"https://mock.url",created_at:"2021-01-01T00:00:00Z",updated_at:"2021-01-01T00:00:00Z"},Pt={number:1,state:"open",dependency:An,security_advisory:Cn,security_vulnerability:Rn,...Ot},At={number:2,state:"open",dependency:{package:Re,manifest_path:"package.json",scope:"runtime"},security_advisory:wn,security_vulnerability:Tn,...Ot},Te={OVERRIDE_TO_KEEP:{packageName:"fake-pastoralist-check-2",fromVersion:"1.0.0",toVersion:"2.1.0",key:"fake-pastoralist-check-2@2.1.0",dependents:{"fake-pastoralist-check-1":"1.0.0"},ledger:{addedDate:"2024-01-15T10:00:00.000Z",reason:"Security fix: Critical vulnerability in fake-pastoralist-check-1 transitive dependency (critical)",securityChecked:!0,securityCheckDate:"2024-01-15T10:00:00.000Z",securityProvider:"osv"}},OVERRIDE_TO_REMOVE:{packageName:"fake-pastoralist-check-3",fromVersion:"0.8.0",toVersion:"1.0.0",key:"fake-pastoralist-check-3@1.0.0",dependents:{},ledger:{addedDate:"2023-06-01T10:00:00.000Z",reason:"Manual override for compatibility testing"}},ALERT_TO_RESOLVE:{packageName:"fake-pastoralist-check-2",currentVersion:"1.0.0",vulnerableVersions:"< 2.1.0",patchedVersion:"2.1.0",severity:"critical",title:"Critical vulnerability in fake-pastoralist-check-2 (transitive from fake-pastoralist-check-1)",cve:"CVE-FAKE-PASTORALIST-2024-0001",fixAvailable:!0,description:"Fake critical security vulnerability in fake-pastoralist-check-2. Used by fake-pastoralist-check-1@1.0.0.",url:"https://example.com/fake-pastoralist-advisory-0001"},ALERT_TO_CAPTURE:{packageName:"fake-pastoralist-check-4",currentVersion:"0.5.0",vulnerableVersions:"< 1.0.0",patchedVersion:void 0,severity:"high",title:"High severity issue in fake-pastoralist-check-4 with no patch available",cve:"CVE-FAKE-PASTORALIST-2024-0002",fixAvailable:!1,description:"Fake high severity vulnerability with no available patch for testing alert capture functionality.",url:"https://example.com/fake-pastoralist-advisory-0002"}}});var kt,xt=()=>{process.stdout.write("\x1B[?25l")},L=()=>{process.stdout.write("\x1B[?25h")},ie=()=>{process.stdout.write("\r\x1B[K")},Ct=(e,t,r)=>{let n=e[t];ie(),process.stdout.write(`${n} ${r}`)},j=(e)=>{let t=e.interval;if(t!==null)clearInterval(t);return Object.assign({},e,{interval:null,isSpinning:!1})},wt=(e,t)=>{return Object.assign({},e,{text:t})},Rt=(e)=>{let t=(e.frameIndex+1)%kt.length;return Object.assign({},e,{frameIndex:t})},Tt=(e)=>{let t=setInterval(()=>{Ct(kt,e.frameIndex,e.text),Object.assign(e,Rt(e))},80);return Object.assign({},e,{interval:t,isSpinning:!0})},H=(e,t)=>{ie(),process.stdout.write(`${e} ${t}
|
|
3
|
+
`)},Vt=(e)=>{if(e.isSpinning)return w(e);xt();let r=Tt(e);return Object.assign(e,r),w(e)},$t=(e)=>{if(!e.isSpinning)return w(e);let r=j(e);return Object.assign(e,r),ie(),L(),w(e)},It=(e,t)=>{let r=j(e);Object.assign(e,r);let n=t||e.text;return H("✔",n),L(),w(e)},Et=(e,t)=>{let r=j(e);Object.assign(e,r);let n=t||e.text;return H("✖",n),L(),w(e)},Ft=(e,t)=>{let r=j(e);Object.assign(e,r);let n=t||e.text;return H("ℹ",n),L(),w(e)},Nt=(e,t)=>{let r=j(e);Object.assign(e,r);let n=t||e.text;return H("⚠",n),L(),w(e)},Vn=(e,t)=>{let r=wt(e,t);return Object.assign(e,r),w(e)},w=(e)=>{return{start:()=>Vt(e),stop:()=>$t(e),succeed:(t)=>It(e,t),fail:(t)=>Et(e,t),info:(t)=>Ft(e,t),warn:(t)=>Nt(e,t),update:(t)=>Vn(e,t)}},$n=(e)=>{return w({text:e,isSpinning:!1,frameIndex:0,interval:null})},se;var Ve=f(()=>{kt=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"],se=$n});var C=(e)=>{return`\x1B[32m${e}\x1B[0m`},K=(e)=>{return`\x1B[31m${e}\x1B[0m`},$e=(e)=>{return`\x1B[33m${e}\x1B[0m`},Ie=(e)=>{return`\x1B[36m${e}\x1B[0m`},Lt=(e)=>{return`\x1B[90m${e}\x1B[0m`};var B=(e,t,r)=>{return(n,i,...s)=>{if(!t)return;let o=i?`[${i}]`:"",a=`${Ce}[${r}]${o} ${n}`;if(e==="debug")console.debug(a,...s);else if(e==="error")console.error(a,...s);else if(e==="info")console.info(a,...s);else if(e==="warn")console.warn(a,...s)}},In=(e)=>{return(t,r,...n)=>{let i=r?`[${r}]`:"",s=`${Ce}[${e}]${i} ${t}`;console.warn(s,...n)}},y=({file:e,isLogging:t=!1})=>({debug:B("debug",t,e),error:B("error",t,e),info:B("info",t,e),warn:In(e)});var jt=f(()=>{T()});function $(e,t){let r=e.split(".").map(Number),n=t.split(".").map(Number),i=Math.max(r.length,n.length);return Array.from({length:i}).reduce((s,o,a)=>{if(s!==0)return s;let c=r[a]||0,l=n[a]||0;return c-l},0)}class oe{max;ttl;cache;head;tail;constructor(e){this.max=e.max,this.ttl=e.ttl,this.cache=new Map,this.head=null,this.tail=null}get(e){let t=this.cache.get(e);if(!t)return;if(this.isExpired(t)){this.delete(e);return}return this.moveToFront(t),t.value}set(e,t){let r=this.cache.get(e);if(r){r.value=t,r.timestamp=Date.now(),this.moveToFront(r);return}let n={key:e,value:t,prev:null,next:null,timestamp:Date.now()};if(this.cache.set(e,n),this.addToFront(n),this.cache.size>this.max)this.evictLRU()}has(e){let t=this.cache.get(e);if(!t)return!1;if(this.isExpired(t))return this.delete(e),!1;return!0}delete(e){let t=this.cache.get(e);if(!t)return!1;return this.removeNode(t),this.cache.delete(e),!0}clear(){this.cache.clear(),this.head=null,this.tail=null}get size(){return this.cache.size}keys(){return Array.from(this.cache.keys())}values(){let e=[],t=this.head;while(t){if(!this.isExpired(t))e.push(t.value);t=t.next}return e}isExpired(e){if(!this.ttl)return!1;return Date.now()-e.timestamp>this.ttl}moveToFront(e){if(e===this.head)return;this.removeNode(e),this.addToFront(e)}addToFront(e){if(e.next=this.head,e.prev=null,this.head)this.head.prev=e;if(this.head=e,!this.tail)this.tail=e}removeNode(e){if(e.prev)e.prev.next=e.next;else this.head=e.next;if(e.next)e.next.prev=e.prev;else this.tail=e.prev}evictLRU(){if(!this.tail)return;this.cache.delete(this.tail.key),this.removeNode(this.tail)}}var ae,En=(e,t,r)=>{let n=e;return n.attemptNumber=t,n.retriesLeft=r,n},Fn=(e,t,r,n)=>{let i=r*Math.pow(t,e-1);return Math.min(i,n)},Nn=(e)=>{return new Promise((t)=>setTimeout(t,e))},U=async(e,t={})=>{let{retries:r=ae.retries,factor:n=ae.factor,minTimeout:i=ae.minTimeout,maxTimeout:s=ae.maxTimeout,onFailedAttempt:o,onRetry:a}=t,c=0,l=async()=>{c++;try{return await e()}catch(u){let d=r-c,g=d>=0,p=Math.max(0,d),h=En(u instanceof Error?u:Error(String(u)),c,p);if(!g)throw h;if(o)await o(h);if(a)a(c,p);let m=Fn(c,n,i,s);return await Nn(m),l()}};return l()};var Ut=f(()=>{ae={retries:3,factor:2,minTimeout:1000,maxTimeout:30000}});var P=f(()=>{Ve();Ve();jt();Ut()});import{globSync as Ln}from"node:fs";import{glob as jn}from"node:fs/promises";import{resolve as Dt,relative as _t}from"node:path";function ce(e,t={}){let{cwd:r=process.cwd(),ignore:n=[],absolute:i=!1}=t,s=Array.isArray(e)?e:[e],o=new Set;for(let a of s){let c=Ln(a,{cwd:r,exclude:n});for(let l of c){let u=Dt(r,l),d=i?u:_t(r,u);o.add(d)}}return Array.from(o).sort()}async function Mt(e,t={}){let{cwd:r=process.cwd(),ignore:n=[],absolute:i=!1}=t,s=Array.isArray(e)?e:[e],o=new Set;for(let a of s){let c=jn(a,{cwd:r,exclude:n});for await(let l of c){let u=Dt(r,l),d=i?u:_t(r,u);o.add(d)}}return Array.from(o).sort()}var ue=()=>{};import*as D from"fs";import{resolve as q}from"path";import{execFile as Un}from"node:child_process";import{promisify as Dn}from"util";var _n,J,le=null,V,Mn=()=>{return{size:V.size,keys:Array.from(V.keys())}},Wn=()=>{let e=V.size;return V.clear(),J.debug(`Cache cleared. Had ${e} entries`,"forceClearCache"),e},Ee=(e)=>{let t=process.cwd(),r=q(t,e);return D.existsSync(r)},Gt=()=>{if(Ee("bun.lockb"))return"bun";if(Ee("yarn.lock"))return"yarn";if(Ee("pnpm-lock.yaml"))return"pnpm";return"npm"},Gn=(e)=>{return e?.resolutions!==void 0},Hn=(e)=>{return e?.overrides!==void 0},Kn=(e)=>{return e?.pnpm?.overrides!==void 0},Ht=(e)=>{if(Gn(e))return"resolutions";if(Hn(e))return"overrides";if(Kn(e))return"pnpm";return null},Kt=(e)=>{return{yarn:"resolutions",pnpm:"pnpm",npm:"overrides",bun:"overrides"}[e]},Bn=(e,t)=>{return{...e,resolutions:t}},qn=(e,t)=>{let r=e.pnpm||{};return{...e,pnpm:{...r,overrides:t}}},Jn=(e,t)=>{return{...e,overrides:t}},Bt=(e,t,r)=>{if(r==="resolutions")return Bn(e,t);if(r==="pnpm")return qn(e,t);if(r==="overrides")return Jn(e,t);return e},Yn=(e)=>{try{let t=D.readFileSync(e,"utf8");return JSON.parse(t)}catch(t){J.error(`Invalid JSON at: ${e}`,"parseJsonFile",t);return}},R=(e)=>{let t=q(e),r=V.get(t);if(r)return r;let n=Yn(t);if(n)V.set(t,n);return n},zn=(e)=>{let t=Boolean(e.pastoralist?.overridePaths),r=Boolean(e.pastoralist?.resolutionPaths),n=Boolean(e.pastoralist?.security),i=Boolean(e.pastoralist?.depPaths);return t||r||n||i},Fe=(e)=>{let t=e.pastoralist?.depPaths,r=e.pastoralist?.overridePaths,n=e.pastoralist?.resolutionPaths,i=e.pastoralist?.security;return{...t&&{depPaths:t},...r&&{overridePaths:r},...n&&{resolutionPaths:n},...i&&{security:i}}},Xn=(e)=>{let{resolutions:t,overrides:r,pnpm:n,...i}=e;if(!n)return i;let{overrides:s,...o}=n,a=Object.keys(o).length>0;return{...i,...a&&{pnpm:o}}},Qn=(e)=>{if(!zn(e)){let{pastoralist:n,...i}=e;return i}let r=Fe(e);return{...e,pastoralist:r}},Zn=(e,t)=>{let r=Fe(e);return{...e,pastoralist:{appendix:t,...r}}},ei=(e)=>{let t=Xn(e);return Qn(t)},ti=(e,t,r,n)=>{let i=t&&Object.keys(t).length>0,s;if(i)s=Zn(e,t);else{let l=Fe(e),u=Object.keys(l).length>0,{pastoralist:d,...g}=e;s=u?{...g,pastoralist:l}:g}if(!(r&&Object.keys(r).length>0))return s;let c=Ht(s)||(n?null:Kt(Gt()));return Bt(s,r,c)},ri=(e)=>{return JSON.stringify(e,null,2)+`
|
|
4
|
+
`},ni=(e)=>{if(!e.pastoralist)return 0;return JSON.stringify(e.pastoralist,null,2).split(`
|
|
5
|
+
`).length},ii=(e)=>{return ni(e)>10},si=(e,t)=>{let r=q(e),n=q(process.cwd(),"package.json");if(r===n)try{let s=JSON.parse(t);if(!Boolean(s.name))return}catch{return}D.writeFileSync(r,t)},Ne=({appendix:e,path:t,config:r,overrides:n,isTesting:i=!1,dryRun:s=!1,silent:o=!1})=>{let a=n&&Object.keys(n).length>0,c=e&&Object.keys(e).length>0,u=a||c?ti(r,e,n||{},i):ei(r);if(i)return u;let d=ri(u);if(s&&!o)console.log(`
|
|
6
|
+
[DRY RUN] Would write to package.json:`),console.log(d);if(s)return u;if(k)J.debug(`Writing updated package.json:
|
|
7
|
+
${d}`,"updatePackageJSON");si(t,d);let p=q(t);if(V.delete(p),ii(u))console.log(`
|
|
8
8
|
\uD83D\uDCA1 Tip: Your pastoralist config is getting large (>10 lines).`),console.log(" Consider moving it to a .pastoralistrc file using:"),console.log(` pastoralist init --useRcConfigFile
|
|
9
|
-
`)},qn=(e)=>{let t=JSON.parse(e),r={},n=(s)=>{if(!(s&&typeof s==="object"))return;Object.entries(s).forEach(([a,c])=>{if(r[a]=!0,c&&typeof c==="object"&&"dependencies"in c)n(c.dependencies)})};if(t.dependencies)n(t.dependencies);return r},Jn=async()=>{try{let{stdout:e}=await wn("npm",["ls","--json","--all"],{encoding:"utf8",maxBuffer:10485760,timeout:3000});return e}catch(e){let t=e;if(t.code===1&&t.stdout)return t.stdout;throw e}},Wt=async()=>{if(ce!==null)return ce;try{let t=await Jn(),r=qn(t);return ce=r,r}catch(t){return q.debug("Failed to get dependency tree","getDependencyTree",t),{}}},Fe=()=>{ce=null},Ne=(e,t=[],r="./",n=q)=>{if(e.length===0)throw n.error("No depPaths provided","findPackageJsonFiles"),Error("No depPaths provided to findPackageJsonFiles");try{n.debug(`Searching with patterns: ${e.join(", ")}, ignoring: ${t.join(", ")}, cwd: ${r}`,"findPackageJsonFiles");let s=oe(e,{cwd:r,ignore:t,absolute:!1,onlyFiles:!0});if(s.length===0){let a=`No package.json files found matching patterns: ${e.join(", ")} in directory: ${r}`;throw n.error(a,"findPackageJsonFiles"),Error(a)}return n.debug(`Found ${s.length} files`,"findPackageJsonFiles"),s}catch(s){throw n.error("Error finding package.json files","findPackageJsonFiles",s),s}};var I=f(()=>{ae();R();P();wn=Cn(xn),q=y({file:"packageJSON.ts",isLogging:k}),V=new Map});var le,zn=(e,t)=>{return Boolean(t[e])},Yn=(e,t)=>{return e.filter((r)=>!zn(r,t))},Xn=(e,t)=>{return e>0&&!t},Ee=(e,t,r,n)=>{let i=Object.keys(e),s=Yn(i,t),o=Boolean(n?.depPaths);if(Xn(s.length,o))r.info(`\uD83D\uDC11 Found overrides for packages not in root dependencies: ${s.join(", ")}`,"checkMonorepoOverrides"),r.info("\uD83D\uDCA1 For monorepo support, use --depPaths flag or add depPaths configuration in package.json","checkMonorepoOverrides");return s},Qn=(e)=>{let t=e?.dependencies||{},r=e?.devDependencies||{},n=e?.peerDependencies||{};return{...t,...r,...n}},Zn=(e)=>{return e.map((r)=>w(r)).reduce((r,n)=>{if(!Boolean(n))return r;let s=Qn(n);return{...r,...s}},{})},Gt=(e,t,r,n)=>{let i=n(e,t,r),s=Zn(e);return{appendix:i,allWorkspaceDeps:s}},ei=(e,t)=>{let r=Boolean(e),n=t.length>0;return r&&n},ti=(e,t)=>{return{...e,dependents:{...e.dependents,...t.dependents}}},Le=(e,t,r,n)=>{if(!ei(t,r))return e;return n.debug("Using overridePaths configuration for monorepo support","mergeOverridePaths"),Object.values(t).forEach((s)=>{Object.entries(s).forEach(([o,a])=>{if(e[o])e[o]=ti(e[o],a);else e[o]=a})}),e},Ht=(e,t)=>{return typeof t[e]==="object"},Bt=(e,t)=>{return Boolean(t[e])},ri=(e,t,r)=>{if(!Ht(e,t))return!1;if(Bt(e,r))return!1;return le.debug(`Found unused nested override for ${e}: parent package not in dependencies`,"isUnusedNestedOverride"),!0},ni=async(e,t,r)=>{if(Ht(e,t))return!1;if(Bt(e,r))return!1;if(!(Object.keys(r).length>0))return le.debug(`Found unused override for ${e}: no dependencies at all`,"isUnusedSimpleOverride"),!0;let o=await Wt();if(Boolean(o[e]))return le.debug(`Keeping override for ${e}: found in dependency tree`,"isUnusedSimpleOverride"),!1;return le.debug(`Found unused override for ${e}: not in dependency tree`,"isUnusedSimpleOverride"),!0},ii=async(e,t,r)=>{if(ri(e,t,r))return!0;return ni(e,t,r)},Kt=async(e,t)=>{let r=Object.keys(e),n=await Promise.all(r.map((i)=>ii(i,e,t)));return r.filter((i,s)=>n[s])},si=(e,t)=>{if(!t)return!1;return Object.values(t).some((r)=>Object.keys(r).some((n)=>n.startsWith(`${e}@`)))},oi=(e,t)=>{return e.filter((r)=>si(r,t))},ai=(e,t)=>{return e.filter((r)=>!t.includes(r))},ci=(e,t,r)=>{return t.reduce((n,i)=>{return Object.keys(n).filter((o)=>o.startsWith(`${i}@`)).reduce((o,a)=>{r.debug(`Removed appendix entry for ${a}`,"removeAppendixEntries");let{[a]:c,...l}=o;return l},n)},e)},li=async(e,t,r,n,i,s,o,a)=>{let c=await Kt(e,n);if(c.length===0)return{finalOverrides:e,finalAppendix:r};let u=oi(i,s),d=ai(c,u);if(d.length>0){o.debug(`Found ${d.length} packages to remove from overrides: ${d.join(", ")}`,"cleanupUnusedOverrides");let g=a(t,d)||e,b=ci(r,d,o);return{finalOverrides:g,finalAppendix:b}}if(u.length>0)o.info(`\uD83D\uDC11 Keeping overrides for packages tracked in overridePaths: ${u.join(", ")}`,"cleanupUnusedOverrides");return{finalOverrides:e,finalAppendix:r}};var je=f(()=>{R();P();I();le=y({file:"workspace.ts",isLogging:k})});var Ue,ui,di=(e)=>{return e.split("/").pop()||""},pi=(e)=>{return e.replace(".patch","")},hi=(e)=>{return e.length>=2?`${e[0]}/${e[1]}`:e[0]},gi=(e)=>{return e[0]},fi=(e)=>{if(!e.includes("+"))return e;let r=e.split("+");return e.startsWith("@")?hi(r):gi(r)},yi=(e,t,r)=>{let n=e[t]||[];return{...e,[t]:[...n,r]}},mi=(e,t)=>{let r=di(e);if(!r.endsWith(".patch"))return t;let i=pi(r),s=fi(i);if(!Boolean(s))return t;return Ue.debug(`Found patch for ${s}: ${e}`,"processPatchFile"),yi(t,s,e)},bi=(e)=>{return e.reduce((t,r)=>mi(r,t),{})},De=(e="./")=>{try{let t=oe(ui,{cwd:e});return bi(t)}catch(t){return Ue.error("Error detecting patches","detectPatches",t),{}}},vi=(e,t)=>{return t[e]||[]},Si=(e,t)=>{return Boolean(t[e])},Oi=(e,t)=>{return e.flatMap(([r,n])=>{if(Si(r,t))return[];return Ue.debug(`Found unused patches for ${r}: ${n.join(", ")}`,"collectUnusedPatches"),n})},_e=(e,t)=>{let r=Object.entries(e);return Oi(r,t)},Pi=(e)=>{return e.split("@")[0]},Ai=(e,t,r)=>{let n=Pi(t),i=vi(n,r);if(!(i.length>0))return e;return{...e,[t]:{...e[t],patches:i}}},Me=(e,t)=>{return Object.keys(e).reduce((n,i)=>Ai(n,i,t),e)};var We=f(()=>{ae();R();P();Ue=y({file:"patches.ts",isLogging:k}),ui=["patches/*.patch",".patches/*.patch","*.patch","patches/**/*.patch"]});var Jt={};gt(Jt,{updateOverrides:()=>qt,resolveOverrides:()=>ue,getOverridesByType:()=>F,defineOverride:()=>Ge});var J,ki=(e)=>{return Object.keys(e).length>0},xi=(e)=>{let t=e?.overrides||{};return Object.keys(t).length>0},Ci=(e)=>{return Object.keys(e).length>0},wi=(e,t,r)=>{return e||t||r},Ri=(e,t,r)=>{let n=t?.overrides||{};return[{type:"overrides",overrides:e},{type:"pnpmOverrides",overrides:n},{type:"resolutions",overrides:r}]},Ti=(e)=>{return e.filter(({overrides:t})=>Object.keys(t).length>0)},Vi=(e)=>{return e.length>1},Ge=({overrides:e={},pnpm:t={},resolutions:r={}}={})=>{let n=ki(e),i=xi(t),s=Ci(r);if(!wi(n,i,s))return;let a=Ri(e,t,r),c=Ti(a);if(Vi(c)){J.error("Only 1 override object allowed","defineOverride");return}return c[0]},$i=(e)=>{return Object.keys(e).reduce((r,n)=>{let i=e[n];return r[n]=i,r},{})},Ii=(e)=>{return{type:"pnpm",pnpm:{overrides:e}}},Fi=(e)=>{return{type:"resolutions",resolutions:e}},Ni=(e)=>{return{type:"npm",overrides:e}},Ei=(e,t)=>{if(e==="pnpmOverrides")return Ii(t);if(e==="resolutions")return Fi(t);return Ni(t)},ue=({config:e={}})=>{let t=Ge(e);if(!t){J.debug("No overrides configuration found","resolveOverrides");return}let{type:n,overrides:i}=t,s=Object.keys(i).length>0,o=Boolean(n);if(!(s&&o)){J.debug("No active overrides found","resolveOverrides");return}let c=$i(i);return Ei(n,c)},Li=(e)=>{return e?.resolutions},ji=(e)=>{return e?.pnpm?.overrides},Ui=(e)=>{return e?.overrides},F=(e)=>{let t=e?.type;if(!t){J.error("no type found","getOverridesByType");return}if(t==="resolutions")return Li(e);if(t==="pnpm")return ji(e);return Ui(e)},Di=(e,t)=>{return!t.includes(e)},_i=(e,t)=>{return Object.entries(e).reduce((r,[n,i])=>{if(Di(n,t))r[n]=i;return r},{})},qt=(e,t)=>{if(!e)return;let n=F(e);if(!n||Object.keys(n).length===0){J.debug("No overrides found to update","updateOverrides");return}return _i(n,t)};var z=f(()=>{R();P();J=y({file:"overrides.ts",isLogging:k})});var Mi=(e,t)=>{return t?.find((r)=>r.packageName===e)?.reason},Wi=(e,t)=>{return t?.[e]},He=(e,t,r,n)=>{if(t)return t;let i=Mi(e,r);if(i)return i;return Wi(e,n)},Gi=(e,t)=>{if(!Boolean(t))return!1;return t.some((n)=>n.packageName===e)},Hi=(e,t)=>{return t?.find((r)=>r.packageName===e)},Bi=()=>({securityChecked:!0,securityCheckDate:new Date().toISOString()}),Ki=(e,t)=>{if(!Boolean(t))return e;return{...e,securityProvider:t}},qi=(e,t)=>{if(!t?.cve)return e;return{...e,cve:t.cve}},Ji=(e,t)=>{if(!t?.severity)return e;return{...e,severity:t.severity}},zi=(e,t)=>{if(!t?.url)return e;return{...e,url:t.url}},Be=(e,t,r)=>{if(!Gi(e,t))return{};let i=Hi(e,t),s=Bi();return s=Ki(s,r),s=qi(s,i),s=Ji(s,i),s=zi(s,i),s},Yi=(e,t)=>{let r={addedDate:new Date().toISOString()};return{...e?{...r,reason:e}:r,...t}},Ke=(e,t,r,n)=>{let s=Boolean(t)?t:Yi(r,n);return{dependents:e,ledger:s}},qe=(e,t,r)=>{return{...e,[t]:r}},zt=(e,t,r)=>{if(!e)return`${t} (transitive dependency)`;return`${t}@${r}`},Yt=(e)=>{return typeof e==="object"},Xi=(e)=>{if(!Boolean(e?.dependents))return!0;return Object.keys(e.dependents).length===0},Xt=(e)=>{return Object.keys(e).reduce((r,n)=>{let i=e[n],s=!i,o=Xi(i);if(s||o)return r;return{...r,[n]:i}},{})},Qt=(e)=>{let t=e?.dependencies||{},r=e?.devDependencies||{},n=e?.peerDependencies||{};return{...t,...r,...n}},Zt=(e,t)=>{return e.some((r)=>t.includes(r))},er=(e,t)=>{if(!Boolean(e))return!1;return Object.keys(e).length>0&&t},de=(e)=>{if(!e)return!1;return Object.keys(e).length>0},tr=(e,t,r)=>{let n=e[t]?.dependents||{};return{...e,[t]:{dependents:{...n,...r.dependents}}}};var Qi=(e,t,r,n,i,s,o,a,c,l=!1)=>{let u=i.includes(e);if(l&&!u)return s;let d=`${e}@${t}`;if(c.has(d))return{...s,[d]:c.get(d)};let p=s?.[d]?.dependents||{},g=n[e],b=zt(u,e,g),v=qe(p,r,b),m=s?.[d]?.ledger,x=Ke(v,m,o,a);return c.set(d,x),{...s,[d]:x}},Zi=(e,t,r,n,i,s,o,a,c,l,u)=>{let d=`${e}@${t}`;if(u.has(d))return{...s,[d]:u.get(d)};let p=s?.[d]?.dependents||{},g=`${n}@${i[n]} (nested override)`,b=qe(p,r,g),v=s?.[d]?.ledger,m=He(e,void 0,a,l)||o,x=Be(e,a,c),ut=Ke(b,v,m,x);return u.set(d,ut),{...s,[d]:ut}},es=(e,t,r,n,i,s,o,a,c,l,u)=>{if(!i.includes(e))return s;return Object.entries(t).reduce((h,[p,g])=>Zi(p,g,r,e,n,h,o,a,c,l,u),s)},ts=(e,t,r,n,i,s,o,a,c,l,u,d=!1)=>{let h=t[e],p=He(e,o,a,l),g=Be(e,a,c);if(Yt(h))return es(e,h,r,n,i,s,p,a,c,l,u);return Qi(e,h,r,n,i,s,p,g,u,d)},_=({overrides:e={},appendix:t={},dependencies:r={},devDependencies:n={},peerDependencies:i={},packageName:s="",reason:o,securityOverrideDetails:a,securityProvider:c,manualOverrideReasons:l,cache:u=new Map,onlyUsedOverrides:d=!1})=>{let h=Object.keys(e),p={...r,...n,...i},g=Object.keys(p),b=h.reduce((v,m)=>ts(m,e,s,p,g,v,o,a,c,l,u,d),t);return Xt(b)},rr=(e,t,r,n=!0)=>{let i=w(e);if(!Boolean(i))return;let{name:o,dependencies:a={},devDependencies:c={},peerDependencies:l={}}=i,u=Qt(i),d=Object.keys(u);if(!Zt(d,r))return;let p=_({overrides:t,dependencies:a,devDependencies:c,peerDependencies:l,packageName:o,securityOverrideDetails:void 0,manualOverrideReasons:void 0,onlyUsedOverrides:!0});if(er(p,n)){let{writeFileSync:b}=ft("fs");i.pastoralist={appendix:p},b(e,JSON.stringify(i,null,2))}return{name:o,dependencies:a,devDependencies:c,appendix:p}},rs=(e)=>{return Boolean(e)},ns=(e)=>{if(!rs(e))return null;return F(e)||null},is=(e,t)=>{let r=w(e);if(!Boolean(r))return null;let{resolveOverrides:i}=(z(),un(Jt)),s=i({config:r}),o=F(s)||null,a=de(o);if(a)t.debug(`Found ${Object.keys(o).length} overrides in ${e}`,"constructAppendix");return a?o:null},ss=(e,t)=>{return e.map((r)=>is(r,t))},os=(e,t)=>{let r=e.filter((i)=>i!==null),n=de(t)?{...t}:{};return r.reduce((i,s)=>({...i,...s}),n)},as=(e,t,r)=>{return e.map((n)=>rr(n,t,r,!1))},cs=(e,t,r)=>{return tr(e,t,r)},ls=(e,t)=>{return Object.entries(t).reduce((n,[i,s])=>cs(n,i,s),e)},us=(e)=>{return e.filter((r)=>r!==null&&r!==void 0&&Boolean(r.appendix)).reduce((r,n)=>ls(r,n.appendix),{})},Je=(e,t,r)=>{let n=ns(t);if(de(n))r.debug(`Found ${Object.keys(n).length} overrides in root package.json`,"constructAppendix");let s=ss(e,r),o=os(s,n);if(!(Object.keys(o).length>0))return r.debug("No overrides found in root or workspace packages","constructAppendix"),{};let c=Object.keys(o);r.debug(`Processing ${c.length} total unique overrides across all packages`,"constructAppendix");let l=as(e,o,c);return us(l)};var pe=f(()=>{I();z()});var nr=(e,t,r,n)=>{return Ne(e,r,t,n)},ir=(e)=>{Ie({appendix:e.finalAppendix,path:e.path,config:e.config,overrides:e.finalOverrides,dryRun:e.options?.dryRun||!1,isTesting:e.isTesting})},sr=(e,t,r,n)=>{let i=t.pastoralist?.depPaths,s=e?.depPaths&&e.depPaths.length>0,o=!s&&i,a=ds(e,t);return{mode:s||o?"workspace":"root",depPaths:a,hasRootOverrides:r,missingInRoot:n}},ds=(e,t)=>{if(e?.depPaths)return e.depPaths;let r=t.pastoralist?.depPaths;if(r==="workspace"||r==="workspaces")return t.workspaces?.map((n)=>`${n}/package.json`)||null;if(Array.isArray(r))return r;if(t.workspaces&&!r)return t.workspaces.map((n)=>`${n}/package.json`);return null};var or=f(()=>{I()});var ps=(e)=>{let t=De(e.root),r=Object.keys(t);if(r.length>0)e.log.debug(`Found patches for packages: ${r.join(", ")}`,"stepDetectPatches");return{...e,patchMap:t}},hs=(e)=>{if(!e.config)return e;let t=ue({options:e.options,config:e.config}),r=F(t)||{};if(e.options?.securityOverrides)e.log.debug("Merging security overrides","stepPrepareOverrides"),r={...r,...e.options.securityOverrides};return{...e,overridesData:t,overrides:r}},gs=(e)=>{if(!e.config)return e;let t=e.overrides||{},r=Object.keys(t).length>0,n={...e.config.dependencies,...e.config.devDependencies,...e.config.peerDependencies},i=Ee(t,n,e.log,e.options),s=sr(e.options,e.config,r,i);return{...e,hasRootOverrides:r,rootDeps:n,missingInRoot:i,mode:s}},fs=(e)=>{if(!e.config||!e.mode||!e.overridesData)return e;let t=e.mode.depPaths;if(!(t&&t.length>0))return e;let n=e.options?.ignore||[],i=nr(t,e.root,n,e.log);if(i.length===0)return e;e.log.debug(`Processing ${i.length} workspace packages`,"stepProcessWorkspaces");let{appendix:s,allWorkspaceDeps:o}=Gt(i,e.overridesData,e.log,Je);return{...e,workspaceAppendix:s,allWorkspaceDeps:o}},ys=(e)=>{if(!e.config||!e.overrides)return e;let t=e.config.pastoralist?.appendix||{};return{...e,existingAppendix:t}},ms=(e)=>{if(!e.config||!e.overrides)return e;let{dependencies:t={},devDependencies:r={},peerDependencies:n={}}=e.config,i=_({overrides:e.overrides,dependencies:t,devDependencies:r,peerDependencies:n,packageName:e.config.name||"root",securityOverrideDetails:e.options?.securityOverrideDetails,securityProvider:e.options?.securityProvider,manualOverrideReasons:e.options?.manualOverrideReasons});if(!e.workspaceAppendix)return{...e,appendix:i};return e.log.debug("Merging workspace appendix with root appendix","stepBuildAppendix"),Object.entries(e.workspaceAppendix).forEach(([s,o])=>{let a=i[s];if(!a)i[s]=o;else a.dependents={...a.dependents,...o.dependents}}),{...e,appendix:i}},bs=(e)=>{if(!e.appendix||!e.patchMap)return e;let t=Me(e.appendix,e.patchMap);return{...e,appendix:t}},vs=(e)=>{if(!e.config||!e.appendix||!e.missingInRoot)return e;let t=e.config.pastoralist?.overridePaths||e.config.pastoralist?.resolutionPaths;return Le(e.appendix,t,e.missingInRoot,e.log),{...e,overridePaths:t}},Ss=(e)=>{if(!e.patchMap||!e.rootDeps)return e;let t=_e(e.patchMap,e.rootDeps);if(t.length>0)e.log.info(`Found ${t.length} potentially unused patch files:`,"stepLogUnusedPatches"),t.forEach((r)=>e.log.info(` - ${r}`,"stepLogUnusedPatches")),e.log.info("Consider removing these patches if the packages are no longer used.","stepLogUnusedPatches");return{...e,allDeps:e.rootDeps}},Os=(e)=>{if(e.finalOverrides!==void 0&&e.finalAppendix!==void 0)return e;let t=e.overrides||{},r=e.appendix||{};if(!e.overrides||!e.overridesData||!e.appendix)return{...e,finalOverrides:t,finalAppendix:r};return{...e,finalOverrides:e.overrides,finalAppendix:e.appendix}},Ps=(e)=>{if(e.isTesting)return e;if(!e.config||e.finalAppendix===void 0||e.finalOverrides===void 0)return e.log.debug(`Skipping write: config=${!!e.config}, appendix=${e.finalAppendix!==void 0}, overrides=${e.finalOverrides!==void 0}`,"stepWriteResult"),e;return e.log.debug(`Writing results: appendix keys=${Object.keys(e.finalAppendix||{}).length}, override keys=${Object.keys(e.finalOverrides||{}).length}`,"stepWriteResult"),ir({path:e.path,config:e.config,finalAppendix:e.finalAppendix,finalOverrides:e.finalOverrides,options:e.options,isTesting:e.isTesting}),e},As=(e,...t)=>{return t.reduce((r,n)=>n(r),e)},ks=(e)=>{let t=!e.mode?.hasRootOverrides,r=e.mode?.mode==="root",n=Boolean(e.config);if(!(t&&r&&n))return e;return e.log.debug("No overrides found","update"),{...e,finalOverrides:{},finalAppendix:{}}},ze=(e)=>{let t=e?.path||"package.json",r=e?.root||"./",n=e?.isTesting||!1,i=k||e?.debug||!1,s=y({file:"update",isLogging:i});if(Fe(),V.clear(),!e.config)return s.debug("No config provided","update"),{options:e,path:t,root:r,isTesting:n,log:s};let o={options:e,path:t,root:r,isTesting:n,log:s,config:e.config},a=As(o,ps,hs,gs,fs,ks,ys,ms,bs,vs,Ss,Os,Ps);if(k)a.log.debug("Update complete","update");return a};var Ye=f(()=>{R();P();I();je();We();z();pe();or()});class Y{debug;isIRLFix;isIRLCatch;log;retryOptions;constructor(e={}){this.debug=e.debug||!1,this.isIRLFix=e.isIRLFix||!1,this.isIRLCatch=e.isIRLCatch||!1,this.log=y({file:"security/osv.ts",isLogging:this.debug}),this.retryOptions=e.retryOptions||{retries:3,factor:2,minTimeout:1000}}async isAvailable(){try{return(await fetch("https://api.osv.dev/v1/query",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({package:{name:"test",ecosystem:"npm"}})})).ok}catch{return!1}}async fetchFromOSVBatchAPI(e){let t=e.map((i)=>({package:{name:i.name,ecosystem:"npm"},version:i.version})),r=await fetch("https://api.osv.dev/v1/querybatch",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({queries:t})});if(!r.ok)throw Error(`HTTP ${r.status}`);return(await r.json()).results||[]}async fetchAlerts(e){if(this.log.debug(`OSV checking ${e.length} packages`,"fetchAlerts"),e.length===0)return[];let t=await U(async()=>{return this.fetchFromOSVBatchAPI(e)},{...this.retryOptions,onFailedAttempt:(s)=>{this.log.debug(`Batch API attempt ${s.attemptNumber} failed`,"fetchAlerts")}}).catch((s)=>{return this.log.debug("Failed to fetch batch results after retries","fetchAlerts",{error:s}),[]}),r=e.map((s,o)=>{let a=t[o];return a?.vulns&&a.vulns.length>0?this.convertOSVAlerts(s,a.vulns):[]}).flat(),n=this.isIRLFix?[Ce.ALERT_TO_RESOLVE]:[],i=this.isIRLCatch?[Ce.ALERT_TO_CAPTURE]:[];return r.concat(n).concat(i)}convertOSVAlerts(e,t){return t.map((r)=>({packageName:e.name,currentVersion:e.version,vulnerableVersions:this.extractVersionRange(r),patchedVersion:this.extractPatchedVersion(r),severity:this.extractSeverity(r),title:r.summary||r.details||`Vulnerability in ${e.name}`,description:r.details,cve:this.extractCVE(r),url:r.references?.[0]?.url||`https://osv.dev/vulnerability/${r.id}`,fixAvailable:!!this.extractPatchedVersion(r)}))}extractVersionRange(e){let t=e.affected?.[0];if(t?.ranges?.[0]?.events){let r=t.ranges[0].events,n=r.find((s)=>s.introduced)?.introduced||"0",i=r.find((s)=>s.fixed)?.fixed;return i?`>= ${n} < ${i}`:`>= ${n}`}return""}extractPatchedVersion(e){return(e.affected?.[0]?.ranges?.[0]?.events||[]).find((i)=>i.fixed)?.fixed}extractSeverity(e){let t=e.database_specific?.severity||e.severity?.[0]?.score||"medium";if(typeof t==="string"){let r=t.toLowerCase();if(["low","medium","high","critical"].includes(r))return r}return"medium"}extractCVE(e){return e.aliases?.find((t)=>t.startsWith("CVE-"))}}var ar=f(()=>{P();R()});import{execFile as xs}from"child_process";import{promisify as Cs}from"util";class ge{owner;repo;token;log;constructor(e){this.token=e.token||process.env.GITHUB_TOKEN,this.log=y({file:"github.ts",isLogging:e.debug}),this.log.debug(`Token provided: ${this.token?"yes (length: "+this.token.length+")":"no"}`,"constructor"),this.owner=e.owner||"",this.repo=e.repo||""}async initialize(){if(!this.owner)this.owner=await this.getRepoOwner();if(!this.repo)this.repo=await this.getRepoName()}async getRepoOwner(){try{let{stdout:e}=await he("git",["config","--get","remote.origin.url"]),t=e.trim();if(this.isGitHubUrl(t)){let r=t.match(/github\.com[:/]([^/]+)\//);if(r)return r[1]}}catch{this.log.debug("Failed to get repo owner from git","getRepoOwner")}throw Error("Unable to determine GitHub repository owner")}async getRepoName(){try{let{stdout:e}=await he("git",["config","--get","remote.origin.url"]),t=e.trim();if(this.isGitHubUrl(t)){let r=t.match(/github\.com[:/][^/]+\/([^/.]+)/);if(r)return r[1]}}catch{this.log.debug("Failed to get repo name from git","getRepoName")}throw Error("Unable to determine GitHub repository name")}isGitHubUrl(e){if(e.startsWith("git@github.com:"))return!0;try{return new URL(e).hostname==="github.com"}catch{return!1}}async fetchAlerts(){this.log.debug("Fetching GitHub Dependabot alerts","fetchAlerts");let e=await this.fetchDependabotAlerts();this.log.debug(`Found ${e.length} Dependabot alerts`,"fetchAlerts");let t=this.convertToSecurityAlerts(e);return this.log.debug(`Converted to ${t.length} security alerts`,"fetchAlerts"),t}async fetchDependabotAlerts(){if(await this.initialize(),this.isMockMode())return this.fetchMockAlerts();return this.fetchRealAlerts()}isMockMode(){return process.env[te.MOCK_MODE]==="true"}async fetchRealAlerts(){if(this.token)return this.log.debug("Using GitHub API with provided token","fetchRealAlerts"),this.fetchAlertsWithApi();if(await this.isGhCliAvailable())return this.log.debug("Using gh CLI (no token provided)","fetchRealAlerts"),this.fetchAlertsWithGhCli();throw Error("GitHub CLI not found and no GITHUB_TOKEN provided. Please install gh CLI or set GITHUB_TOKEN environment variable.")}async fetchMockAlerts(){if(this.log.debug("Using mock Dependabot alerts","fetchMockAlerts"),this.shouldForceVulnerable())return this.getMockVulnerableAlerts();return[]}shouldForceVulnerable(){return process.env[te.FORCE_VULNERABLE]==="true"}async getMockVulnerableAlerts(){let e=process.env[te.MOCK_FILE];if(e){let t=await this.loadMockFile(e);if(t)return t}return this.getDefaultMockAlerts()}async loadMockFile(e){try{let{readFileSync:t}=await import("fs"),r=t(e,"utf-8");return JSON.parse(r)}catch(t){return this.log.debug("Failed to read mock file","loadMockFile",{error:t}),null}}getDefaultMockAlerts(){return[bt,vt]}async isGhCliAvailable(){try{return await he("gh",["--version"]),!0}catch{return!1}}async executeGhCli(){let e=["api",`repos/${this.owner}/${this.repo}/dependabot/alerts`,"--paginate"];this.log.debug(`Fetching alerts with gh CLI: gh ${e.join(" ")}`,"executeGhCli");let{stdout:t}=await he("gh",e);return this.log.debug(`gh CLI stdout length: ${t.length}`,"executeGhCli"),t}async fetchAlertsWithGhCli(){try{let e=await U(()=>this.executeGhCli(),{retries:3,factor:2,minTimeout:1000,onFailedAttempt:(r)=>{this.log.debug(`gh CLI attempt ${r.attemptNumber} failed`,"fetchAlertsWithGhCli")}}),t=JSON.parse(e);return this.log.debug(`Parsed ${Array.isArray(t)?t.length:"non-array"} alerts`,"fetchAlertsWithGhCli"),Array.isArray(t)?t:[]}catch(e){throw this.log.error("Failed to fetch alerts with gh CLI","fetchAlertsWithGhCli",{error:e}),Error(`Failed to fetch Dependabot alerts: ${e}`)}}async fetchFromGitHubAPI(){let e=`https://api.github.com/repos/${this.owner}/${this.repo}/dependabot/alerts`,t=await fetch(e,{headers:{Authorization:`Bearer ${this.token}`,Accept:"application/vnd.github.v3+json"}});if(!t.ok){let n=await t.json();throw Error(`GitHub API error: ${n.message||t.statusText}`)}let r=await t.json();return Array.isArray(r)?r:[]}async fetchAlertsWithApi(){try{return await U(()=>this.fetchFromGitHubAPI(),{retries:3,factor:2,minTimeout:1000,onFailedAttempt:(e)=>{this.log.debug(`GitHub API attempt ${e.attemptNumber} failed`,"fetchAlertsWithApi")}})}catch(e){throw this.log.error("Failed to fetch alerts with API","fetchAlertsWithApi",{error:e}),Error(`Failed to fetch Dependabot alerts: ${e}`)}}convertToSecurityAlerts(e){return e.filter((t)=>t.state==="open").map((t)=>{let{security_vulnerability:r,security_advisory:n}=t,i=this.extractCurrentVersion(t);return{packageName:r.package.name,currentVersion:i,vulnerableVersions:r.vulnerable_version_range,patchedVersion:r.first_patched_version?.identifier,severity:this.normalizeSeverity(r.severity),title:n.summary,description:n.description,cve:n.cve_id,url:t.html_url,fixAvailable:!!r.first_patched_version}})}extractCurrentVersion(e){let t=e.security_vulnerability.vulnerable_version_range;if(t.includes(">=")&&t.includes("<=")){let r=t.match(/>= ?([^\s,]+)/);return r?r[1]:"unknown"}if(t.includes(">=")){let r=t.match(/>= ?([^\s,]+)/);return r?r[1]:"unknown"}return"unknown"}normalizeSeverity(e){let t=e.toLowerCase();switch(t){case"low":case"medium":case"high":case"critical":return t;default:return"medium"}}}var he;var cr=f(()=>{P();R();he=Cs(xs)});import{execFile as ws}from"child_process";import{promisify as Rs}from"util";import*as ur from"readline/promises";class X{log;constructor(e={}){this.log=y({file:"security/cli-installer.ts",isLogging:e.debug})}async isInstalled(e){try{return await fe("which",[e]),!0}catch{return!1}}async isInstalledGlobally(e){try{let{stdout:t}=await fe("npm",["list","-g",e,"--depth=0"]);return t.includes(e)}catch{return!1}}async installGlobally(e){this.log.info(`Installing ${e} globally...`,"installGlobally");try{await fe("npm",["install","-g",e],{timeout:120000}),this.log.info(`Successfully installed ${e}`,"installGlobally")}catch(t){throw this.log.error(`Failed to install ${e}`,"installGlobally",{error:t}),Error(`Failed to install ${e}: ${t}`)}}async ensureInstalled(e){let{packageName:t,cliCommand:r}=e;if(await this.isInstalled(r))return this.log.debug(`${r} is already installed`,"ensureInstalled"),!0;if(await this.isInstalledGlobally(t))return this.log.debug(`${t} is installed globally but command not in PATH`,"ensureInstalled"),!0;this.log.info(`${r} not found, installing ${t}...`,"ensureInstalled");try{if(await this.installGlobally(t),!await this.isInstalled(r))return this.log.info(`${t} was installed but ${r} is still not available. Please ensure it's in your PATH.`,"ensureInstalled"),!1;return!0}catch(s){return this.log.error(`Could not install ${t}`,"ensureInstalled",{error:s}),!1}}async getVersion(e){try{let{stdout:t}=await fe(e,["--version"]);return t.trim()}catch{return}}}class Qe{prompts;constructor(e={confirm:Vs,select:$s,input:Is}){this.prompts=e}async promptForSecurityActions(e,t){if(e.length===0)return[];console.log(`
|
|
9
|
+
`)},oi=(e)=>{let t=JSON.parse(e),r={},n=(s)=>{if(!(s&&typeof s==="object"))return;Object.entries(s).forEach(([a,c])=>{if(r[a]=!0,c&&typeof c==="object"&&"dependencies"in c)n(c.dependencies)})};if(t.dependencies)n(t.dependencies);return r},ai=async()=>{try{let{stdout:e}=await _n("npm",["ls","--json","--all"],{encoding:"utf8",maxBuffer:10485760,timeout:3000});return e}catch(e){let t=e;if(t.code===1&&t.stdout)return t.stdout;throw e}},qt=async()=>{if(le!==null)return le;try{let t=await ai(),r=oi(t);return le=r,r}catch(t){return J.debug("Failed to get dependency tree","getDependencyTree",t),{}}},Le=()=>{le=null},je=(e,t=[],r="./",n=J)=>{if(e.length===0)throw n.error("No depPaths provided","findPackageJsonFiles"),Error("No depPaths provided to findPackageJsonFiles");try{n.debug(`Searching with patterns: ${e.join(", ")}, ignoring: ${t.join(", ")}, cwd: ${r}`,"findPackageJsonFiles");let s=ce(e,{cwd:r,ignore:t,absolute:!1,onlyFiles:!0});if(s.length===0){let a=`No package.json files found matching patterns: ${e.join(", ")} in directory: ${r}`;throw n.error(a,"findPackageJsonFiles"),Error(a)}return n.debug(`Found ${s.length} files`,"findPackageJsonFiles"),s}catch(s){throw n.error("Error finding package.json files","findPackageJsonFiles",s),s}};var I=f(()=>{ue();T();P();_n=Dn(Un),J=y({file:"packageJSON.ts",isLogging:k}),V=new Map});var de,ci=(e,t)=>{return Boolean(t[e])},ui=(e,t)=>{return e.filter((r)=>!ci(r,t))},li=(e,t)=>{return e>0&&!t},Ue=(e,t,r,n)=>{let i=Object.keys(e),s=ui(i,t),o=Boolean(n?.depPaths);if(li(s.length,o))r.info(`\uD83D\uDC11 Found overrides for packages not in root dependencies: ${s.join(", ")}`,"checkMonorepoOverrides"),r.info("\uD83D\uDCA1 For monorepo support, use --depPaths flag or add depPaths configuration in package.json","checkMonorepoOverrides");return s},di=(e)=>{let t=e?.dependencies||{},r=e?.devDependencies||{},n=e?.peerDependencies||{};return{...t,...r,...n}},pi=(e)=>{return e.map((r)=>R(r)).reduce((r,n)=>{if(!Boolean(n))return r;let s=di(n);return{...r,...s}},{})},Jt=(e,t,r,n)=>{let i=n(e,t,r),s=pi(e);return{appendix:i,allWorkspaceDeps:s}},hi=(e,t)=>{let r=Boolean(e),n=t.length>0;return r&&n},gi=(e,t)=>{return{...e,dependents:{...e.dependents,...t.dependents}}},De=(e,t,r,n)=>{if(!hi(t,r))return e;return n.debug("Using overridePaths configuration for monorepo support","mergeOverridePaths"),Object.values(t).forEach((s)=>{Object.entries(s).forEach(([o,a])=>{if(e[o])e[o]=gi(e[o],a);else e[o]=a})}),e},Yt=(e,t)=>{return typeof t[e]==="object"},zt=(e,t)=>{return Boolean(t[e])},fi=(e,t,r)=>{if(!Yt(e,t))return!1;if(zt(e,r))return!1;return de.debug(`Found unused nested override for ${e}: parent package not in dependencies`,"isUnusedNestedOverride"),!0},yi=async(e,t,r)=>{if(Yt(e,t))return!1;if(zt(e,r))return!1;if(!(Object.keys(r).length>0))return de.debug(`Found unused override for ${e}: no dependencies at all`,"isUnusedSimpleOverride"),!0;let o=await qt();if(Boolean(o[e]))return de.debug(`Keeping override for ${e}: found in dependency tree`,"isUnusedSimpleOverride"),!1;return de.debug(`Found unused override for ${e}: not in dependency tree`,"isUnusedSimpleOverride"),!0},mi=async(e,t,r)=>{if(fi(e,t,r))return!0;return yi(e,t,r)},Xt=async(e,t)=>{let r=Object.keys(e),n=await Promise.all(r.map((i)=>mi(i,e,t)));return r.filter((i,s)=>n[s])},bi=(e,t)=>{if(!t)return!1;return Object.values(t).some((r)=>Object.keys(r).some((n)=>n.startsWith(`${e}@`)))},vi=(e,t)=>{return e.filter((r)=>bi(r,t))},Si=(e,t)=>{return e.filter((r)=>!t.includes(r))},Oi=(e,t,r)=>{return t.reduce((n,i)=>{return Object.keys(n).filter((o)=>o.startsWith(`${i}@`)).reduce((o,a)=>{r.debug(`Removed appendix entry for ${a}`,"removeAppendixEntries");let{[a]:c,...l}=o;return l},n)},e)},Pi=async(e,t,r,n,i,s,o,a)=>{let c=await Xt(e,n);if(c.length===0)return{finalOverrides:e,finalAppendix:r};let u=vi(i,s),d=Si(c,u);if(d.length>0){o.debug(`Found ${d.length} packages to remove from overrides: ${d.join(", ")}`,"cleanupUnusedOverrides");let h=a(t,d)||e,m=Oi(r,d,o);return{finalOverrides:h,finalAppendix:m}}if(u.length>0)o.info(`\uD83D\uDC11 Keeping overrides for packages tracked in overridePaths: ${u.join(", ")}`,"cleanupUnusedOverrides");return{finalOverrides:e,finalAppendix:r}};var _e=f(()=>{T();P();I();de=y({file:"workspace.ts",isLogging:k})});var Me,Ai,ki=(e)=>{return e.split("/").pop()||""},xi=(e)=>{return e.replace(".patch","")},Ci=(e)=>{return e.length>=2?`${e[0]}/${e[1]}`:e[0]},wi=(e)=>{return e[0]},Ri=(e)=>{if(!e.includes("+"))return e;let r=e.split("+");return e.startsWith("@")?Ci(r):wi(r)},Ti=(e,t,r)=>{let n=e[t]||[];return{...e,[t]:[...n,r]}},Vi=(e,t)=>{let r=ki(e);if(!r.endsWith(".patch"))return t;let i=xi(r),s=Ri(i);if(!Boolean(s))return t;return Me.debug(`Found patch for ${s}: ${e}`,"processPatchFile"),Ti(t,s,e)},$i=(e)=>{return e.reduce((t,r)=>Vi(r,t),{})},We=(e="./")=>{try{let t=ce(Ai,{cwd:e});return $i(t)}catch(t){return Me.error("Error detecting patches","detectPatches",t),{}}},Ii=(e,t)=>{return t[e]||[]},Ei=(e,t)=>{return Boolean(t[e])},Fi=(e,t)=>{return e.flatMap(([r,n])=>{if(Ei(r,t))return[];return Me.debug(`Found unused patches for ${r}: ${n.join(", ")}`,"collectUnusedPatches"),n})},Ge=(e,t)=>{let r=Object.entries(e);return Fi(r,t)},Ni=(e)=>{return e.split("@")[0]},Li=(e,t,r)=>{let n=Ni(t),i=Ii(n,r);if(!(i.length>0))return e;return{...e,[t]:{...e[t],patches:i}}},He=(e,t)=>{return Object.keys(e).reduce((n,i)=>Li(n,i,t),e)};var Ke=f(()=>{ue();T();P();Me=y({file:"patches.ts",isLogging:k}),Ai=["patches/*.patch",".patches/*.patch","*.patch","patches/**/*.patch"]});var Zt={};vt(Zt,{updateOverrides:()=>Qt,resolveOverrides:()=>pe,getOverridesByType:()=>E,defineOverride:()=>Be});var Y,ji=(e)=>{return Object.keys(e).length>0},Ui=(e)=>{let t=e?.overrides||{};return Object.keys(t).length>0},Di=(e)=>{return Object.keys(e).length>0},_i=(e,t,r)=>{return e||t||r},Mi=(e,t,r)=>{let n=t?.overrides||{};return[{type:"overrides",overrides:e},{type:"pnpmOverrides",overrides:n},{type:"resolutions",overrides:r}]},Wi=(e)=>{return e.filter(({overrides:t})=>Object.keys(t).length>0)},Gi=(e)=>{return e.length>1},Be=({overrides:e={},pnpm:t={},resolutions:r={}}={})=>{let n=ji(e),i=Ui(t),s=Di(r);if(!_i(n,i,s))return;let a=Mi(e,t,r),c=Wi(a);if(Gi(c)){Y.error("Only 1 override object allowed","defineOverride");return}return c[0]},Hi=(e)=>{return Object.keys(e).reduce((r,n)=>{let i=e[n];return r[n]=i,r},{})},Ki=(e)=>{return{type:"pnpm",pnpm:{overrides:e}}},Bi=(e)=>{return{type:"resolutions",resolutions:e}},qi=(e)=>{return{type:"npm",overrides:e}},Ji=(e,t)=>{if(e==="pnpmOverrides")return Ki(t);if(e==="resolutions")return Bi(t);return qi(t)},pe=({config:e={}})=>{let t=Be(e);if(!t){Y.debug("No overrides configuration found","resolveOverrides");return}let{type:n,overrides:i}=t,s=Object.keys(i).length>0,o=Boolean(n);if(!(s&&o)){Y.debug("No active overrides found","resolveOverrides");return}let c=Hi(i);return Ji(n,c)},Yi=(e)=>{return e?.resolutions},zi=(e)=>{return e?.pnpm?.overrides},Xi=(e)=>{return e?.overrides},E=(e)=>{let t=e?.type;if(!t){Y.error("no type found","getOverridesByType");return}if(t==="resolutions")return Yi(e);if(t==="pnpm")return zi(e);return Xi(e)},Qi=(e,t)=>{return!t.includes(e)},Zi=(e,t)=>{return Object.entries(e).reduce((r,[n,i])=>{if(Qi(n,t))r[n]=i;return r},{})},Qt=(e,t)=>{if(!e)return;let n=E(e);if(!n||Object.keys(n).length===0){Y.debug("No overrides found to update","updateOverrides");return}return Zi(n,t)};var z=f(()=>{T();P();Y=y({file:"overrides.ts",isLogging:k})});var es=(e,t)=>{return t?.find((r)=>r.packageName===e)?.reason},ts=(e,t)=>{return t?.[e]},qe=(e,t,r,n)=>{if(t)return t;let i=es(e,r);if(i)return i;return ts(e,n)},rs=(e,t)=>{if(!Boolean(t))return!1;return t.some((n)=>n.packageName===e)},ns=(e,t)=>{return t?.find((r)=>r.packageName===e)},is=()=>({securityChecked:!0,securityCheckDate:new Date().toISOString()}),ss=(e,t)=>{if(!Boolean(t))return e;return{...e,securityProvider:t}},os=(e,t)=>{if(!t?.cve)return e;return{...e,cve:t.cve}},as=(e,t)=>{if(!t?.severity)return e;return{...e,severity:t.severity}},cs=(e,t)=>{if(!t?.url)return e;return{...e,url:t.url}},Je=(e,t,r)=>{if(!rs(e,t))return{};let i=ns(e,t),s=is();return s=ss(s,r),s=os(s,i),s=as(s,i),s=cs(s,i),s},us=(e,t)=>{let r={addedDate:new Date().toISOString()};return{...e?{...r,reason:e}:r,...t}},Ye=(e,t,r,n)=>{let s=Boolean(t)?t:us(r,n);return{dependents:e,ledger:s}},ze=(e,t,r)=>{return{...e,[t]:r}},er=(e,t,r)=>{if(!e)return`${t} (transitive dependency)`;return`${t}@${r}`},tr=(e)=>{return typeof e==="object"},ls=(e)=>{if(!Boolean(e?.dependents))return!0;return Object.keys(e.dependents).length===0},rr=(e)=>{return Object.keys(e).reduce((r,n)=>{let i=e[n],s=!i,o=ls(i);if(s||o)return r;return{...r,[n]:i}},{})},nr=(e)=>{let t=e?.dependencies||{},r=e?.devDependencies||{},n=e?.peerDependencies||{};return{...t,...r,...n}},ir=(e,t)=>{return e.some((r)=>t.includes(r))},sr=(e,t)=>{if(!Boolean(e))return!1;return Object.keys(e).length>0&&t},he=(e)=>{if(!e)return!1;return Object.keys(e).length>0},or=(e,t,r)=>{let n=e[t]?.dependents||{};return{...e,[t]:{dependents:{...n,...r.dependents}}}};var ds=(e,t,r,n,i,s,o,a,c,l=!1)=>{let u=i.includes(e);if(l&&!u)return s;let d=`${e}@${t}`;if(c.has(d))return{...s,[d]:c.get(d)};let p=s?.[d]?.dependents||{},h=n[e],m=er(u,e,h),b=ze(p,r,m),v=s?.[d]?.ledger,x=Ye(b,v,o,a);return c.set(d,x),{...s,[d]:x}},ps=(e,t,r,n,i,s,o,a,c,l,u)=>{let d=`${e}@${t}`;if(u.has(d))return{...s,[d]:u.get(d)};let p=s?.[d]?.dependents||{},h=`${n}@${i[n]} (nested override)`,m=ze(p,r,h),b=s?.[d]?.ledger,v=qe(e,void 0,a,l)||o,x=Je(e,a,c),W=Ye(m,b,v,x);return u.set(d,W),{...s,[d]:W}},hs=(e,t,r,n,i,s,o,a,c,l,u)=>{if(!i.includes(e))return s;return Object.entries(t).reduce((g,[p,h])=>ps(p,h,r,e,n,g,o,a,c,l,u),s)},gs=(e,t,r,n,i,s,o,a,c,l,u,d=!1)=>{let g=t[e],p=qe(e,o,a,l),h=Je(e,a,c);if(tr(g))return hs(e,g,r,n,i,s,p,a,c,l,u);return ds(e,g,r,n,i,s,p,h,u,d)},_=({overrides:e={},appendix:t={},dependencies:r={},devDependencies:n={},peerDependencies:i={},packageName:s="",reason:o,securityOverrideDetails:a,securityProvider:c,manualOverrideReasons:l,cache:u=new Map,onlyUsedOverrides:d=!1})=>{let g=Object.keys(e),p={...r,...n,...i},h=Object.keys(p),m=g.reduce((b,v)=>gs(v,e,s,p,h,b,o,a,c,l,u,d),t);return rr(m)},ar=(e,t,r,n=!0)=>{let i=R(e);if(!Boolean(i))return;let{name:o,dependencies:a={},devDependencies:c={},peerDependencies:l={}}=i,u=nr(i),d=Object.keys(u);if(!ir(d,r))return;let p=_({overrides:t,dependencies:a,devDependencies:c,peerDependencies:l,packageName:o,securityOverrideDetails:void 0,manualOverrideReasons:void 0,onlyUsedOverrides:!0});if(sr(p,n)){let{writeFileSync:m}=St("fs");i.pastoralist={appendix:p},m(e,JSON.stringify(i,null,2))}return{name:o,dependencies:a,devDependencies:c,appendix:p}},fs=(e)=>{return Boolean(e)},ys=(e)=>{if(!fs(e))return null;return E(e)||null},ms=(e,t)=>{let r=R(e);if(!Boolean(r))return null;let{resolveOverrides:i}=(z(),On(Zt)),s=i({config:r}),o=E(s)||null,a=he(o);if(a)t.debug(`Found ${Object.keys(o).length} overrides in ${e}`,"constructAppendix");return a?o:null},bs=(e,t)=>{return e.map((r)=>ms(r,t))},vs=(e,t)=>{let r=e.filter((i)=>i!==null),n=he(t)?{...t}:{};return r.reduce((i,s)=>({...i,...s}),n)},Ss=(e,t,r)=>{return e.map((n)=>ar(n,t,r,!1))},Os=(e,t,r)=>{return or(e,t,r)},Ps=(e,t)=>{return Object.entries(t).reduce((n,[i,s])=>Os(n,i,s),e)},As=(e)=>{return e.filter((r)=>r!==null&&r!==void 0&&Boolean(r.appendix)).reduce((r,n)=>Ps(r,n.appendix),{})},Xe=(e,t,r)=>{let n=ys(t);if(he(n))r.debug(`Found ${Object.keys(n).length} overrides in root package.json`,"constructAppendix");let s=bs(e,r),o=vs(s,n);if(!(Object.keys(o).length>0))return r.debug("No overrides found in root or workspace packages","constructAppendix"),{};let c=Object.keys(o);r.debug(`Processing ${c.length} total unique overrides across all packages`,"constructAppendix");let l=Ss(e,o,c);return As(l)};var ge=f(()=>{I();z()});var cr=(e,t,r,n)=>{return je(e,r,t,n)},ur=(e)=>{let t=e.options?.outputFormat==="json";Ne({appendix:e.finalAppendix,path:e.path,config:e.config,overrides:e.finalOverrides,dryRun:e.options?.dryRun||!1,silent:t,isTesting:e.isTesting})},lr=(e,t,r,n)=>{let i=t.pastoralist?.depPaths,s=e?.depPaths&&e.depPaths.length>0,o=!s&&i,a=ks(e,t);return{mode:s||o?"workspace":"root",depPaths:a,hasRootOverrides:r,missingInRoot:n}},ks=(e,t)=>{if(e?.depPaths)return e.depPaths;let r=t.pastoralist?.depPaths;if(r==="workspace"||r==="workspaces")return t.workspaces?.map((n)=>`${n}/package.json`)||null;if(Array.isArray(r))return r;if(t.workspaces&&!r)return t.workspaces.map((n)=>`${n}/package.json`);return null};var dr=f(()=>{I()});var xs=(e)=>{let t=We(e.root),r=Object.keys(t);if(r.length>0)e.log.debug(`Found patches for packages: ${r.join(", ")}`,"stepDetectPatches");return{...e,patchMap:t}},Cs=(e)=>{if(!e.config)return e;let t=pe({options:e.options,config:e.config}),r=E(t)||{};if(e.options?.securityOverrides)e.log.debug("Merging security overrides","stepPrepareOverrides"),r={...r,...e.options.securityOverrides};return{...e,overridesData:t,overrides:r}},ws=(e)=>{if(!e.config)return e;let t=e.overrides||{},r=Object.keys(t).length>0,n={...e.config.dependencies,...e.config.devDependencies,...e.config.peerDependencies},i=Ue(t,n,e.log,e.options),s=lr(e.options,e.config,r,i);return{...e,hasRootOverrides:r,rootDeps:n,missingInRoot:i,mode:s}},Rs=(e)=>{if(!e.config||!e.mode||!e.overridesData)return e;let t=e.mode.depPaths;if(!(t&&t.length>0))return e;let n=e.options?.ignore||[],i=cr(t,e.root,n,e.log);if(i.length===0)return e;e.log.debug(`Processing ${i.length} workspace packages`,"stepProcessWorkspaces");let{appendix:s,allWorkspaceDeps:o}=Jt(i,e.overridesData,e.log,Xe);return{...e,workspaceAppendix:s,allWorkspaceDeps:o}},Ts=(e)=>{if(!e.config||!e.overrides)return e;let t=e.config.pastoralist?.appendix||{};return{...e,existingAppendix:t}},Vs=(e)=>{if(!e.config||!e.overrides)return e;let{dependencies:t={},devDependencies:r={},peerDependencies:n={}}=e.config,i=_({overrides:e.overrides,dependencies:t,devDependencies:r,peerDependencies:n,packageName:e.config.name||"root",securityOverrideDetails:e.options?.securityOverrideDetails,securityProvider:e.options?.securityProvider,manualOverrideReasons:e.options?.manualOverrideReasons});if(!e.workspaceAppendix)return{...e,appendix:i};return e.log.debug("Merging workspace appendix with root appendix","stepBuildAppendix"),Object.entries(e.workspaceAppendix).forEach(([s,o])=>{let a=i[s];if(!a)i[s]=o;else a.dependents={...a.dependents,...o.dependents}}),{...e,appendix:i}},$s=(e)=>{if(!e.appendix||!e.patchMap)return e;let t=He(e.appendix,e.patchMap);return{...e,appendix:t}},Is=(e)=>{if(!e.config||!e.appendix||!e.missingInRoot)return e;let t=e.config.pastoralist?.overridePaths||e.config.pastoralist?.resolutionPaths;return De(e.appendix,t,e.missingInRoot,e.log),{...e,overridePaths:t}},Es=(e)=>{if(!e.patchMap||!e.rootDeps)return e;let t=Ge(e.patchMap,e.rootDeps);if(t.length>0)e.log.info(`Found ${t.length} potentially unused patch files:`,"stepLogUnusedPatches"),t.forEach((r)=>e.log.info(` - ${r}`,"stepLogUnusedPatches")),e.log.info("Consider removing these patches if the packages are no longer used.","stepLogUnusedPatches");return{...e,allDeps:e.rootDeps}},Fs=(e)=>{if(e.finalOverrides!==void 0&&e.finalAppendix!==void 0)return e;let t=e.overrides||{},r=e.appendix||{};if(!e.overrides||!e.overridesData||!e.appendix)return{...e,finalOverrides:t,finalAppendix:r};return{...e,finalOverrides:e.overrides,finalAppendix:e.appendix}},Ns=(e)=>{if(e.isTesting)return e;if(!e.config||e.finalAppendix===void 0||e.finalOverrides===void 0)return e.log.debug(`Skipping write: config=${!!e.config}, appendix=${e.finalAppendix!==void 0}, overrides=${e.finalOverrides!==void 0}`,"stepWriteResult"),e;return e.log.debug(`Writing results: appendix keys=${Object.keys(e.finalAppendix||{}).length}, override keys=${Object.keys(e.finalOverrides||{}).length}`,"stepWriteResult"),ur({path:e.path,config:e.config,finalAppendix:e.finalAppendix,finalOverrides:e.finalOverrides,options:e.options,isTesting:e.isTesting}),e},Ls=(e,...t)=>{return t.reduce((r,n)=>n(r),e)},js=(e)=>{let t=!e.mode?.hasRootOverrides,r=e.mode?.mode==="root",n=Boolean(e.config);if(!(t&&r&&n))return e;return e.log.debug("No overrides found","update"),{...e,finalOverrides:{},finalAppendix:{}}},Qe=(e)=>{let t=e?.path||"package.json",r=e?.root||"./",n=e?.isTesting||!1,i=k||e?.debug||!1,s=y({file:"update",isLogging:i});if(Le(),V.clear(),!e.config)return s.debug("No config provided","update"),{options:e,path:t,root:r,isTesting:n,log:s};let o={options:e,path:t,root:r,isTesting:n,log:s,config:e.config},a=Ls(o,xs,Cs,ws,Rs,js,Ts,Vs,$s,Is,Es,Fs,Ns);if(k)a.log.debug("Update complete","update");return a};var Ze=f(()=>{T();P();I();_e();Ke();z();ge();dr()});class X{debug;isIRLFix;isIRLCatch;strict;log;retryOptions;constructor(e={}){this.debug=e.debug||!1,this.isIRLFix=e.isIRLFix||!1,this.isIRLCatch=e.isIRLCatch||!1,this.strict=e.strict||!1,this.log=y({file:"security/osv.ts",isLogging:this.debug}),this.retryOptions=e.retryOptions||{retries:3,factor:2,minTimeout:1000}}async isAvailable(){try{return(await fetch("https://api.osv.dev/v1/query",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({package:{name:"test",ecosystem:"npm"}})})).ok}catch{return!1}}async fetchFromOSVBatchAPI(e){let t=e.map((i)=>({package:{name:i.name,ecosystem:"npm"},version:i.version})),r=await fetch("https://api.osv.dev/v1/querybatch",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({queries:t})});if(!r.ok)throw Error(`HTTP ${r.status}`);return(await r.json()).results||[]}async fetchAlerts(e){if(this.log.debug(`OSV checking ${e.length} packages`,"fetchAlerts"),e.length===0)return[];let t=await U(async()=>{return this.fetchFromOSVBatchAPI(e)},{...this.retryOptions,onFailedAttempt:(s)=>{this.log.debug(`Batch API attempt ${s.attemptNumber} failed`,"fetchAlerts")}}).catch((s)=>{this.log.debug("Failed to fetch batch results after retries","fetchAlerts",{error:s});let o=s instanceof Error?s.message:"Unknown error";if(this.strict)throw Error(`OSV security check failed after ${this.retryOptions.retries} retries. Reason: ${o}. Failing due to --strict mode.`);return this.log.warn(`OSV security check failed after ${this.retryOptions.retries} retries. Your dependencies were NOT checked for vulnerabilities. Reason: ${o}. Run with --debug for details or --strict to fail on errors.`,"fetchAlerts"),[]}),r=e.map((s,o)=>{let a=t[o];return a?.vulns&&a.vulns.length>0?this.convertOSVAlerts(s,a.vulns):[]}).flat(),n=this.isIRLFix?[Te.ALERT_TO_RESOLVE]:[],i=this.isIRLCatch?[Te.ALERT_TO_CAPTURE]:[];return r.concat(n).concat(i)}convertOSVAlerts(e,t){return t.map((r)=>({packageName:e.name,currentVersion:e.version,vulnerableVersions:this.extractVersionRange(r),patchedVersion:this.extractPatchedVersion(r),severity:this.extractSeverity(r),title:r.summary||r.details||`Vulnerability in ${e.name}`,description:r.details,cve:this.extractCVE(r),url:r.references?.[0]?.url||`https://osv.dev/vulnerability/${r.id}`,fixAvailable:!!this.extractPatchedVersion(r)}))}extractVersionRange(e){let t=e.affected?.[0];if(t?.ranges?.[0]?.events){let r=t.ranges[0].events,n=r.find((s)=>s.introduced)?.introduced||"0",i=r.find((s)=>s.fixed)?.fixed;return i?`>= ${n} < ${i}`:`>= ${n}`}return""}extractPatchedVersion(e){return(e.affected?.[0]?.ranges?.[0]?.events||[]).find((i)=>i.fixed)?.fixed}extractSeverity(e){let t=e.database_specific?.severity||e.severity?.[0]?.score||"medium";if(typeof t==="string"){let r=t.toLowerCase();if(["low","medium","high","critical"].includes(r))return r}return"medium"}extractCVE(e){return e.aliases?.find((t)=>t.startsWith("CVE-"))}}var pr=f(()=>{P();T()});import{execFile as Us}from"child_process";import{promisify as Ds}from"util";class ye{owner;repo;token;log;constructor(e){this.token=e.token||process.env.GITHUB_TOKEN,this.log=y({file:"github.ts",isLogging:e.debug}),this.log.debug(`Token provided: ${this.token?"yes (length: "+this.token.length+")":"no"}`,"constructor"),this.owner=e.owner||"",this.repo=e.repo||""}async initialize(){if(!this.owner)this.owner=await this.getRepoOwner();if(!this.repo)this.repo=await this.getRepoName()}async getRepoOwner(){try{let{stdout:e}=await fe("git",["config","--get","remote.origin.url"]),t=e.trim();if(this.isGitHubUrl(t)){let r=t.match(/github\.com[:/]([^/]+)\//);if(r)return r[1]}}catch{this.log.debug("Failed to get repo owner from git","getRepoOwner")}throw Error("Unable to determine GitHub repository owner")}async getRepoName(){try{let{stdout:e}=await fe("git",["config","--get","remote.origin.url"]),t=e.trim();if(this.isGitHubUrl(t)){let r=t.match(/github\.com[:/][^/]+\/([^/.]+)/);if(r)return r[1]}}catch{this.log.debug("Failed to get repo name from git","getRepoName")}throw Error("Unable to determine GitHub repository name")}isGitHubUrl(e){if(e.startsWith("git@github.com:"))return!0;try{return new URL(e).hostname==="github.com"}catch{return!1}}async fetchAlerts(){this.log.debug("Fetching GitHub Dependabot alerts","fetchAlerts");let e=await this.fetchDependabotAlerts();this.log.debug(`Found ${e.length} Dependabot alerts`,"fetchAlerts");let t=this.convertToSecurityAlerts(e);return this.log.debug(`Converted to ${t.length} security alerts`,"fetchAlerts"),t}async fetchDependabotAlerts(){if(await this.initialize(),this.isMockMode())return this.fetchMockAlerts();return this.fetchRealAlerts()}isMockMode(){return process.env[ne.MOCK_MODE]==="true"}async fetchRealAlerts(){if(this.token)return this.log.debug("Using GitHub API with provided token","fetchRealAlerts"),this.fetchAlertsWithApi();if(await this.isGhCliAvailable())return this.log.debug("Using gh CLI (no token provided)","fetchRealAlerts"),this.fetchAlertsWithGhCli();throw Error("GitHub CLI not found and no GITHUB_TOKEN provided. Please install gh CLI or set GITHUB_TOKEN environment variable.")}async fetchMockAlerts(){if(this.log.debug("Using mock Dependabot alerts","fetchMockAlerts"),this.shouldForceVulnerable())return this.getMockVulnerableAlerts();return[]}shouldForceVulnerable(){return process.env[ne.FORCE_VULNERABLE]==="true"}async getMockVulnerableAlerts(){let e=process.env[ne.MOCK_FILE];if(e){let t=await this.loadMockFile(e);if(t)return t}return this.getDefaultMockAlerts()}async loadMockFile(e){try{let{readFileSync:t}=await import("fs"),r=t(e,"utf-8");return JSON.parse(r)}catch(t){return this.log.debug("Failed to read mock file","loadMockFile",{error:t}),null}}getDefaultMockAlerts(){return[Pt,At]}async isGhCliAvailable(){try{return await fe("gh",["--version"]),!0}catch{return!1}}async executeGhCli(){let e=["api",`repos/${this.owner}/${this.repo}/dependabot/alerts`,"--paginate"];this.log.debug(`Fetching alerts with gh CLI: gh ${e.join(" ")}`,"executeGhCli");let{stdout:t}=await fe("gh",e,{timeout:Ms});return this.log.debug(`gh CLI stdout length: ${t.length}`,"executeGhCli"),t}async fetchAlertsWithGhCli(){try{let e=await U(()=>this.executeGhCli(),{retries:3,factor:2,minTimeout:1000,onFailedAttempt:(r)=>{this.log.debug(`gh CLI attempt ${r.attemptNumber} failed`,"fetchAlertsWithGhCli")}}),t=JSON.parse(e);return this.log.debug(`Parsed ${Array.isArray(t)?t.length:"non-array"} alerts`,"fetchAlertsWithGhCli"),Array.isArray(t)?t:[]}catch(e){throw this.log.error("Failed to fetch alerts with gh CLI","fetchAlertsWithGhCli",{error:e}),Error(`Failed to fetch Dependabot alerts: ${e}`)}}async fetchFromGitHubAPI(){let e=`https://api.github.com/repos/${this.owner}/${this.repo}/dependabot/alerts`,t=new AbortController,r=setTimeout(()=>t.abort(),_s);try{let n=await fetch(e,{headers:{Authorization:`Bearer ${this.token}`,Accept:"application/vnd.github.v3+json"},signal:t.signal});if(!n.ok){let s=await n.json();throw Error(`GitHub API error: ${s.message||n.statusText}`)}let i=await n.json();return Array.isArray(i)?i:[]}finally{clearTimeout(r)}}async fetchAlertsWithApi(){try{return await U(()=>this.fetchFromGitHubAPI(),{retries:3,factor:2,minTimeout:1000,onFailedAttempt:(e)=>{this.log.debug(`GitHub API attempt ${e.attemptNumber} failed`,"fetchAlertsWithApi")}})}catch(e){throw this.log.error("Failed to fetch alerts with API","fetchAlertsWithApi",{error:e}),Error(`Failed to fetch Dependabot alerts: ${e}`)}}convertToSecurityAlerts(e){return e.filter((t)=>t.state==="open").map((t)=>{let{security_vulnerability:r,security_advisory:n}=t,i=this.extractCurrentVersion(t);return{packageName:r.package.name,currentVersion:i,vulnerableVersions:r.vulnerable_version_range,patchedVersion:r.first_patched_version?.identifier,severity:this.normalizeSeverity(r.severity),title:n.summary,description:n.description,cve:n.cve_id,url:t.html_url,fixAvailable:!!r.first_patched_version}})}extractCurrentVersion(e){let t=e.security_vulnerability.vulnerable_version_range;if(t.includes(">=")&&t.includes("<=")){let r=t.match(/>= ?([^\s,]+)/);return r?r[1]:"unknown"}if(t.includes(">=")){let r=t.match(/>= ?([^\s,]+)/);return r?r[1]:"unknown"}return"unknown"}normalizeSeverity(e){let t=e.toLowerCase();switch(t){case"low":case"medium":case"high":case"critical":return t;default:return"medium"}}}var fe,_s=30000,Ms=60000;var hr=f(()=>{P();T();fe=Ds(Us)});import{execFile as Ws}from"child_process";import{promisify as Gs}from"util";import*as fr from"readline/promises";class Q{log;constructor(e={}){this.log=y({file:"security/cli-installer.ts",isLogging:e.debug})}async isInstalled(e){try{return await me("which",[e]),!0}catch{return!1}}async isInstalledGlobally(e){try{let{stdout:t}=await me("npm",["list","-g",e,"--depth=0"]);return t.includes(e)}catch{return!1}}async installGlobally(e){this.log.info(`Installing ${e} globally...`,"installGlobally");try{await me("npm",["install","-g",e],{timeout:120000}),this.log.info(`Successfully installed ${e}`,"installGlobally")}catch(t){throw this.log.error(`Failed to install ${e}`,"installGlobally",{error:t}),Error(`Failed to install ${e}: ${t}`)}}async ensureInstalled(e){let{packageName:t,cliCommand:r}=e;if(await this.isInstalled(r))return this.log.debug(`${r} is already installed`,"ensureInstalled"),!0;if(await this.isInstalledGlobally(t))return this.log.debug(`${t} is installed globally but command not in PATH`,"ensureInstalled"),!0;this.log.info(`${r} not found, installing ${t}...`,"ensureInstalled");try{if(await this.installGlobally(t),!await this.isInstalled(r))return this.log.info(`${t} was installed but ${r} is still not available. Please ensure it's in your PATH.`,"ensureInstalled"),!1;return!0}catch(s){return this.log.error(`Could not install ${t}`,"ensureInstalled",{error:s}),!1}}async getVersion(e){try{let{stdout:t}=await me(e,["--version"]);return t.trim()}catch{return}}}class tt{prompts;constructor(e={confirm:Ks,select:Bs,input:qs}){this.prompts=e}async promptForSecurityActions(e,t){if(e.length===0)return[];console.log(`
|
|
10
10
|
\uD83D\uDD12 Security Vulnerabilities Found
|
|
11
11
|
`),console.log("═".repeat(50));let r=this.generateSummary(e);if(console.log(r),!await this.prompts.confirm("Would you like to review and apply security fixes?",!0))return[];let i=[];for(let o of t){let a=e.find((l)=>l.packageName===o.packageName);if(!a)continue;if(console.log(`
|
|
12
12
|
\uD83D\uDCE6 ${o.packageName}`),console.log(` Current: ${o.fromVersion}`),console.log(` ${this.getSeverityEmoji(a.severity)} ${a.title}`),a.cve)console.log(` CVE: ${a.cve}`);let c=await this.prompts.select("How would you like to handle this vulnerability?",[{name:`✅ Apply fix: Update to ${o.toVersion}`,value:"apply"},{name:"⏭️ Skip this vulnerability",value:"skip"},{name:"\uD83D\uDCDD Enter custom version",value:"custom"}]);if(c==="apply")i.push(o);else if(c==="custom"){let l=await this.prompts.input("Enter the version to use:",o.toVersion);i.push(Object.assign({},o,{toVersion:l}))}}if(i.length>0){if(console.log(`
|
|
13
13
|
\uD83D\uDCCB Selected Overrides:
|
|
14
14
|
`),i.forEach((a)=>{console.log(` ${a.packageName}: ${a.fromVersion} → ${a.toVersion}`)}),!await this.prompts.confirm("Apply these overrides to your package.json?",!0))return[]}return i}generateSummary(e){let t=e.reduce((n,i)=>{return n[i.severity]++,n},{critical:0,high:0,medium:0,low:0}),r=`Found ${e.length} vulnerable package(s):
|
|
15
|
-
`;if(t.critical>0)r+=` ${
|
|
16
|
-
`;if(t.high>0)r+=` ${
|
|
17
|
-
`;if(t.medium>0)r+=` ${
|
|
18
|
-
`;if(t.low>0)r+=` ${
|
|
19
|
-
`;return r}getSeverityEmoji(e){switch(e.toLowerCase()){case"critical":return H("[!]");case"high":return H("[!]");case"medium":return Re("[*]");case"low":return Te("[i]");default:return $t("[*]")}}}var fe,lr=(e)=>{return{low:1,medium:2,high:3,critical:4}[e.toLowerCase()]||0},dr=(e)=>{let t=e.reduce((r,n)=>{let i=`${n.packageName}@${n.currentVersion}:${n.cve||n.title}`,s=r.get(i);if(!s||lr(n.severity)>lr(s.severity))r.set(i,n);return r},new Map);return Array.from(t.values())},pr=(e)=>{let t=Object.assign({},e.dependencies,e.devDependencies,e.peerDependencies);return Object.entries(t).map(([r,n])=>({name:r,version:n.replace(/^[\^~]/,"")}))},Ts=(e,t)=>{try{let r=e.replace(/^[\^~]/,"");if(t.includes(">=")&&t.includes("<")){let[,n]=t.match(/>= ?([^\s,]+)/)||[],[,i]=t.match(/< ?([^\s,]+)/)||[];if(n&&i)return $(r,n)>=0&&$(r,i)<0}if(t.startsWith("<")){let n=t.replace(/< ?/,"");return $(r,n)<0}if(t.startsWith("<=")){let n=t.replace(/<= ?/,"");return $(r,n)<=0}return!1}catch{return!1}},hr=(e,t)=>{let r=Object.assign({},e.dependencies,e.devDependencies,e.peerDependencies);return t.filter((n)=>{let i=r[n.packageName];if(!i)return!1;return n.currentVersion=i,Ts(i,n.vulnerableVersions)})},Xe=()=>{return ur.createInterface({input:process.stdin,output:process.stdout})},Vs=async(e,t=!0)=>{let r=Xe(),n=t?"Y/n":"y/N",i=await r.question(`${e} (${n}): `);r.close();let s=i.trim();if(s==="")return t;return s.toLowerCase().startsWith("y")},$s=async(e,t)=>{let r=Xe();console.log(e),t.forEach((i,s)=>{console.log(` ${s+1}) ${i.name}`)});let n=null;while(n===null){let i=await r.question(`Select (1-${t.length}): `),s=parseInt(i.trim(),10);if(s>=1&&s<=t.length)n=t[s-1].value;else console.log("Invalid selection. Please try again.")}return r.close(),n},Is=async(e,t="")=>{let r=Xe(),n=t?`${e} (${t}): `:`${e}: `,i=await r.question(n);return r.close(),i.trim()||t};var ye=f(()=>{P();fe=Rs(ws)});import{execFile as Fs}from"child_process";import{promisify as Ns}from"util";class me{log;installer;token;constructor(e={}){this.log=y({file:"security/snyk.ts",isLogging:e.debug||!1}),this.installer=new X({debug:e.debug}),this.token=e.token||process.env.SNYK_TOKEN}async ensureInstalled(){return this.installer.ensureInstalled({packageName:"snyk",cliCommand:"snyk"})}async isAuthenticated(){if(!this.token)try{return await Ze("snyk",["config","get","api"]),!0}catch{return!1}return!0}async authenticate(){if(this.token)await Ze("snyk",["config","set",`api=${this.token}`]),this.log.debug("Authenticated with Snyk using provided token","authenticate");else throw Error("Snyk requires authentication. Set SNYK_TOKEN or provide --securityProviderToken")}async validatePrerequisites(){if(!await this.ensureInstalled())return this.log.info("Snyk CLI not available, skipping Snyk scan","validatePrerequisites"),!1;if(!await this.isAuthenticated())try{return await this.authenticate(),!0}catch(r){return this.log.info("Snyk authentication failed, skipping Snyk scan","validatePrerequisites",{error:r}),!1}return!0}async runSnykScan(){let{stdout:e}=await Ze("snyk",["test","--json"],{timeout:60000});return JSON.parse(e)}async fetchAlerts(){if(!await this.validatePrerequisites())return[];try{let t=await this.runSnykScan();return this.convertSnykVulnerabilities(t)}catch(t){let r=t;if(r.stdout)try{let n=JSON.parse(r.stdout);return this.convertSnykVulnerabilities(n)}catch{this.log.debug("Failed to parse Snyk error output","fetchAlerts",{error:t})}return this.log.debug("Snyk scan failed","fetchAlerts",{error:t}),[]}}convertSnykVulnerabilities(e){if(!e.vulnerabilities||!Array.isArray(e.vulnerabilities))return[];return e.vulnerabilities.map((t)=>this.convertVulnToAlert(t))}convertVulnToAlert(e){let t=e.packageName||e.name||"",r=e.version,n=e.semver?.vulnerable||"",i=this.extractPatchedVersion(e),s=this.normalizeSeverity(e.severity),o=e.title,a=e.description,c=e.identifiers?.CVE?.[0],l=e.url||`https://snyk.io/vuln/${e.id}`;return{packageName:t,currentVersion:r,vulnerableVersions:n,patchedVersion:i,severity:s,title:o,description:a,cve:c,url:l,fixAvailable:!!i}}extractPatchedVersion(e){if(e.fixedIn&&e.fixedIn.length>0)return e.fixedIn[0];if(e.upgradePath&&e.upgradePath.length>1){let t=e.upgradePath[e.upgradePath.length-1];if(typeof t==="string")return t.split("@")[1]}return}normalizeSeverity(e){let t=e.toLowerCase();switch(t){case"low":case"medium":case"high":case"critical":return t;default:return"medium"}}}var Ze;var gr=f(()=>{P();ye();Ze=Ns(Fs)});import{execFile as Es}from"child_process";import{promisify as Ls}from"util";class be{log;installer;token;constructor(e={}){this.log=y({file:"security/socket.ts",isLogging:e.debug||!1}),this.installer=new X({debug:e.debug}),this.token=e.token||process.env.SOCKET_SECURITY_API_KEY}async ensureInstalled(){return this.installer.ensureInstalled({packageName:"@socketsecurity/cli",cliCommand:"socket"})}async isAuthenticated(){return!!this.token}async validatePrerequisites(){if(!await this.ensureInstalled())return this.log.info("Socket CLI not available, skipping Socket scan","validatePrerequisites"),!1;if(!await this.isAuthenticated())return this.log.info("Socket requires authentication. Set SOCKET_SECURITY_API_KEY or provide --securityProviderToken","validatePrerequisites"),!1;return!0}async runSocketScan(){let e={...process.env,SOCKET_SECURITY_API_KEY:this.token},{stdout:t}=await js("socket",["report","create","--format","json"],{timeout:60000,env:e});return JSON.parse(t)}async fetchAlerts(){if(!await this.validatePrerequisites())return[];try{let t=await this.runSocketScan();return this.convertSocketAlerts(t)}catch(t){return this.log.debug("Socket scan failed","fetchAlerts",{error:t}),[]}}convertSocketAlerts(e){if(!e?.packages)return[];return e.packages.filter((t)=>t.issues&&t.issues.length>0).flatMap((t)=>t.issues.map((r)=>this.convertIssueToAlert(t,r)))}convertIssueToAlert(e,t){let r=t.type==="vulnerability",n=e.name,i=e.version,s=r?`<= ${i}`:"",o=void 0,a=this.mapSocketSeverity(t.severity),c=t.title||t.type,l=t.description,u=r?t.cve:void 0,d=t.url||`https://socket.dev/npm/package/${n}/overview/${i}`,h=!1;return{packageName:n,currentVersion:i,vulnerableVersions:s,patchedVersion:void 0,severity:a,title:c,description:l,cve:u,url:d,fixAvailable:!1}}mapSocketSeverity(e){switch(e.toLowerCase()){case"critical":return"critical";case"high":return"high";case"medium":case"moderate":return"medium";case"low":case"info":return"low";default:return"medium"}}}var js;var fr=f(()=>{P();ye();js=Ls(Es)});var ve=f(()=>{ar();cr();gr();fr()});var yr=()=>{};import{readFileSync as mr,copyFileSync as br,writeFileSync as Us,existsSync as Q}from"fs";import{resolve as Z}from"path";class Se{providers;log;cache;constructor(e){this.log=y({file:"security/index.ts",isLogging:e.debug}),this.providers=this.createProviders(e),this.cache=new ie({max:500,ttl:3600000})}createProviders(e){return(Array.isArray(e.provider)?e.provider:[e.provider||"osv"]).map((r)=>this.createProvider(r,e))}createProvider(e,t){switch(e){case"osv":return new Y({debug:t.debug,isIRLFix:t.isIRLFix,isIRLCatch:t.isIRLCatch});case"github":return new ge({debug:t.debug,token:t.token});case"snyk":return new me({debug:t.debug,token:t.token});case"socket":return new be({debug:t.debug,token:t.token});default:return this.log.debug(`Provider ${e} not yet implemented, using OSV`,"createProvider"),new Y({debug:t.debug,isIRLFix:t.isIRLFix,isIRLCatch:t.isIRLCatch})}}generateCacheKey(e){let t=e.map((n)=>`${n.name}@${n.version}`).sort().join("|");return`${this.providers.map((n)=>n.constructor.name).sort().join("|")}:${t}`}async checkSecurity(e,t={}){this.log.debug("Starting security check","checkSecurity");try{let r=pr(e);if(r.length===0)return this.log.debug("No packages to check","checkSecurity"),{alerts:[],overrides:[],updates:[]};let n=this.generateCacheKey(r),i=this.cache.get(n),s;if(i)this.log.debug("Using cached security results","checkSecurity"),s=i;else s=(await Promise.all(this.providers.map((h)=>h.fetchAlerts(r)))).flat(),this.cache.set(n,s);this.log.debug(`Found ${s.length} security alerts from ${this.providers.length} provider(s)`,"checkSecurity");let o=dr(s);if(t.depPaths&&t.depPaths.length>0){this.log.debug("Scanning workspace packages for vulnerabilities","checkSecurity");let d=await this.findWorkspaceVulnerabilities(t.depPaths,t.root||"./",s);o=[...o,...d]}this.log.debug(`Found ${o.length} vulnerable packages in dependencies`,"checkSecurity");let c=this.generateOverrides(o),l=await this.checkOverrideUpdates(e,s);if(t.interactive&&o.length>0)c=await new Qe().promptForSecurityActions(o,c);return{alerts:o,overrides:c,updates:l}}catch(r){throw this.log.error("Security check failed","checkSecurity",{error:r}),r}}readPackageFile(e){try{let t=mr(e,"utf-8"),r=JSON.parse(t);if(!(r&&typeof r==="object"))return this.log.debug(`Invalid package.json format in ${e}`,"readPackageFile"),null;return r}catch(t){return this.log.debug(`Failed to check ${e}`,"readPackageFile",{error:t}),null}}isNewVulnerability(e,t){return!t.find((n)=>n.packageName===e.packageName&&n.currentVersion===e.currentVersion)}extractNewVulnerabilities(e,t,r){return hr(e,t).filter((i)=>this.isNewVulnerability(i,r))}async findWorkspaceVulnerabilities(e,t,r){try{let n=e.map((a)=>Z(t,a)),i=await Lt(n,{ignore:["**/node_modules/**"],absolute:!0});return(await Promise.all(i.map(async(a)=>{let c=this.readPackageFile(a);if(!c)return[];return this.extractNewVulnerabilities(c,r,[])}))).flat()}catch(n){return this.log.error("Failed to find workspace vulnerabilities","findWorkspaceVulnerabilities",{error:n}),[]}}async checkOverrideUpdates(e,t){let r=e.overrides||e.pnpm?.overrides||e.resolutions||{},n=e.pastoralist?.appendix||{},s=Object.entries(r).filter(([a,c])=>typeof c==="string").map(([a,c])=>{let l=`${a}@${c}`,u=n[l];if(!u?.ledger?.securityChecked)return null;let p=t.filter((v)=>v.packageName===a&&v.patchedVersion).find((v)=>$(v.patchedVersion,c)>0);if(!p)return null;return{packageName:a,currentOverride:c,newerVersion:p.patchedVersion,reason:`Newer security patch available: ${p.title}`,addedDate:u.ledger?.addedDate}}).filter((a)=>a!==null);if(s.length>0)this.log.debug(`Found ${s.length} override updates available`,"checkOverrideUpdates");return s}generateOverrides(e){return e.filter((t)=>t.fixAvailable&&t.patchedVersion).map((t)=>{let r={packageName:t.packageName,fromVersion:t.currentVersion,toVersion:t.patchedVersion,reason:`Security fix: ${t.title} (${t.severity})`,severity:t.severity},n=t.cve?{cve:t.cve}:{},i=t.description?{description:t.description}:{},s=t.url?{url:t.url}:{};return Object.assign({},r,n,i,s)})}generatePackageOverrides(e){return e.reduce((t,r)=>{let n=t[r.packageName];if(n&&typeof n==="string"){if($(r.toVersion,n)>0)return Object.assign({},t,{[r.packageName]:r.toVersion});return t}return Object.assign({},t,{[r.packageName]:r.toVersion})},{})}formatVulnerabilityEntry(e){let t=[];if(t.push(`[${e.severity.toUpperCase()}] ${e.packageName}@${e.currentVersion}
|
|
15
|
+
`;if(t.critical>0)r+=` ${K("[CRITICAL]")} ${t.critical}
|
|
16
|
+
`;if(t.high>0)r+=` ${K("[HIGH] ")} ${t.high}
|
|
17
|
+
`;if(t.medium>0)r+=` ${$e("[MEDIUM] ")} ${t.medium}
|
|
18
|
+
`;if(t.low>0)r+=` ${Ie("[LOW] ")} ${t.low}
|
|
19
|
+
`;return r}getSeverityEmoji(e){switch(e.toLowerCase()){case"critical":return K("[!]");case"high":return K("[!]");case"medium":return $e("[*]");case"low":return Ie("[i]");default:return Lt("[*]")}}}var me,gr=(e)=>{return{low:1,medium:2,high:3,critical:4}[e.toLowerCase()]||0},yr=(e)=>{let t=e.reduce((r,n)=>{let i=`${n.packageName}@${n.currentVersion}:${n.cve||n.title}`,s=r.get(i);if(!s||gr(n.severity)>gr(s.severity))r.set(i,n);return r},new Map);return Array.from(t.values())},mr=(e)=>{let t=Object.assign({},e.dependencies,e.devDependencies,e.peerDependencies);return Object.entries(t).map(([r,n])=>({name:r,version:n.replace(/^[\^~]/,"")}))},Hs=(e,t)=>{try{let r=e.replace(/^[\^~]/,"");if(t.includes(">=")&&t.includes("<")){let[,n]=t.match(/>= ?([^\s,]+)/)||[],[,i]=t.match(/< ?([^\s,]+)/)||[];if(n&&i)return $(r,n)>=0&&$(r,i)<0}if(t.startsWith("<")){let n=t.replace(/< ?/,"");return $(r,n)<0}if(t.startsWith("<=")){let n=t.replace(/<= ?/,"");return $(r,n)<=0}return!1}catch{return!1}},br=(e,t)=>{let r=Object.assign({},e.dependencies,e.devDependencies,e.peerDependencies);return t.filter((n)=>{let i=r[n.packageName];if(!i)return!1;return n.currentVersion=i,Hs(i,n.vulnerableVersions)})},et=()=>{return fr.createInterface({input:process.stdin,output:process.stdout})},Ks=async(e,t=!0)=>{let r=et(),n=t?"Y/n":"y/N",i=await r.question(`${e} (${n}): `);r.close();let s=i.trim();if(s==="")return t;return s.toLowerCase().startsWith("y")},Bs=async(e,t)=>{let r=et();console.log(e),t.forEach((i,s)=>{console.log(` ${s+1}) ${i.name}`)});let n=null;while(n===null){let i=await r.question(`Select (1-${t.length}): `),s=parseInt(i.trim(),10);if(s>=1&&s<=t.length)n=t[s-1].value;else console.log("Invalid selection. Please try again.")}return r.close(),n},qs=async(e,t="")=>{let r=et(),n=t?`${e} (${t}): `:`${e}: `,i=await r.question(n);return r.close(),i.trim()||t};var be=f(()=>{P();me=Gs(Ws)});import{execFile as Js}from"child_process";import{promisify as Ys}from"util";class ve{log;installer;token;strict;constructor(e={}){this.log=y({file:"security/snyk.ts",isLogging:e.debug||!1}),this.installer=new Q({debug:e.debug}),this.token=e.token||process.env.SNYK_TOKEN,this.strict=e.strict||!1,this.log.warn("Snyk provider is EXPERIMENTAL. Report issues at https://github.com/yowainwright/pastoralist/issues","constructor")}async ensureInstalled(){return this.installer.ensureInstalled({packageName:"snyk",cliCommand:"snyk"})}async isAuthenticated(){if(!this.token)try{return await rt("snyk",["config","get","api"]),!0}catch{return!1}return!0}async authenticate(){if(this.token)await rt("snyk",["config","set",`api=${this.token}`]),this.log.debug("Authenticated with Snyk using provided token","authenticate");else throw Error("Snyk requires authentication. Set SNYK_TOKEN or provide --securityProviderToken")}async validatePrerequisites(){if(!await this.ensureInstalled())return this.log.info("Snyk CLI not available, skipping Snyk scan","validatePrerequisites"),!1;if(!await this.isAuthenticated())try{return await this.authenticate(),!0}catch(r){return this.log.info("Snyk authentication failed, skipping Snyk scan","validatePrerequisites",{error:r}),!1}return!0}async runSnykScan(){let{stdout:e}=await rt("snyk",["test","--json"],{timeout:60000});return JSON.parse(e)}async fetchAlerts(){if(!await this.validatePrerequisites())return[];try{let t=await this.runSnykScan();return this.convertSnykVulnerabilities(t)}catch(t){let r=t;if(r.stdout)try{let i=JSON.parse(r.stdout);return this.convertSnykVulnerabilities(i)}catch{this.log.debug("Failed to parse Snyk error output","fetchAlerts",{error:t})}this.log.debug("Snyk scan failed","fetchAlerts",{error:t});let n=t instanceof Error?t.message:"Unknown error";if(this.strict)throw Error(`Snyk security check failed. Reason: ${n}. Failing due to --strict mode.`);return this.log.warn(`Snyk security check failed. Your dependencies were NOT checked. Reason: ${n}. Run with --debug for details or --strict to fail on errors.`,"fetchAlerts"),[]}}convertSnykVulnerabilities(e){if(!e.vulnerabilities||!Array.isArray(e.vulnerabilities))return[];return e.vulnerabilities.map((t)=>this.convertVulnToAlert(t))}convertVulnToAlert(e){let t=e.packageName||e.name||"",r=e.version,n=e.semver?.vulnerable||"",i=this.extractPatchedVersion(e),s=this.normalizeSeverity(e.severity),o=e.title,a=e.description,c=e.identifiers?.CVE?.[0],l=e.url||`https://snyk.io/vuln/${e.id}`;return{packageName:t,currentVersion:r,vulnerableVersions:n,patchedVersion:i,severity:s,title:o,description:a,cve:c,url:l,fixAvailable:!!i}}extractPatchedVersion(e){if(e.fixedIn&&e.fixedIn.length>0)return e.fixedIn[0];if(e.upgradePath&&e.upgradePath.length>1){let t=e.upgradePath[e.upgradePath.length-1];if(typeof t==="string")return t.split("@")[1]}return}normalizeSeverity(e){let t=e.toLowerCase();switch(t){case"low":case"medium":case"high":case"critical":return t;default:return"medium"}}}var rt;var vr=f(()=>{P();be();rt=Ys(Js)});import{execFile as zs}from"child_process";import{promisify as Xs}from"util";class Se{log;installer;token;strict;constructor(e={}){this.log=y({file:"security/socket.ts",isLogging:e.debug||!1}),this.installer=new Q({debug:e.debug}),this.token=e.token||process.env.SOCKET_SECURITY_API_KEY,this.strict=e.strict||!1,this.log.warn("Socket provider is EXPERIMENTAL. Report issues at https://github.com/yowainwright/pastoralist/issues","constructor")}async ensureInstalled(){return this.installer.ensureInstalled({packageName:"@socketsecurity/cli",cliCommand:"socket"})}async isAuthenticated(){return!!this.token}async validatePrerequisites(){if(!await this.ensureInstalled())return this.log.info("Socket CLI not available, skipping Socket scan","validatePrerequisites"),!1;if(!await this.isAuthenticated())return this.log.info("Socket requires authentication. Set SOCKET_SECURITY_API_KEY or provide --securityProviderToken","validatePrerequisites"),!1;return!0}async runSocketScan(){let e={...process.env,SOCKET_SECURITY_API_KEY:this.token},{stdout:t}=await Qs("socket",["report","create","--format","json"],{timeout:60000,env:e});return JSON.parse(t)}async fetchAlerts(){if(!await this.validatePrerequisites())return[];try{let t=await this.runSocketScan();return this.convertSocketAlerts(t)}catch(t){this.log.debug("Socket scan failed","fetchAlerts",{error:t});let r=t instanceof Error?t.message:"Unknown error";if(this.strict)throw Error(`Socket security check failed. Reason: ${r}. Failing due to --strict mode.`);return this.log.warn(`Socket security check failed. Your dependencies were NOT checked. Reason: ${r}. Run with --debug for details or --strict to fail on errors.`,"fetchAlerts"),[]}}convertSocketAlerts(e){if(!e?.packages)return[];return e.packages.filter((t)=>t.issues&&t.issues.length>0).flatMap((t)=>t.issues.map((r)=>this.convertIssueToAlert(t,r)))}convertIssueToAlert(e,t){let r=t.type==="vulnerability",n=e.name,i=e.version,s=r?`<= ${i}`:"",o=void 0,a=this.mapSocketSeverity(t.severity),c=t.title||t.type,l=t.description,u=r?t.cve:void 0,d=t.url||`https://socket.dev/npm/package/${n}/overview/${i}`,g=!1;return{packageName:n,currentVersion:i,vulnerableVersions:s,patchedVersion:void 0,severity:a,title:c,description:l,cve:u,url:d,fixAvailable:!1}}mapSocketSeverity(e){switch(e.toLowerCase()){case"critical":return"critical";case"high":return"high";case"medium":case"moderate":return"medium";case"low":case"info":return"low";default:return"medium"}}}var Qs;var Sr=f(()=>{P();be();Qs=Xs(zs)});var Oe=f(()=>{pr();hr();vr();Sr()});var Or=()=>{};import{readFileSync as Pr,copyFileSync as Ar,writeFileSync as Zs,existsSync as Z}from"fs";import{resolve as ee}from"path";class Pe{providers;log;cache;constructor(e){this.log=y({file:"security/index.ts",isLogging:e.debug}),this.providers=this.createProviders(e),this.cache=new oe({max:500,ttl:3600000})}createProviders(e){return(Array.isArray(e.provider)?e.provider:[e.provider||"osv"]).map((r)=>this.createProvider(r,e))}createProvider(e,t){switch(e){case"osv":return new X({debug:t.debug,isIRLFix:t.isIRLFix,isIRLCatch:t.isIRLCatch,strict:t.strict});case"github":return new ye({debug:t.debug,token:t.token});case"snyk":return new ve({debug:t.debug,token:t.token,strict:t.strict});case"socket":return new Se({debug:t.debug,token:t.token,strict:t.strict});default:return this.log.debug(`Provider ${e} not yet implemented, using OSV`,"createProvider"),new X({debug:t.debug,isIRLFix:t.isIRLFix,isIRLCatch:t.isIRLCatch,strict:t.strict})}}generateCacheKey(e){let t=e.map((n)=>`${n.name}@${n.version}`).sort().join("|");return`${this.providers.map((n)=>n.constructor.name).sort().join("|")}:${t}`}async checkSecurity(e,t={}){this.log.debug("Starting security check","checkSecurity");try{let r=mr(e);if(r.length===0)return this.log.debug("No packages to check","checkSecurity"),{alerts:[],overrides:[],updates:[]};let n=this.generateCacheKey(r),i=this.cache.get(n),s;if(i)this.log.debug("Using cached security results","checkSecurity"),s=i;else s=(await Promise.all(this.providers.map((g)=>g.fetchAlerts(r)))).flat(),this.cache.set(n,s);this.log.debug(`Found ${s.length} security alerts from ${this.providers.length} provider(s)`,"checkSecurity");let o=yr(s);if(t.depPaths&&t.depPaths.length>0){this.log.debug("Scanning workspace packages for vulnerabilities","checkSecurity");let d=await this.findWorkspaceVulnerabilities(t.depPaths,t.root||"./",s);o=[...o,...d]}this.log.debug(`Found ${o.length} vulnerable packages in dependencies`,"checkSecurity");let c=this.generateOverrides(o),l=await this.checkOverrideUpdates(e,s);if(t.interactive&&o.length>0)c=await new tt().promptForSecurityActions(o,c);return{alerts:o,overrides:c,updates:l}}catch(r){throw this.log.error("Security check failed","checkSecurity",{error:r}),r}}readPackageFile(e){try{let t=Pr(e,"utf-8"),r=JSON.parse(t);if(!(r&&typeof r==="object"))return this.log.debug(`Invalid package.json format in ${e}`,"readPackageFile"),null;return r}catch(t){return this.log.debug(`Failed to check ${e}`,"readPackageFile",{error:t}),null}}isNewVulnerability(e,t){return!t.find((n)=>n.packageName===e.packageName&&n.currentVersion===e.currentVersion)}extractNewVulnerabilities(e,t,r){return br(e,t).filter((i)=>this.isNewVulnerability(i,r))}async findWorkspaceVulnerabilities(e,t,r){try{let n=e.map((a)=>ee(t,a)),i=await Mt(n,{ignore:["**/node_modules/**"],absolute:!0});return(await Promise.all(i.map(async(a)=>{let c=this.readPackageFile(a);if(!c)return[];return this.extractNewVulnerabilities(c,r,[])}))).flat()}catch(n){return this.log.error("Failed to find workspace vulnerabilities","findWorkspaceVulnerabilities",{error:n}),[]}}async checkOverrideUpdates(e,t){let r=e.overrides||e.pnpm?.overrides||e.resolutions||{},n=e.pastoralist?.appendix||{},s=Object.entries(r).filter(([a,c])=>typeof c==="string").map(([a,c])=>{let l=`${a}@${c}`,u=n[l];if(!u?.ledger?.securityChecked)return null;let p=t.filter((b)=>b.packageName===a&&b.patchedVersion).find((b)=>$(b.patchedVersion,c)>0);if(!p)return null;return{packageName:a,currentOverride:c,newerVersion:p.patchedVersion,reason:`Newer security patch available: ${p.title}`,addedDate:u.ledger?.addedDate}}).filter((a)=>a!==null);if(s.length>0)this.log.debug(`Found ${s.length} override updates available`,"checkOverrideUpdates");return s}generateOverrides(e){return e.filter((t)=>t.fixAvailable&&t.patchedVersion).map((t)=>{let r={packageName:t.packageName,fromVersion:t.currentVersion,toVersion:t.patchedVersion,reason:`Security fix: ${t.title} (${t.severity})`,severity:t.severity},n=t.cve?{cve:t.cve}:{},i=t.description?{description:t.description}:{},s=t.url?{url:t.url}:{};return Object.assign({},r,n,i,s)})}generatePackageOverrides(e){return e.reduce((t,r)=>{let n=t[r.packageName];if(n&&typeof n==="string"){if($(r.toVersion,n)>0)return Object.assign({},t,{[r.packageName]:r.toVersion});return t}return Object.assign({},t,{[r.packageName]:r.toVersion})},{})}formatVulnerabilityEntry(e){let t=[];if(t.push(`[${e.severity.toUpperCase()}] ${e.packageName}@${e.currentVersion}
|
|
20
20
|
`),t.push(` ${e.title}
|
|
21
21
|
`),Boolean(e.cve))t.push(` CVE: ${e.cve}
|
|
22
22
|
`);if(e.fixAvailable&&e.patchedVersion)t.push(` Fix available: ${e.patchedVersion}
|
|
@@ -34,11 +34,11 @@ Security Check Report
|
|
|
34
34
|
`;if(e.length===0)return r+`No vulnerable packages found
|
|
35
35
|
`;let i=`Found ${e.length} vulnerable package(s):
|
|
36
36
|
|
|
37
|
-
`,s=e.map((a)=>this.formatVulnerabilityEntry(a)).join(""),o=this.formatOverridesSection(t);return[r,i,s,o].filter(Boolean).join("")}createBackup(e){let t=`${e}.backup-${Date.now()}`;return
|
|
37
|
+
`,s=e.map((a)=>this.formatVulnerabilityEntry(a)).join(""),o=this.formatOverridesSection(t);return[r,i,s,o].filter(Boolean).join("")}createBackup(e){let t=`${e}.backup-${Date.now()}`;return Ar(e,t),this.log.debug(`Created backup at ${t}`,"createBackup"),t}applyOverridesToPackageJson(e,t,r){if(t==="pnpm")return{...e,pnpm:{...e.pnpm||{},overrides:{...e.pnpm?.overrides||{},...r}}};let n=this.getOverrideField(t);return{...e,[n]:{...e[n]||{},...r}}}logInstallInstructions(e){console.log(`
|
|
38
38
|
⚠️ Don't forget to run your package manager install command:`);let t={yarn:"yarn install",pnpm:"pnpm install",bun:"bun install",npm:"npm install"};console.log(` ${t[e]||t.npm}`)}logSuccess(e,t,r,n,i){if(console.log(`
|
|
39
39
|
✅ Auto-fix applied successfully!`),console.log(`\uD83D\uDCDD Updated ${e} with ${Object.keys(r).length} security override(s)`),console.log(`\uD83D\uDCBE Backup saved to ${t}`),Object.keys(r).length>0)console.log(`
|
|
40
|
-
\uD83D\uDCCB Applied overrides:`),Object.entries(r).forEach(([o,a])=>{let c=n.find((l)=>l.packageName===o);console.log(` ${o}: ${a} (${c?.severity||"unknown"} severity)`)});this.logInstallInstructions(i)}applyAutoFix(e,t){try{let r=t||
|
|
41
|
-
`),this.logSuccess(r,n,o,e,s)}catch(r){throw this.log.error("Failed to apply auto-fix","applyAutoFix",{error:r}),Error(`Auto-fix failed: ${r}`)}}detectPackageManager(){try{let e=process.cwd();if(
|
|
40
|
+
\uD83D\uDCCB Applied overrides:`),Object.entries(r).forEach(([o,a])=>{let c=n.find((l)=>l.packageName===o);console.log(` ${o}: ${a} (${c?.severity||"unknown"} severity)`)});this.logInstallInstructions(i)}applyAutoFix(e,t){try{let r=t||ee(process.cwd(),"package.json");if(!Z(r))throw Error(`package.json not found at ${r}`);let n=this.createBackup(r),i=JSON.parse(Pr(r,"utf-8")),s=this.detectPackageManager(),o=this.generatePackageOverrides(e),a=e.map((v)=>{let x={packageName:v.packageName,reason:v.reason};if(v.cve)x.cve=v.cve;if(v.severity)x.severity=v.severity;if(v.description)x.description=v.description;if(v.url)x.url=v.url;return x}),c=this.providers[0]?.constructor.name.toLowerCase()||"",l="osv";if(c.includes("github"))l="github";else if(c.includes("snyk"))l="snyk";else if(c.includes("socket"))l="socket";let u=i.pastoralist?.appendix||{},d=i.dependencies||{},g=i.devDependencies||{},p=i.peerDependencies||{},h=i.name||"",m=_({overrides:o,appendix:u,dependencies:d,devDependencies:g,peerDependencies:p,packageName:h,securityOverrideDetails:a,securityProvider:l}),b=this.applyOverridesToPackageJson(i,s,o);b.pastoralist=b.pastoralist||{},b.pastoralist.appendix=m,Zs(r,JSON.stringify(b,null,2)+`
|
|
41
|
+
`),this.logSuccess(r,n,o,e,s)}catch(r){throw this.log.error("Failed to apply auto-fix","applyAutoFix",{error:r}),Error(`Auto-fix failed: ${r}`)}}detectPackageManager(){try{let e=process.cwd();if(Z(ee(e,"bun.lockb")))return"bun";if(Z(ee(e,"yarn.lock")))return"yarn";if(Z(ee(e,"pnpm-lock.yaml")))return"pnpm";return"npm"}catch{return"npm"}}getOverrideField(e){switch(e){case"yarn":return"resolutions";case"pnpm":case"npm":case"bun":default:return"overrides"}}rollbackAutoFix(e){try{if(!Z(e))throw Error(`Backup file not found at ${e}`);let t=e.replace(/\.backup-\d+$/,"");Ar(e,t),console.log(`✅ Rolled back to ${e}`)}catch(t){throw this.log.error("Failed to rollback","rollbackAutoFix",{error:t}),Error(`Rollback failed: ${t}`)}}}var nt=f(()=>{Oe();P();be();ge();ue();Oe();Or();Oe()});function Cr(e){if(!ao(e))return;return e}var kr,F=(e)=>{return typeof e==="object"&&e!==null&&!Array.isArray(e)},N=(e)=>{return typeof e==="string"},M=(e)=>{return typeof e==="boolean"},xr=(e)=>{return Array.isArray(e)},Ae=(e)=>{return xr(e)&&e.every(N)},st=(e)=>{return N(e)&&["osv","github","snyk","npm","socket"].includes(e)},eo=(e)=>{if(st(e))return!0;return xr(e)&&e.every(st)},to=(e)=>{return N(e)&&["low","medium","high","critical"].includes(e)},ro=(e)=>{return F(e)},no=(e)=>{if(!F(e))return!1;if(!(("addedDate"in e)&&N(e.addedDate)))return!1;if("reason"in e&&e.reason!==void 0&&!N(e.reason))return!1;if("securityChecked"in e&&e.securityChecked!==void 0&&!M(e.securityChecked))return!1;if("securityCheckDate"in e&&e.securityCheckDate!==void 0&&!N(e.securityCheckDate))return!1;if("securityProvider"in e&&e.securityProvider!==void 0&&!st(e.securityProvider))return!1;return!0},io=(e)=>{if(!F(e))return!1;if("rootDeps"in e&&e.rootDeps!==void 0&&!Ae(e.rootDeps))return!1;if("dependents"in e&&e.dependents!==void 0&&!ro(e.dependents))return!1;if("patches"in e&&e.patches!==void 0&&!Ae(e.patches))return!1;if("ledger"in e&&e.ledger!==void 0&&!no(e.ledger))return!1;return!0},it=(e)=>{if(!F(e))return!1;return Object.values(e).every(io)},so=(e)=>{if(!F(e))return!1;if("enabled"in e&&e.enabled!==void 0&&!M(e.enabled))return!1;if("provider"in e&&e.provider!==void 0&&!eo(e.provider))return!1;if("autoFix"in e&&e.autoFix!==void 0&&!M(e.autoFix))return!1;if("interactive"in e&&e.interactive!==void 0&&!M(e.interactive))return!1;if("securityProviderToken"in e&&e.securityProviderToken!==void 0&&!N(e.securityProviderToken))return!1;if("severityThreshold"in e&&e.severityThreshold!==void 0&&!to(e.severityThreshold))return!1;if("excludePackages"in e&&e.excludePackages!==void 0&&!Ae(e.excludePackages))return!1;if("hasWorkspaceSecurityChecks"in e&&e.hasWorkspaceSecurityChecks!==void 0&&!M(e.hasWorkspaceSecurityChecks))return!1;return!0},oo=(e)=>{if(e==="workspace"||e==="workspaces")return!0;return Ae(e)},ao=(e)=>{if(!F(e))return!1;if("appendix"in e&&e.appendix!==void 0&&!it(e.appendix))return!1;if("depPaths"in e&&e.depPaths!==void 0&&!oo(e.depPaths))return!1;if("checkSecurity"in e&&e.checkSecurity!==void 0&&!M(e.checkSecurity))return!1;if("overridePaths"in e&&e.overridePaths!==void 0){if(!F(e.overridePaths))return!1;if(!Object.values(e.overridePaths).every(it))return!1}if("resolutionPaths"in e&&e.resolutionPaths!==void 0){if(!F(e.resolutionPaths))return!1;if(!Object.values(e.resolutionPaths).every(it))return!1}if("security"in e&&e.security!==void 0&&!so(e.security))return!1;return!0};var ke=f(()=>{kr=[".pastoralistrc",".pastoralistrc.json","pastoralist.json","pastoralist.config.js","pastoralist.config.ts"]});import{existsSync as co,readFileSync as uo}from"fs";import{resolve as wr}from"path";var ot,lo=()=>{ot.clear()},po=(e)=>e.endsWith(".json")||e===".pastoralistrc",ho=(e)=>{let t=uo(e,"utf8");return JSON.parse(t)},go=async(e)=>{let r=await import(wr(e));return r.default||r},fo=async(e,t)=>{if(po(e))return ho(t);return await go(t)},yo=(e,t)=>{if(!t)return e;return Cr(e)||null},mo=async(e,t,r)=>{let n=wr(t,e);if(!co(n))return null;try{let i=await fo(e,n);if(!i)return null;return yo(i,r)}catch(i){let s=i instanceof Error?i.message:String(i);return console.error(`Failed to load config from ${e}: ${s}`),null}},xe=async(e=process.cwd(),t=!0)=>{for(let r of kr){let n=await mo(r,e,t);if(n!==null)return n}return},bo=(e,t)=>{if(!e&&!t)return;if(!e)return t;if(!t)return e;let r=(n,i)=>{if(!e[n])return i;let s=e[n],o=Object.assign({},s.dependents,i.dependents),a=i.patches?(s.patches||[]).concat(i.patches):s.patches;return{dependents:o,patches:a,ledger:i.ledger||s.ledger}};return Object.entries(t).reduce((n,[i,s])=>({...n,[i]:r(i,s)}),{...e})},Rr=(e,t)=>{if(!e)return t;if(!t)return e;let r=bo(e.appendix,t.appendix),n=Object.assign({},e.overridePaths,t.overridePaths),i=Object.assign({},e.resolutionPaths,t.resolutionPaths),s=Object.assign({},e.security,t.security);return Object.assign({},e,t,{appendix:r,overridePaths:n,resolutionPaths:i,security:s})},vo=async(e=process.cwd(),t,r=!0)=>{let n=`${e}:${r}:${JSON.stringify(t)}`,i=ot.get(n);if(i)return i;let s=await xe(e,r),o=Rr(s,t);if(o)ot.set(n,o);return o};var at=f(()=>{ke();ke();ke();ot=new Map});var ct,Tr=`
|
|
42
42
|
Pastoralist - A utility CLI to manage your dependency overrides
|
|
43
43
|
|
|
44
44
|
Usage: pastoralist [command] [options]
|
|
@@ -49,6 +49,7 @@ Commands:
|
|
|
49
49
|
Options:
|
|
50
50
|
--debug Enable debug mode
|
|
51
51
|
--dry-run Preview changes without writing to package.json
|
|
52
|
+
--outputFormat <format> Output format: text (default) or json
|
|
52
53
|
-p, --path <path> Specifies a path to a package.json (default: "package.json")
|
|
53
54
|
-d, --depPaths [paths...] Specifies glob paths to package.jsons
|
|
54
55
|
--ignore [paths...] Specifies glob paths to ignore
|
|
@@ -63,30 +64,31 @@ Options:
|
|
|
63
64
|
--interactive Run security checks in interactive mode
|
|
64
65
|
--hasWorkspaceSecurityChecks Include workspace packages in security scan
|
|
65
66
|
--promptForReasons Prompt for reasons when adding manual overrides
|
|
66
|
-
|
|
67
|
+
--strict Fail on any security check errors (network failures, API errors)
|
|
68
|
+
`,Vr=2;var $r=f(()=>{ct=[{flags:["--debug"],hasValue:!1},{flags:["--dry-run"],hasValue:!1},{flags:["--outputFormat"],hasValue:!0,defaultValue:"text"},{flags:["-p","--path"],hasValue:!0,defaultValue:"package.json"},{flags:["-d","--depPaths"],hasValue:!0,isArray:!0},{flags:["--ignore"],hasValue:!0,isArray:!0},{flags:["-r","--root"],hasValue:!0},{flags:["-t","--isTestingCLI"],hasValue:!1},{flags:["--isTesting"],hasValue:!1},{flags:["--isIRLFix"],hasValue:!1},{flags:["--isIRLCatch"],hasValue:!1},{flags:["--init"],hasValue:!1},{flags:["--checkSecurity"],hasValue:!1},{flags:["--forceSecurityRefactor"],hasValue:!1},{flags:["--securityProvider"],hasValue:!0,isArray:!0},{flags:["--securityProviderToken"],hasValue:!0},{flags:["--interactive"],hasValue:!1},{flags:["--hasWorkspaceSecurityChecks"],hasValue:!1},{flags:["--promptForReasons"],hasValue:!1},{flags:["--strict"],hasValue:!1}]});var So=(e)=>ct.find((t)=>t.flags.includes(e)),Ir=(e)=>{return(e.flags.find((r)=>r.startsWith("--"))||e.flags[0]).replace(/^--?/,"").replace(/-([a-z])/g,(r,n)=>n.toUpperCase())},Oo=(e)=>{let t=e.indexOf("=");return t>-1?{flag:e.slice(0,t),value:e.slice(t+1)}:{flag:e}},ut=(e)=>e.startsWith("-"),Po=(e,t)=>{let r=[],n=t+1;while(n<e.length&&!ut(e[n]))r.push(e[n]),n++;let i=r.length>0,s=n-t-1;return{value:i?r:void 0,consumed:s}},Ao=(e,t)=>{let r=e[t+1];return r&&!ut(r)?{value:r,consumed:1}:{value:!0,consumed:0}},ko=(e,t,r)=>r.isArray?Po(e,t):Ao(e,t),xo=(e)=>ct.reduce((t,r)=>{let n=Ir(r);return t[n]===void 0&&r.defaultValue!==void 0?Object.assign({},t,{[n]:r.defaultValue}):t},e),Co=(e,t,r)=>{let n=e[t];if(!ut(n))return{nextIndex:t+1,options:r.options,command:n};let{flag:s,value:o}=Oo(n),a=So(s);if(!a)return{nextIndex:t+1,options:r.options,command:r.command};let l=Ir(a);if(o!==void 0){let m=Object.assign({},r.options,{[l]:o});return{nextIndex:t+1,options:m,command:r.command}}if(!a.hasValue){let m=Object.assign({},r.options,{[l]:!0});return{nextIndex:t+1,options:m,command:r.command}}let{value:g,consumed:p}=ko(e,t,a),h=Object.assign({},r.options,{[l]:g});return{nextIndex:t+p+1,options:h,command:r.command}},Er=(e)=>{let t=e.slice(Vr),r=0,n={options:{},command:void 0};while(r<t.length){let s=Co(t,r,n);r=s.nextIndex,n={options:s.options,command:s.command}}let i=xo(n.options);return{command:n.command,options:i}},Fr=()=>{console.log(Tr)};var Nr=f(()=>{$r()});import*as Lr from"readline";class jr{rl;constructor(){this.rl=Lr.createInterface({input:process.stdin,output:process.stdout})}close(){this.rl.close()}ensureCookedMode(){if(process.stdin.isTTY)process.stdin.setRawMode(!1)}async input(e,t){return new Promise((r)=>{let n=t?`${e} (${t}): `:`${e}: `;this.ensureCookedMode(),this.rl.question(n,(i)=>{r(i.trim()||t||"")})})}async confirm(e,t=!0){return new Promise((r)=>{let n=t?"Y/n":"y/N";this.ensureCookedMode(),this.rl.question(`${e} (${n}): `,(i)=>{let s=i.trim().toLowerCase();if(s==="")r(t);else r(s==="y"||s==="yes")})})}async list(e,t){return console.log(`
|
|
67
69
|
${e}`),t.forEach((r,n)=>{console.log(` ${n+1}. ${r.name}`)}),new Promise((r)=>{let n=()=>{this.ensureCookedMode(),this.rl.question(`
|
|
68
|
-
Enter your choice (number): `,(i)=>{let s=parseInt(i.trim(),10);if(isNaN(s)||s<1||s>t.length)console.log("⚠️ Invalid choice. Please enter a number between 1 and "+t.length),n();else r(t[s-1].value)})};n()})}async prompt(e){let{type:t="input",message:r}=e;switch(t){case"confirm":return this.confirm(r,e.default??!0);case"list":return this.list(r,e.choices);case"input":default:return this.input(r,e.default??"")}}async promptMany(e){return e.reduce(async(t,r,n)=>{let i=await t,s=`answer${n}`,o=r.type==="confirm",a=r.type==="list";if(o)i[s]=await this.prompt(r);else if(a)i[s]=await this.prompt(r);else i[s]=await this.prompt(r);return i},Promise.resolve({}))}}async function
|
|
70
|
+
Enter your choice (number): `,(i)=>{let s=parseInt(i.trim(),10);if(isNaN(s)||s<1||s>t.length)console.log("⚠️ Invalid choice. Please enter a number between 1 and "+t.length),n();else r(t[s-1].value)})};n()})}async prompt(e){let{type:t="input",message:r}=e;switch(t){case"confirm":return this.confirm(r,e.default??!0);case"list":return this.list(r,e.choices);case"input":default:return this.input(r,e.default??"")}}async promptMany(e){return e.reduce(async(t,r,n)=>{let i=await t,s=`answer${n}`,o=r.type==="confirm",a=r.type==="list";if(o)i[s]=await this.prompt(r);else if(a)i[s]=await this.prompt(r);else i[s]=await this.prompt(r);return i},Promise.resolve({}))}}async function Ur(e){let t=new jr;try{return await e(t)}finally{t.close()}}var Dr=()=>{};var _r,Mr,Wr,lt,dt,Gr="packages/*/package.json",O,te,S;var Hr=f(()=>{_r=[{name:"In package.json (recommended for simple setups)",value:"package.json"},{name:"In a separate config file (recommended for complex setups)",value:"external"}],Mr=[{name:".pastoralistrc.json (JSON format)",value:".pastoralistrc.json"},{name:"pastoralist.config.js (JavaScript module)",value:"pastoralist.config.js"},{name:"pastoralist.config.ts (TypeScript module)",value:"pastoralist.config.ts"}],Wr=[{name:'Use "workspace" keyword (auto-detect from package.json)',value:"workspace"},{name:"Specify custom paths",value:"custom"}],lt=[{name:"OSV (Open Source Vulnerabilities - free, recommended)",value:"osv"},{name:"GitHub Advisory Database",value:"github"},{name:"npm audit",value:"npm"},{name:"Snyk [EXPERIMENTAL] (requires token)",value:"snyk"},{name:"Socket.dev [EXPERIMENTAL] (requires token)",value:"socket"}],dt=[{name:"Low (all vulnerabilities)",value:"low"},{name:"Medium (medium and above)",value:"medium"},{name:"High (high and critical only)",value:"high"},{name:"Critical (critical only)",value:"critical"}],O={welcome:"This wizard will help you set up your Pastoralist configuration.",skipInfo:"You can skip any step by selecting the skip option.",existingConfigWarning:"⚠️ Existing Pastoralist configuration detected. Do you want to overwrite it?",existingFileWarning:(e)=>`⚠️ ${e} already exists. Overwrite?`,configNotSaved:"✅ Configuration not saved. File preserved.",configSaved:(e)=>`✅ Configuration saved to ${e}`,initCancelled:"✅ Initialization cancelled. Your existing configuration is preserved.",initComplete:"initialization complete!",packageJsonNotFound:"❌ Error: package.json not found",noTokenProvided:()=>"⚠️ No token provided. You can add it later to the config or use --securityProviderToken flag.",tokenCreationInfo:(e,t)=>`\uD83D\uDCA1 To create a ${e} token, visit: ${t}`,tokenRequiredWarning:(e)=>`⚠️ ${e} requires a token to function. Security scanning will not work without it.`,workspacesDetected:(e)=>`Detected workspaces in package.json: ${e.join(", ")}`,noWorkspacesDetected:"No workspaces detected in package.json.",savingConfig:"\uD83D\uDCBE Saving configuration...",nextSteps:"\uD83D\uDCDA Next Steps:"},te={configLocation:"\uD83D\uDCCD Step 1: Configuration Location",workspace:"\uD83D\uDCE6 Step 2: Workspace Configuration",security:"\uD83D\uDD12 Step 3: Security Configuration"},S={configLocation:"Where would you like to store your Pastoralist configuration?",configFormat:"Choose a config file format:",setupWorkspaces:"Do you want to configure workspace dependencies?",workspaceType:"How would you like to configure workspace dependencies?",customWorkspacePaths:"Enter workspace paths (comma-separated glob patterns)",setupSecurity:"Do you want to enable security vulnerability scanning?",securityProvider:"Choose a security provider:",hasToken:(e)=>`Do you have a ${e} API token?`,enterToken:(e)=>`Enter your ${e} API token (will be stored in config)`,securityInteractive:"Enable interactive mode for security fixes? (allows you to review/approve each fix)",securityAutoFix:"Enable auto-fix mode? (automatically applies security overrides without prompting)",severityThreshold:"What severity level should trigger alerts?",hasWorkspaceSecurityChecks:"Scan workspace packages for vulnerabilities?"}});function Kr(e){return e.split(",").map((t)=>t.trim()).filter((t)=>t.length>0)}function Br(e){let t={};if(e.setupWorkspaces){if(e.workspaceType==="workspace")t.depPaths="workspace";if(e.workspaceType==="custom"&&e.customWorkspacePaths?.length)t.depPaths=e.customWorkspacePaths}if(e.setupSecurity){if(t.checkSecurity=!0,t.security={enabled:!0,provider:e.securityProvider,interactive:e.securityInteractive,autoFix:e.securityAutoFix,severityThreshold:e.severityThreshold,hasWorkspaceSecurityChecks:e.hasWorkspaceSecurityChecks},Boolean(e.securityProviderToken))t.security.securityProviderToken=e.securityProviderToken}return t}function qr(e,t){if(t.endsWith(".json"))return JSON.stringify(e,null,2)+`
|
|
69
71
|
`;if(t.endsWith(".js"))return`module.exports = ${JSON.stringify(e,null,2)};
|
|
70
72
|
`;return`import type { PastoralistConfig } from 'pastoralist';
|
|
71
73
|
|
|
72
74
|
const config: PastoralistConfig = ${JSON.stringify(e,null,2)};
|
|
73
75
|
|
|
74
76
|
export default config;
|
|
75
|
-
`}import{writeFileSync as
|
|
76
|
-
${
|
|
77
|
-
${O.workspacesDetected(r)}`,"promptForWorkspaceType"),await e.list(S.workspaceType,
|
|
78
|
-
${
|
|
79
|
-
${O.noWorkspacesDetected}`,"collectWorkspaceAnswers");if(t.workspaceType=await
|
|
77
|
+
`}import{writeFileSync as zr,existsSync as wo}from"fs";import{resolve as Ro}from"path";async function Jr(e,t,r){if(r.info(`
|
|
78
|
+
${te.configLocation}`,"collectConfigLocationAnswers"),t.configLocation=await e.list(S.configLocation,_r),t.configLocation==="external")t.configFormat=await e.list(S.configFormat,Mr)}async function To(e){let t=await e.input(S.customWorkspacePaths,Gr);return Kr(t)}async function Vo(e,t,r,n){if(!t)return"custom";return n.info(`
|
|
79
|
+
${O.workspacesDetected(r)}`,"promptForWorkspaceType"),await e.list(S.workspaceType,Wr)}async function Yr(e,t,r,n){if(n.info(`
|
|
80
|
+
${te.workspace}`,"collectWorkspaceAnswers"),t.setupWorkspaces=await e.confirm(S.setupWorkspaces,!0),!t.setupWorkspaces)return;let i=Boolean(r?.workspaces&&r.workspaces.length>0);if(!i)n.info(`
|
|
81
|
+
${O.noWorkspacesDetected}`,"collectWorkspaceAnswers");if(t.workspaceType=await Vo(e,i,r?.workspaces||[],n),t.workspaceType==="custom")t.customWorkspacePaths=await To(e)}async function Xr(e,t,r){let n=$o(t);if(!n.required&&!n.optional)return;if(n.createUrl)r.info(`
|
|
80
82
|
${O.tokenCreationInfo(t,n.createUrl)}`,"promptForSecurityToken");if(!await e.confirm(S.hasToken(t),!1)){if(n.required)r.info(`
|
|
81
83
|
${O.tokenRequiredWarning(t)}`,"promptForSecurityToken");return}let s=await e.input(S.enterToken(t),"");if(!s){r.info(`
|
|
82
|
-
${O.noTokenProvided()}`,"promptForSecurityToken");return}return s}function
|
|
83
|
-
${
|
|
84
|
-
`);n.info(O.configSaved(t),"saveToPackageJson")}async function
|
|
85
|
-
${O.configNotSaved}`,"saveToExternalFile");return}}let c=
|
|
84
|
+
${O.noTokenProvided()}`,"promptForSecurityToken");return}return s}function $o(e){switch(e){case"github":return{required:!1,optional:!0,createUrl:"https://github.com/settings/tokens/new?description=Pastoralist%20Security&scopes=repo",scopes:["repo"]};case"snyk":return{required:!0,optional:!1,createUrl:"https://app.snyk.io/account"};case"socket":return{required:!0,optional:!1,createUrl:"https://socket.dev/dashboard/settings"};default:return{required:!1,optional:!1}}}async function Io(e,t,r){if(r.info(`
|
|
85
|
+
${te.security}`,"collectSecurityAnswers"),t.setupSecurity=await e.confirm(S.setupSecurity,!0),!t.setupSecurity)return;if(t.securityProvider=await e.list(S.securityProvider,lt),t.securityProviderToken=await Xr(e,t.securityProvider,r),t.securityInteractive=await e.confirm(S.securityInteractive,!0),!t.securityInteractive)t.securityAutoFix=await e.confirm(S.securityAutoFix,!1);if(t.severityThreshold=await e.list(S.severityThreshold,dt),t.setupWorkspaces)t.hasWorkspaceSecurityChecks=await e.confirm(S.hasWorkspaceSecurityChecks,!0)}async function Eo(e,t,r,n,i=!1){if(!r){n.info(O.packageJsonNotFound,"saveToPackageJson");return}if(r.pastoralist=e,!i)zr(t,JSON.stringify(r,null,2)+`
|
|
86
|
+
`);n.info(O.configSaved(t),"saveToPackageJson")}async function Fo(e,t,r,n,i,s=!1){let o=Ro(r,t);if(wo(o)){if(!await n.confirm(O.existingFileWarning(t),!1)){i.info(`
|
|
87
|
+
${O.configNotSaved}`,"saveToExternalFile");return}}let c=qr(e,t);if(!s)zr(o,c);i.info(O.configSaved(o),"saveToExternalFile")}function No(e,t){if(t.info(`
|
|
86
88
|
${O.nextSteps}
|
|
87
89
|
`,"displayNextSteps"),t.info(` 1. Run ${C("pastoralist")} to check and update your dependencies`,"displayNextSteps"),e)t.info(` 2. Run ${C("pastoralist --checkSecurity")} to scan for security vulnerabilities`,"displayNextSteps");t.info(" 3. Check the documentation for advanced configuration options","displayNextSteps"),t.info(`
|
|
88
90
|
\uD83D\uDC69\uD83C\uDFFD\uD83C\uDF3E ${C("Pastoralist")} ${O.initComplete}
|
|
89
|
-
`,"displayNextSteps")}async function
|
|
91
|
+
`,"displayNextSteps")}async function Lo(e,t,r){let n=await xe(t,!1),i=await R(r);if(!(n||i?.pastoralist))return!0;return await e.confirm(O.existingConfigWarning,!1)}async function pt(e={}){let t=y({file:"init/index.ts",isLogging:!0}),r=!!(e.checkSecurity||e.securityProvider),n=!!e.hasWorkspaceSecurityChecks,i=r||n;if(r)t.info(`
|
|
90
92
|
\uD83D\uDC69\uD83C\uDFFD\uD83C\uDF3E ${C("Pastoralist")} security configuration wizard
|
|
91
93
|
`,"initCommand");else if(n)t.info(`
|
|
92
94
|
\uD83D\uDC69\uD83C\uDFFD\uD83C\uDF3E ${C("Pastoralist")} workspace configuration wizard
|
|
@@ -94,11 +96,11 @@ ${O.nextSteps}
|
|
|
94
96
|
\uD83D\uDC69\uD83C\uDFFD\uD83C\uDF3E ${C("Pastoralist")} initialization wizard
|
|
95
97
|
`,"initCommand"),t.info(`${O.welcome}
|
|
96
98
|
`,"initCommand"),t.info(`${O.skipInfo}
|
|
97
|
-
`,"initCommand");let s=e.path||"package.json",o=e.root||process.cwd();await
|
|
98
|
-
${O.initCancelled}`,"initCommand");return}let l=await
|
|
99
|
+
`,"initCommand");let s=e.path||"package.json",o=e.root||process.cwd();await Ur(async(a)=>{if(!await Lo(a,o,s)){t.info(`
|
|
100
|
+
${O.initCancelled}`,"initCommand");return}let l=await R(s),u={configLocation:"package.json",setupWorkspaces:!1,setupSecurity:!1};if(r){if(u.setupSecurity=!0,e.securityProvider)u.securityProvider=e.securityProvider}if(n)u.setupWorkspaces=!0,u.hasWorkspaceSecurityChecks=!0;if(!i)await Jr(a,u,t),await Yr(a,u,l,t),await Io(a,u,t);else{if(await Jr(a,u,t),n)await Yr(a,u,l,t);if(r)await jo(a,u,t)}let d=Br(u);t.info(`
|
|
99
101
|
${O.savingConfig}
|
|
100
|
-
`,"initCommand");let
|
|
101
|
-
${
|
|
102
|
+
`,"initCommand");let g=u.configLocation==="package.json",p=u.configLocation==="external"&&u.configFormat;if(g)await Eo(d,s,l,t,e.isTesting);if(p)await Fo(d,u.configFormat,o,a,t,e.isTesting);No(u.setupSecurity,t)})}async function jo(e,t,r){if(r.info(`
|
|
103
|
+
${te.security}`,"collectSecurityAnswersWithContext"),!t.securityProvider)t.securityProvider=await e.list(S.securityProvider,lt);if(t.securityProviderToken=await Xr(e,t.securityProvider,r),t.securityInteractive=await e.confirm(S.securityInteractive,!0),!t.securityInteractive)t.securityAutoFix=await e.confirm(S.securityAutoFix,!1);if(t.severityThreshold=await e.list(S.severityThreshold,dt),t.setupWorkspaces&&!t.hasWorkspaceSecurityChecks)t.hasWorkspaceSecurityChecks=await e.confirm(S.hasWorkspaceSecurityChecks,!0)}var Qr=f(()=>{P();Dr();at();I();P();Hr()});var pn={};vt(pn,{runSecurityCheck:()=>nn,run:()=>Do,outputResult:()=>re,handleTestMode:()=>Zr,handleSecurityResults:()=>sn,handleInitMode:()=>en,formatUpdateReport:()=>on,determineSecurityScanPaths:()=>an,createErrorResult:()=>cn,createEmptyResult:()=>ht,buildUpdateResult:()=>ln,buildSecurityResult:()=>un,buildSecurityOverrideDetail:()=>rn,buildMergedOptions:()=>tn,action:()=>dn});function an(e,t,r=Uo){let n=e?.pastoralist?.depPaths,i=Array.isArray(n),s=e?.workspaces||[],o=s.length>0,a=n==="workspace",c=t.hasWorkspaceSecurityChecks||!1,l=t.checkSecurity||e?.pastoralist?.checkSecurity||!1,u=i&&l,p=a&&o&&l||c&&o;if(u)return r.debug(`Using depPaths configuration for security checks: ${n.join(", ")}`,"determineSecurityScanPaths"),n;if(p)return r.debug(`Using workspace configuration for security checks: ${s.join(", ")}`,"determineSecurityScanPaths"),s.map((h)=>`${h}/package.json`);return[]}async function dn(e={},t={createLogger:y,handleTestMode:Zr,handleInitMode:en,resolveJSON:R,buildMergedOptions:tn,runSecurityCheck:nn,handleSecurityResults:sn,createSpinner:se,green:C,update:Qe,processExit:(r)=>process.exit(r)}){let r=k||e.debug,n=e.outputFormat==="json",i=t.createLogger({file:"program.ts",isLogging:r}),{isTestingCLI:s=!1,init:o=!1,...a}=e,c=ht();if(t.handleTestMode(s,i,e))return re(c,n),c;if(await t.handleInitMode(o,e,a))return re(c,n),c;try{let l=e.path||"package.json",u=e.root&&!l.startsWith("/")?`${e.root}/${l}`:l,d=await t.resolveJSON(u),g=d?.pastoralist?.security||{},p=Array.isArray(g.provider)?g.provider[0]:g.provider,h=t.buildMergedOptions(e,a,g,p);if(h.config=d,h.path=u,e.root)h.root=e.root;let m={hasSecurityIssues:!1,securityAlertCount:0,securityAlerts:[]};if(h.checkSecurity){let{spinner:gt,securityChecker:gn,alerts:ft,securityOverrides:fn,updates:yn}=await t.runSecurityCheck(d,h,Boolean(r),i);if(m=un(ft),!n)t.handleSecurityResults(ft,fn,gn,gt,h,yn);else gt.stop()}let b=n?{start:()=>({succeed:()=>{},stop:()=>{}}),succeed:()=>{},stop:()=>{}}:t.createSpinner(`\uD83D\uDC69\uD83C\uDFFD\uD83C\uDF3E ${t.green("pastoralist")} checking herd...`).start();if(!n)b.start?.();let v=await t.update(h),x=ln(v,d,e.dryRun||!1);if(!n)b.succeed(`\uD83D\uDC69\uD83C\uDFFD\uD83C\uDF3E ${t.green("pastoralist")} the herd is safe!`);let W={...c,...m,...x};return re(W,n),W}catch(l){let u=cn(l);if(n)re(u,n);else i.error("action:fn","action",{error:l});return t.processExit(1),u}}var Uo,Zr=(e,t,r)=>{if(e)return t.debug("action:options:","action",{options:r}),!0;return!1},en=async(e,t,r,n={initCommand:pt})=>{if(e)return await n.initCommand({path:t.path,root:t.root,checkSecurity:r.checkSecurity,securityProvider:r.securityProvider,hasWorkspaceSecurityChecks:r.hasWorkspaceSecurityChecks}),!0;return!1},tn=(e,t,r,n)=>{return{...t,checkSecurity:e.checkSecurity??r.enabled,forceSecurityRefactor:e.forceSecurityRefactor??r.autoFix,securityProvider:e.securityProvider??n??"osv",securityProviderToken:e.securityProviderToken??r.securityProviderToken,interactive:e.interactive??r.interactive,hasWorkspaceSecurityChecks:e.hasWorkspaceSecurityChecks??r.hasWorkspaceSecurityChecks}},rn=(e)=>{let t=Boolean(e.cve),r=Boolean(e.severity),n=Boolean(e.description),i=Boolean(e.url);return{packageName:e.packageName,reason:e.reason,...t&&{cve:e.cve},...r&&{severity:e.severity},...n&&{description:e.description},...i&&{url:e.url}}},nn=async(e,t,r,n,i={createSpinner:se,SecurityChecker:Pe,determineSecurityScanPaths:an,green:C})=>{let s=i.createSpinner(`\uD83D\uDD12 ${i.green("pastoralist")} checking for security vulnerabilities...`).start();try{let o=new i.SecurityChecker({provider:t.securityProvider,forceRefactor:t.forceSecurityRefactor,interactive:t.interactive,token:t.securityProviderToken,debug:r,isIRLFix:t.isIRLFix,isIRLCatch:t.isIRLCatch}),a=i.determineSecurityScanPaths(e,t,n),{alerts:c,overrides:l,updates:u}=await o.checkSecurity(e,{...t,depPaths:a,root:t.root||"./"});return{spinner:s,securityChecker:o,alerts:c,securityOverrides:l,updates:u}}catch(o){throw s.fail(`\uD83D\uDD12 ${i.green("pastoralist")} security check failed: ${o instanceof Error?o.message:String(o)}`),o}},sn=(e,t,r,n,i,s=[])=>{let o=e.length>0,a=s.length>0,c=i.forceSecurityRefactor||i.interactive,l=o&&c,u=a&&c;if(o){let p=r.formatSecurityReport(e,t);n.info(p)}if(a){let p=on(s);n.info(p)}let d=[...t];if(u){let p=s.map((h)=>({packageName:h.packageName,fromVersion:h.currentOverride,toVersion:h.newerVersion,reason:h.reason,severity:"medium"}));d.push(...p)}if(l||u){let p=r.generatePackageOverrides(d);i.securityOverrides=p;let h=d.filter((b)=>{let v=p[b.packageName];return typeof v==="string"&&v===b.toVersion});if(i.securityOverrideDetails=h.map(rn),(l||u)&&h.length>0)r.applyAutoFix(h,i.path)}if(!o&&!a)n.succeed(`\uD83D\uDD12 ${C("pastoralist")} no security vulnerabilities found!`)},on=(e)=>{let t=`
|
|
102
104
|
Security Override Updates
|
|
103
105
|
`+"=".repeat(50)+`
|
|
104
106
|
|
|
@@ -109,4 +111,4 @@ Security Override Updates
|
|
|
109
111
|
Newer patch: ${i.newerVersion}
|
|
110
112
|
${i.reason}
|
|
111
113
|
|
|
112
|
-
`).join("");return t+r+n},
|
|
114
|
+
`).join("");return t+r+n},ht=()=>({success:!0,hasSecurityIssues:!1,hasUnusedOverrides:!1,updated:!1,securityAlertCount:0,unusedOverrideCount:0,overrideCount:0,errors:[],securityAlerts:[],unusedOverrides:[],appliedOverrides:{}}),cn=(e)=>{let t=e instanceof Error?e.message:String(e);return{...ht(),success:!1,errors:[t]}},un=(e)=>({hasSecurityIssues:e.length>0,securityAlertCount:e.length,securityAlerts:e.map((t)=>({packageName:t.packageName,severity:t.severity||"unknown",cve:t.cve,description:t.description}))}),ln=(e,t,r)=>{let n=e.finalOverrides||{},i=e.finalAppendix||{},s=Object.keys(n),o=Object.fromEntries(s.filter((u)=>typeof n[u]==="string").map((u)=>[u,n[u]])),a=t?.pastoralist?.appendix||{},c=t?.overrides||t?.resolutions||t?.pnpm?.overrides||{},l=JSON.stringify(i)!==JSON.stringify(a)||JSON.stringify(n)!==JSON.stringify(c);return{overrideCount:s.length,appliedOverrides:o,updated:l&&!r}},re=(e,t)=>{if(t)console.log(JSON.stringify(e))},Do=async(e=process.argv)=>{let t=Er(e),r=t.options;if(r.help||e.includes("-h")||e.includes("--help")){Fr();return}if(t.command==="init"){await pt(r);return}await dn(r)};var hn=f(()=>{Nr();P();Ze();P();I();T();nt();Qr();Uo=y({file:"program.ts",isLogging:!1})});Ze();I();_e();ge();z();Ke();nt();at();P();import{realpathSync as _o}from"fs";import{fileURLToPath as Mo}from"url";var fu=(e)=>{if(!e)return[];let t=Object.keys(e);if(t.length===0)return[];return t.filter((r)=>{let n=e[r]?.dependents;return!n||Object.keys(n).length===0}).map((r)=>r.split("@")[0])},Wo=Mo(import.meta.url),Go=process.argv[1]?_o(process.argv[1]):"",Ho=Wo===Go||process.argv[1]?.endsWith("/pastoralist")||process.argv[1]?.endsWith("\\pastoralist");if(Ho){let{run:e}=await Promise.resolve().then(() => (hn(),pn));await e(process.argv)}export{Ne as updatePackageJSON,Qt as updateOverrides,_ as updateAppendix,Qe as update,pe as resolveOverrides,R as resolveJSON,ar as processPackageJSON,De as mergeOverridePaths,Rr as mergeConfigs,y as logger,B as logMethod,xe as loadExternalConfig,vo as loadConfig,V as jsonCache,E as getOverridesByType,Kt as getOverrideFieldForPackageManager,Ht as getExistingOverrideField,Mn as getCacheStats,Wn as forceClearCache,Ge as findUnusedPatches,Xt as findUnusedOverrides,fu as findRemovableAppendixItems,je as findPackageJsonFiles,We as detectPatches,Gt as detectPackageManager,Be as defineOverride,Xe as constructAppendix,Le as clearDependencyTreeCache,lo as clearConfigCache,Pi as cleanupUnusedOverrides,Ue as checkMonorepoOverrides,He as attachPatchesToAppendix,Bt as applyOverridesToConfig,Pe as SecurityChecker};
|
package/dist/types.d.ts
CHANGED
|
@@ -48,6 +48,7 @@ export interface PastoralistConfig {
|
|
|
48
48
|
severityThreshold?: "low" | "medium" | "high" | "critical";
|
|
49
49
|
excludePackages?: string[];
|
|
50
50
|
hasWorkspaceSecurityChecks?: boolean;
|
|
51
|
+
strict?: boolean;
|
|
51
52
|
};
|
|
52
53
|
}
|
|
53
54
|
export interface OverridesConfig {
|
|
@@ -86,6 +87,7 @@ export interface Options {
|
|
|
86
87
|
appendix?: Appendix;
|
|
87
88
|
debug?: boolean;
|
|
88
89
|
dryRun?: boolean;
|
|
90
|
+
outputFormat?: "text" | "json";
|
|
89
91
|
exec?: Exec;
|
|
90
92
|
help?: boolean;
|
|
91
93
|
isTesting?: boolean;
|
|
@@ -109,6 +111,7 @@ export interface Options {
|
|
|
109
111
|
promptForReasons?: boolean;
|
|
110
112
|
manualOverrideReasons?: Record<string, string>;
|
|
111
113
|
config?: PastoralistJSON;
|
|
114
|
+
strict?: boolean;
|
|
112
115
|
}
|
|
113
116
|
export interface OverridesType {
|
|
114
117
|
[key: string]: string | Record<string, string>;
|
|
@@ -117,6 +120,7 @@ export interface UpdatePackageJSONOptions {
|
|
|
117
120
|
appendix?: Appendix;
|
|
118
121
|
debug?: boolean;
|
|
119
122
|
dryRun?: boolean;
|
|
123
|
+
silent?: boolean;
|
|
120
124
|
path: string;
|
|
121
125
|
config: PastoralistJSON;
|
|
122
126
|
overrides?: OverridesType;
|
|
@@ -156,5 +160,23 @@ type ConsoleMethodFunc = (msg: string, caller?: string, ...args: unknown[]) => v
|
|
|
156
160
|
export type ConsoleObject = {
|
|
157
161
|
[K in ConsoleMethod]: ConsoleMethodFunc;
|
|
158
162
|
};
|
|
163
|
+
export interface PastoralistResult {
|
|
164
|
+
success: boolean;
|
|
165
|
+
hasSecurityIssues: boolean;
|
|
166
|
+
hasUnusedOverrides: boolean;
|
|
167
|
+
updated: boolean;
|
|
168
|
+
securityAlertCount: number;
|
|
169
|
+
unusedOverrideCount: number;
|
|
170
|
+
overrideCount: number;
|
|
171
|
+
errors: string[];
|
|
172
|
+
securityAlerts?: Array<{
|
|
173
|
+
packageName: string;
|
|
174
|
+
severity: string;
|
|
175
|
+
cve?: string;
|
|
176
|
+
description?: string;
|
|
177
|
+
}>;
|
|
178
|
+
unusedOverrides?: string[];
|
|
179
|
+
appliedOverrides?: Record<string, string>;
|
|
180
|
+
}
|
|
159
181
|
export * from "./core/security/types";
|
|
160
182
|
export * from "./core/update/types";
|
package/dist/utils/logger.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type ConsoleMethod = "debug" | "error" | "info";
|
|
1
|
+
export type ConsoleMethod = "debug" | "error" | "info" | "warn";
|
|
2
2
|
type ConsoleMethodFunc = (msg: string, caller?: string, ...args: unknown[]) => void;
|
|
3
3
|
export type ConsoleObject = {
|
|
4
4
|
[K in ConsoleMethod]: ConsoleMethodFunc;
|
|
@@ -8,9 +8,11 @@ export interface LoggerOptions {
|
|
|
8
8
|
isLogging?: boolean;
|
|
9
9
|
}
|
|
10
10
|
export declare const logMethod: (type: ConsoleMethod, isLogging: boolean, file: string) => (msg: string, caller?: string, ...args: unknown[]) => void;
|
|
11
|
+
export declare const warnMethod: (file: string) => (msg: string, caller?: string, ...args: unknown[]) => void;
|
|
11
12
|
export declare const logger: ({ file, isLogging }: LoggerOptions) => {
|
|
12
13
|
debug: (msg: string, caller?: string, ...args: unknown[]) => void;
|
|
13
14
|
error: (msg: string, caller?: string, ...args: unknown[]) => void;
|
|
14
15
|
info: (msg: string, caller?: string, ...args: unknown[]) => void;
|
|
16
|
+
warn: (msg: string, caller?: string, ...args: unknown[]) => void;
|
|
15
17
|
};
|
|
16
18
|
export {};
|
package/dist/utils/spinner.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export declare const succeed: (state: SpinnerState, text?: string) => Spinner;
|
|
|
14
14
|
export declare const fail: (state: SpinnerState, text?: string) => Spinner;
|
|
15
15
|
export declare const info: (state: SpinnerState, text?: string) => Spinner;
|
|
16
16
|
export declare const warn: (state: SpinnerState, text?: string) => Spinner;
|
|
17
|
+
export declare const update: (state: SpinnerState, text: string) => Spinner;
|
|
17
18
|
export declare const createSpinnerMethods: (state: SpinnerState) => Spinner;
|
|
18
19
|
export declare const createSpinner: (text: string) => Spinner;
|
|
19
20
|
export default createSpinner;
|
package/dist/utils/types.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export type Spinner = {
|
|
|
11
11
|
fail: (text?: string) => Spinner;
|
|
12
12
|
info: (text?: string) => Spinner;
|
|
13
13
|
warn: (text?: string) => Spinner;
|
|
14
|
+
update: (text: string) => Spinner;
|
|
14
15
|
};
|
|
15
16
|
export type RGB = {
|
|
16
17
|
r: number;
|
|
@@ -41,6 +42,7 @@ export interface RetryOptions {
|
|
|
41
42
|
minTimeout?: number;
|
|
42
43
|
maxTimeout?: number;
|
|
43
44
|
onFailedAttempt?: (error: RetryError) => void | Promise<void>;
|
|
45
|
+
onRetry?: (attemptNumber: number, retriesLeft: number) => void;
|
|
44
46
|
}
|
|
45
47
|
export interface RetryError extends Error {
|
|
46
48
|
attemptNumber: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pastoralist",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.4",
|
|
4
4
|
"description": "A tool to watch over node module resolutions and overrides 🐑 👩🏽🌾",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"pnpm"
|
|
57
57
|
],
|
|
58
58
|
"author": "Jeff Wainwright <https:jeffry.in> (yowainwright@gmail.com)",
|
|
59
|
-
"license": "
|
|
59
|
+
"license": "Elastic-2.0",
|
|
60
60
|
"bugs": {
|
|
61
61
|
"url": "https://github.com/yowainwright/pastoralist/issues"
|
|
62
62
|
},
|
|
@@ -69,9 +69,9 @@
|
|
|
69
69
|
"@types/bun": "latest",
|
|
70
70
|
"codependence": "^0.3.1",
|
|
71
71
|
"oxlint": "^1.25.0",
|
|
72
|
-
"prettier": "3.
|
|
73
|
-
"release-it": "19.0
|
|
74
|
-
"turbo": "2.6.
|
|
72
|
+
"prettier": "3.7.4",
|
|
73
|
+
"release-it": "19.1.0",
|
|
74
|
+
"turbo": "2.6.3",
|
|
75
75
|
"typescript": "5.9.3"
|
|
76
76
|
},
|
|
77
77
|
"release-it": {
|