pastoralist 1.7.2 → 1.7.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/README.md CHANGED
@@ -294,6 +294,171 @@ For detailed information about using Pastoralist in workspace/monorepo environme
294
294
 
295
295
  ---
296
296
 
297
+ ## Configuration
298
+
299
+ Pastoralist supports multiple configuration methods to fit your project's needs. Configuration can be defined in external files or directly in your `package.json`.
300
+
301
+ ### Configuration Files
302
+
303
+ Pastoralist searches for configuration files in this order (first found wins):
304
+
305
+ 1. `.pastoralistrc` (JSON format)
306
+ 2. `.pastoralistrc.json`
307
+ 3. `pastoralist.json`
308
+ 4. `pastoralist.config.js`
309
+ 5. `pastoralist.config.ts`
310
+
311
+ **Example `.pastoralistrc.json`:**
312
+
313
+ ```json
314
+ {
315
+ "checkSecurity": true,
316
+ "depPaths": "workspaces",
317
+ "security": {
318
+ "provider": "osv",
319
+ "severityThreshold": "medium"
320
+ }
321
+ }
322
+ ```
323
+
324
+ **Example `pastoralist.config.js`:**
325
+
326
+ ```js
327
+ module.exports = {
328
+ checkSecurity: true,
329
+ depPaths: ["packages/*/package.json", "apps/*/package.json"],
330
+ security: {
331
+ provider: "osv",
332
+ severityThreshold: "high",
333
+ excludePackages: ["@types/*"]
334
+ }
335
+ };
336
+ ```
337
+
338
+ **Example `pastoralist.config.ts`:**
339
+
340
+ ```ts
341
+ import { PastoralistConfig } from 'pastoralist';
342
+
343
+ const config: PastoralistConfig = {
344
+ checkSecurity: true,
345
+ depPaths: "workspaces",
346
+ security: {
347
+ provider: "osv",
348
+ severityThreshold: "critical"
349
+ }
350
+ };
351
+
352
+ export default config;
353
+ ```
354
+
355
+ ### Configuration Priority
356
+
357
+ When both external config files and `package.json` configuration exist:
358
+
359
+ 1. **External config** provides base settings
360
+ 2. **`package.json`** overrides top-level fields
361
+ 3. **Nested objects** (like `security`) are deep merged
362
+
363
+ **Example:**
364
+
365
+ ```js
366
+ // .pastoralistrc.json
367
+ {
368
+ "checkSecurity": true,
369
+ "depPaths": "workspaces",
370
+ "security": {
371
+ "provider": "osv",
372
+ "severityThreshold": "medium"
373
+ }
374
+ }
375
+
376
+ // package.json
377
+ {
378
+ "pastoralist": {
379
+ "security": {
380
+ "severityThreshold": "high" // Overrides "medium" from .pastoralistrc.json
381
+ }
382
+ }
383
+ }
384
+
385
+ // Effective config:
386
+ {
387
+ "checkSecurity": true,
388
+ "depPaths": "workspaces",
389
+ "security": {
390
+ "provider": "osv",
391
+ "severityThreshold": "high" // From package.json
392
+ }
393
+ }
394
+ ```
395
+
396
+ ### Configuration Options
397
+
398
+ | Option | Type | Description |
399
+ |--------|------|-------------|
400
+ | `checkSecurity` | `boolean` | Enable security vulnerability scanning |
401
+ | `depPaths` | `"workspace"` \| `"workspaces"` \| `string[]` | Paths to scan for dependencies in monorepos |
402
+ | `appendix` | `object` | Auto-generated dependency tracking (managed by Pastoralist) |
403
+ | `overridePaths` | `object` | Manual override tracking for specific paths |
404
+ | `resolutionPaths` | `object` | Manual resolution tracking for specific paths |
405
+ | `security` | `object` | Security scanning configuration (see below) |
406
+
407
+ #### Security Configuration
408
+
409
+ | Option | Type | Description |
410
+ |--------|------|-------------|
411
+ | `enabled` | `boolean` | Enable/disable security checks |
412
+ | `provider` | `"osv"` \| `"github"` \| `"snyk"` \| `"npm"` \| `"socket"` | Security provider (currently only OSV) |
413
+ | `autoFix` | `boolean` | Automatically apply security fixes |
414
+ | `interactive` | `boolean` | Use interactive mode for security fixes |
415
+ | `securityProviderToken` | `string` | API token for providers that require auth |
416
+ | `severityThreshold` | `"low"` \| `"medium"` \| `"high"` \| `"critical"` | Minimum severity level to report |
417
+ | `excludePackages` | `string[]` | Packages to exclude from security checks |
418
+ | `hasWorkspaceSecurityChecks` | `boolean` | Include workspace packages in scans |
419
+
420
+ ### Security Tracking in Appendix
421
+
422
+ When security vulnerabilities are detected and fixed, Pastoralist tracks this information in the appendix ledger:
423
+
424
+ ```js
425
+ "pastoralist": {
426
+ "appendix": {
427
+ "lodash@4.17.21": {
428
+ "dependents": {
429
+ "my-app": "lodash@^4.17.0"
430
+ },
431
+ "ledger": {
432
+ "addedDate": "2024-01-15T10:30:00.000Z",
433
+ "reason": "Security vulnerability CVE-2021-23337",
434
+ "securityChecked": true,
435
+ "securityCheckDate": "2024-01-15T10:30:00.000Z",
436
+ "securityProvider": "osv"
437
+ }
438
+ }
439
+ }
440
+ }
441
+ ```
442
+
443
+ The ledger tracks:
444
+ - `addedDate`: When the override was first added
445
+ - `reason`: Why the override was needed (e.g., security issue description)
446
+ - `securityChecked`: Whether a security check was performed
447
+ - `securityCheckDate`: When the last security check occurred
448
+ - `securityProvider`: Which provider detected the vulnerability
449
+
450
+ This allows you to see at a glance which packages were overridden due to security issues and when they were last verified.
451
+
452
+ ### Best Practices
453
+
454
+ 1. **Use external config files** for shared settings across teams
455
+ 2. **Use `package.json`** for project-specific overrides
456
+ 3. **Commit config files** to version control
457
+ 4. **Use `depPaths: "workspaces"`** for most monorepos
458
+ 5. **Enable security checks** in CI/CD pipelines with `--checkSecurity`
459
+
460
+ ---
461
+
297
462
  ## Setup
298
463
 
299
464
  > #### Okay! Hopefully the breakdowns above were clear enough on why you might want to use Pastoralist!
@@ -0,0 +1 @@
1
+ export declare const CONFIG_FILES: readonly [".pastoralistrc", ".pastoralistrc.json", "pastoralist.json", "pastoralist.config.js", "pastoralist.config.ts"];
@@ -0,0 +1,158 @@
1
+ import { z } from "zod";
2
+ export declare const AppendixItemSchema: z.ZodObject<{
3
+ rootDeps: z.ZodOptional<z.ZodArray<z.ZodString>>;
4
+ dependents: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
5
+ patches: z.ZodOptional<z.ZodArray<z.ZodString>>;
6
+ ledger: z.ZodOptional<z.ZodObject<{
7
+ addedDate: z.ZodString;
8
+ reason: z.ZodOptional<z.ZodString>;
9
+ securityChecked: z.ZodOptional<z.ZodBoolean>;
10
+ securityCheckDate: z.ZodOptional<z.ZodString>;
11
+ securityProvider: z.ZodOptional<z.ZodEnum<{
12
+ npm: "npm";
13
+ osv: "osv";
14
+ github: "github";
15
+ snyk: "snyk";
16
+ socket: "socket";
17
+ }>>;
18
+ }, z.core.$strip>>;
19
+ }, z.core.$strip>;
20
+ export declare const AppendixSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
21
+ rootDeps: z.ZodOptional<z.ZodArray<z.ZodString>>;
22
+ dependents: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
23
+ patches: z.ZodOptional<z.ZodArray<z.ZodString>>;
24
+ ledger: z.ZodOptional<z.ZodObject<{
25
+ addedDate: z.ZodString;
26
+ reason: z.ZodOptional<z.ZodString>;
27
+ securityChecked: z.ZodOptional<z.ZodBoolean>;
28
+ securityCheckDate: z.ZodOptional<z.ZodString>;
29
+ securityProvider: z.ZodOptional<z.ZodEnum<{
30
+ npm: "npm";
31
+ osv: "osv";
32
+ github: "github";
33
+ snyk: "snyk";
34
+ socket: "socket";
35
+ }>>;
36
+ }, z.core.$strip>>;
37
+ }, z.core.$strip>>;
38
+ export declare const SecurityProviderSchema: z.ZodEnum<{
39
+ npm: "npm";
40
+ osv: "osv";
41
+ github: "github";
42
+ snyk: "snyk";
43
+ socket: "socket";
44
+ }>;
45
+ export declare const SeverityThresholdSchema: z.ZodEnum<{
46
+ high: "high";
47
+ medium: "medium";
48
+ low: "low";
49
+ critical: "critical";
50
+ }>;
51
+ export declare const SecurityConfigSchema: z.ZodObject<{
52
+ enabled: z.ZodOptional<z.ZodBoolean>;
53
+ provider: z.ZodOptional<z.ZodEnum<{
54
+ npm: "npm";
55
+ osv: "osv";
56
+ github: "github";
57
+ snyk: "snyk";
58
+ socket: "socket";
59
+ }>>;
60
+ autoFix: z.ZodOptional<z.ZodBoolean>;
61
+ interactive: z.ZodOptional<z.ZodBoolean>;
62
+ securityProviderToken: z.ZodOptional<z.ZodString>;
63
+ severityThreshold: z.ZodOptional<z.ZodEnum<{
64
+ high: "high";
65
+ medium: "medium";
66
+ low: "low";
67
+ critical: "critical";
68
+ }>>;
69
+ excludePackages: z.ZodOptional<z.ZodArray<z.ZodString>>;
70
+ hasWorkspaceSecurityChecks: z.ZodOptional<z.ZodBoolean>;
71
+ }, z.core.$strip>;
72
+ export declare const PastoralistConfigSchema: z.ZodObject<{
73
+ appendix: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
74
+ rootDeps: z.ZodOptional<z.ZodArray<z.ZodString>>;
75
+ dependents: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
76
+ patches: z.ZodOptional<z.ZodArray<z.ZodString>>;
77
+ ledger: z.ZodOptional<z.ZodObject<{
78
+ addedDate: z.ZodString;
79
+ reason: z.ZodOptional<z.ZodString>;
80
+ securityChecked: z.ZodOptional<z.ZodBoolean>;
81
+ securityCheckDate: z.ZodOptional<z.ZodString>;
82
+ securityProvider: z.ZodOptional<z.ZodEnum<{
83
+ npm: "npm";
84
+ osv: "osv";
85
+ github: "github";
86
+ snyk: "snyk";
87
+ socket: "socket";
88
+ }>>;
89
+ }, z.core.$strip>>;
90
+ }, z.core.$strip>>>;
91
+ depPaths: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"workspace">, z.ZodLiteral<"workspaces">, z.ZodArray<z.ZodString>]>>;
92
+ checkSecurity: z.ZodOptional<z.ZodBoolean>;
93
+ overridePaths: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodObject<{
94
+ rootDeps: z.ZodOptional<z.ZodArray<z.ZodString>>;
95
+ dependents: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
96
+ patches: z.ZodOptional<z.ZodArray<z.ZodString>>;
97
+ ledger: z.ZodOptional<z.ZodObject<{
98
+ addedDate: z.ZodString;
99
+ reason: z.ZodOptional<z.ZodString>;
100
+ securityChecked: z.ZodOptional<z.ZodBoolean>;
101
+ securityCheckDate: z.ZodOptional<z.ZodString>;
102
+ securityProvider: z.ZodOptional<z.ZodEnum<{
103
+ npm: "npm";
104
+ osv: "osv";
105
+ github: "github";
106
+ snyk: "snyk";
107
+ socket: "socket";
108
+ }>>;
109
+ }, z.core.$strip>>;
110
+ }, z.core.$strip>>>>;
111
+ resolutionPaths: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodObject<{
112
+ rootDeps: z.ZodOptional<z.ZodArray<z.ZodString>>;
113
+ dependents: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
114
+ patches: z.ZodOptional<z.ZodArray<z.ZodString>>;
115
+ ledger: z.ZodOptional<z.ZodObject<{
116
+ addedDate: z.ZodString;
117
+ reason: z.ZodOptional<z.ZodString>;
118
+ securityChecked: z.ZodOptional<z.ZodBoolean>;
119
+ securityCheckDate: z.ZodOptional<z.ZodString>;
120
+ securityProvider: z.ZodOptional<z.ZodEnum<{
121
+ npm: "npm";
122
+ osv: "osv";
123
+ github: "github";
124
+ snyk: "snyk";
125
+ socket: "socket";
126
+ }>>;
127
+ }, z.core.$strip>>;
128
+ }, z.core.$strip>>>>;
129
+ security: z.ZodOptional<z.ZodObject<{
130
+ enabled: z.ZodOptional<z.ZodBoolean>;
131
+ provider: z.ZodOptional<z.ZodEnum<{
132
+ npm: "npm";
133
+ osv: "osv";
134
+ github: "github";
135
+ snyk: "snyk";
136
+ socket: "socket";
137
+ }>>;
138
+ autoFix: z.ZodOptional<z.ZodBoolean>;
139
+ interactive: z.ZodOptional<z.ZodBoolean>;
140
+ securityProviderToken: z.ZodOptional<z.ZodString>;
141
+ severityThreshold: z.ZodOptional<z.ZodEnum<{
142
+ high: "high";
143
+ medium: "medium";
144
+ low: "low";
145
+ critical: "critical";
146
+ }>>;
147
+ excludePackages: z.ZodOptional<z.ZodArray<z.ZodString>>;
148
+ hasWorkspaceSecurityChecks: z.ZodOptional<z.ZodBoolean>;
149
+ }, z.core.$strip>>;
150
+ }, z.core.$strip>;
151
+ export type AppendixItem = z.infer<typeof AppendixItemSchema>;
152
+ export type Appendix = z.infer<typeof AppendixSchema>;
153
+ export type SecurityProvider = z.infer<typeof SecurityProviderSchema>;
154
+ export type SeverityThreshold = z.infer<typeof SeverityThresholdSchema>;
155
+ export type SecurityConfig = z.infer<typeof SecurityConfigSchema>;
156
+ export type PastoralistConfig = z.infer<typeof PastoralistConfigSchema>;
157
+ export declare function validateConfig(config: unknown): PastoralistConfig;
158
+ export declare function safeValidateConfig(config: unknown): PastoralistConfig | undefined;
@@ -0,0 +1,4 @@
1
+ import { PastoralistConfig } from "./index";
2
+ export declare const loadExternalConfig: (root?: string, validate?: boolean) => Promise<PastoralistConfig | undefined>;
3
+ export declare const mergeConfigs: (externalConfig: PastoralistConfig | undefined, packageJsonConfig: PastoralistConfig | undefined) => PastoralistConfig | undefined;
4
+ export declare const loadConfig: (root?: string, packageJsonConfig?: PastoralistConfig, validate?: boolean) => Promise<PastoralistConfig | undefined>;