@preship/core 1.0.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -40,7 +40,125 @@ interface ScanResult {
40
40
  passed: boolean;
41
41
  scanDurationMs: number;
42
42
  }
43
+ type SecuritySeverity = 'critical' | 'high' | 'medium' | 'low';
44
+ interface SecurityVulnerability {
45
+ id: string;
46
+ package: string;
47
+ version: string;
48
+ severity: SecuritySeverity;
49
+ summary: string;
50
+ fixedVersion?: string;
51
+ references: string[];
52
+ source: 'osv' | 'github-advisory' | 'npm-audit';
53
+ }
54
+ interface PackageHealth {
55
+ package: string;
56
+ version: string;
57
+ deprecated: boolean;
58
+ deprecationMessage?: string;
59
+ outdated: boolean;
60
+ latestVersion?: string;
61
+ majorVersionsBehind?: number;
62
+ unmaintained: boolean;
63
+ lastPublishDate?: string;
64
+ weeklyDownloads?: number;
65
+ }
66
+ type SecurityPolicyLevel = 'default' | 'strict' | 'lenient';
67
+ interface SecurityFinding {
68
+ type: 'vulnerability' | 'deprecated' | 'outdated' | 'unmaintained';
69
+ severity: SecuritySeverity;
70
+ package: string;
71
+ version: string;
72
+ message: string;
73
+ details?: SecurityVulnerability | PackageHealth;
74
+ }
75
+ interface SecurityResult {
76
+ enabled: boolean;
77
+ passed: boolean;
78
+ totalPackages: number;
79
+ vulnerabilities: SecurityVulnerability[];
80
+ healthIssues: PackageHealth[];
81
+ findings: SecurityFinding[];
82
+ stats: {
83
+ critical: number;
84
+ high: number;
85
+ medium: number;
86
+ low: number;
87
+ deprecated: number;
88
+ outdated: number;
89
+ unmaintained: number;
90
+ };
91
+ scanDurationMs: number;
92
+ }
93
+ type SecretSeverity = 'critical' | 'high' | 'medium' | 'low';
94
+ interface SecretRule {
95
+ id: string;
96
+ description: string;
97
+ severity: SecretSeverity;
98
+ keywords: string[];
99
+ pattern: RegExp;
100
+ entropyThreshold?: number;
101
+ allowPatterns?: RegExp[];
102
+ }
103
+ interface SecretFinding {
104
+ ruleId: string;
105
+ description: string;
106
+ severity: SecretSeverity;
107
+ file: string;
108
+ line: number;
109
+ column: number;
110
+ match: string;
111
+ entropy?: number;
112
+ }
113
+ interface SecretsResult {
114
+ enabled: boolean;
115
+ passed: boolean;
116
+ filesScanned: number;
117
+ findings: SecretFinding[];
118
+ stats: {
119
+ critical: number;
120
+ high: number;
121
+ medium: number;
122
+ low: number;
123
+ };
124
+ scanDurationMs: number;
125
+ }
126
+ interface UnifiedScanResult {
127
+ version: string;
128
+ projectPath: string;
129
+ projectType: ProjectType;
130
+ framework?: string;
131
+ timestamp: string;
132
+ passed: boolean;
133
+ mode: ResolverMode;
134
+ policy: string;
135
+ modules: {
136
+ license?: ScanResult;
137
+ security?: SecurityResult;
138
+ secrets?: SecretsResult;
139
+ };
140
+ totalScanDurationMs: number;
141
+ }
43
142
  type ResolverMode = 'auto' | 'online' | 'local';
143
+ interface ModuleConfig {
144
+ license: boolean;
145
+ security: boolean;
146
+ secrets: boolean;
147
+ }
148
+ interface SecurityConfig {
149
+ severity: SecurityPolicyLevel;
150
+ failOn: SecuritySeverity;
151
+ checkOutdated: boolean;
152
+ checkDeprecated: boolean;
153
+ checkUnmaintained: boolean;
154
+ outdatedMajorThreshold: number;
155
+ unmaintainedYears: number;
156
+ }
157
+ interface SecretsConfig {
158
+ scanPaths: string[];
159
+ allowPaths: string[];
160
+ allowRules: string[];
161
+ }
44
162
  interface PreshipConfig {
45
163
  policy?: string;
46
164
  reject?: string[];
@@ -56,6 +174,9 @@ interface PreshipConfig {
56
174
  cache?: boolean;
57
175
  cacheTTL?: number;
58
176
  scanTimeout?: number;
177
+ modules?: Partial<ModuleConfig>;
178
+ security?: Partial<SecurityConfig>;
179
+ secrets?: Partial<SecretsConfig>;
59
180
  }
60
181
  interface ExceptionEntry {
61
182
  package: string;
@@ -73,6 +194,7 @@ interface PolicyTemplate {
73
194
  scanDevDependencies: boolean;
74
195
  }
75
196
 
197
+ declare function getDefaultConfig(): PreshipConfig;
76
198
  declare function loadConfig(projectPath: string): PreshipConfig;
77
199
 
78
200
  declare function detectProjects(rootPath: string): DetectedProject[];
@@ -238,4 +360,4 @@ interface ScanTimeoutController {
238
360
  */
239
361
  declare function createScanTimeoutController(timeout?: number): ScanTimeoutController;
240
362
 
241
- export { AdaptiveRateLimiter, type CacheEntry, type CacheFile, type Dependency, type DetectedProject, type ExceptionEntry, type LicenseSource, type ParsedDependency, type PolicyResult, type PolicyTemplate, type PolicyVerdict, type PreshipConfig, type ProjectType, type ResolverMode, type ScanResult, type ScanTimeoutController, cacheKey, createEmptyCache, createScanTimeoutController, detectProjects, getCacheEntry, getOrCreateKey, loadCache, loadConfig, parseNpmLockfile, parsePnpmLockfile, parseYarnLockfile, saveCache, setCacheEntry };
363
+ export { AdaptiveRateLimiter, type CacheEntry, type CacheFile, type Dependency, type DetectedProject, type ExceptionEntry, type LicenseSource, type ModuleConfig, type PackageHealth, type ParsedDependency, type PolicyResult, type PolicyTemplate, type PolicyVerdict, type PreshipConfig, type ProjectType, type ResolverMode, type ScanResult, type ScanTimeoutController, type SecretFinding, type SecretRule, type SecretSeverity, type SecretsConfig, type SecretsResult, type SecurityConfig, type SecurityFinding, type SecurityPolicyLevel, type SecurityResult, type SecuritySeverity, type SecurityVulnerability, type UnifiedScanResult, cacheKey, createEmptyCache, createScanTimeoutController, detectProjects, getCacheEntry, getDefaultConfig, getOrCreateKey, loadCache, loadConfig, parseNpmLockfile, parsePnpmLockfile, parseYarnLockfile, saveCache, setCacheEntry };
package/dist/index.js CHANGED
@@ -36,6 +36,7 @@ __export(index_exports, {
36
36
  createScanTimeoutController: () => createScanTimeoutController,
37
37
  detectProjects: () => detectProjects,
38
38
  getCacheEntry: () => getCacheEntry,
39
+ getDefaultConfig: () => getDefaultConfig,
39
40
  getOrCreateKey: () => getOrCreateKey,
40
41
  loadCache: () => loadCache,
41
42
  loadConfig: () => loadConfig,
@@ -56,9 +57,11 @@ var CONFIG_FILENAMES = [
56
57
  "preship-config.yaml",
57
58
  "preship-config.json"
58
59
  ];
59
- var VALID_POLICIES = ["commercial-safe", "strict", "permissive-only"];
60
+ var VALID_POLICIES = ["commercial-safe", "saas-safe", "distribution-safe", "strict", "permissive-only"];
60
61
  var VALID_OUTPUTS = ["table", "json", "csv"];
61
62
  var VALID_MODES = ["auto", "online", "local"];
63
+ var VALID_SECURITY_SEVERITIES = ["default", "strict", "lenient"];
64
+ var VALID_SECURITY_FAIL_ON = ["critical", "high", "medium", "low"];
62
65
  function validateConfig(config, filePath) {
63
66
  if (config.policy !== void 0) {
64
67
  if (typeof config.policy !== "string" || !VALID_POLICIES.includes(config.policy)) {
@@ -190,6 +193,97 @@ function validateConfig(config, filePath) {
190
193
  );
191
194
  }
192
195
  }
196
+ if (config.modules !== void 0) {
197
+ if (typeof config.modules !== "object" || config.modules === null || Array.isArray(config.modules)) {
198
+ throw new Error(
199
+ `Invalid preship-config at ${filePath}:
200
+ 'modules' must be an object with boolean values (e.g., { license: true, security: true, secrets: true }).
201
+ See https://github.com/dipen-code/preship for config docs.`
202
+ );
203
+ }
204
+ const m = config.modules;
205
+ for (const key of ["license", "security", "secrets"]) {
206
+ if (m[key] !== void 0 && typeof m[key] !== "boolean") {
207
+ throw new Error(
208
+ `Invalid preship-config at ${filePath}:
209
+ 'modules.${key}' must be a boolean, got ${typeof m[key]}.
210
+ See https://github.com/dipen-code/preship for config docs.`
211
+ );
212
+ }
213
+ }
214
+ }
215
+ if (config.security !== void 0) {
216
+ if (typeof config.security !== "object" || config.security === null || Array.isArray(config.security)) {
217
+ throw new Error(
218
+ `Invalid preship-config at ${filePath}:
219
+ 'security' must be an object.
220
+ See https://github.com/dipen-code/preship for config docs.`
221
+ );
222
+ }
223
+ const s = config.security;
224
+ if (s.severity !== void 0 && (typeof s.severity !== "string" || !VALID_SECURITY_SEVERITIES.includes(s.severity))) {
225
+ throw new Error(
226
+ `Invalid preship-config at ${filePath}:
227
+ 'security.severity' must be one of: ${VALID_SECURITY_SEVERITIES.join(", ")}, got '${s.severity}'.
228
+ See https://github.com/dipen-code/preship for config docs.`
229
+ );
230
+ }
231
+ if (s.failOn !== void 0 && (typeof s.failOn !== "string" || !VALID_SECURITY_FAIL_ON.includes(s.failOn))) {
232
+ throw new Error(
233
+ `Invalid preship-config at ${filePath}:
234
+ 'security.failOn' must be one of: ${VALID_SECURITY_FAIL_ON.join(", ")}, got '${s.failOn}'.
235
+ See https://github.com/dipen-code/preship for config docs.`
236
+ );
237
+ }
238
+ for (const boolField of ["checkOutdated", "checkDeprecated", "checkUnmaintained"]) {
239
+ if (s[boolField] !== void 0 && typeof s[boolField] !== "boolean") {
240
+ throw new Error(
241
+ `Invalid preship-config at ${filePath}:
242
+ 'security.${boolField}' must be a boolean, got ${typeof s[boolField]}.
243
+ See https://github.com/dipen-code/preship for config docs.`
244
+ );
245
+ }
246
+ }
247
+ for (const numField of ["outdatedMajorThreshold", "unmaintainedYears"]) {
248
+ if (s[numField] !== void 0 && (typeof s[numField] !== "number" || s[numField] <= 0)) {
249
+ throw new Error(
250
+ `Invalid preship-config at ${filePath}:
251
+ 'security.${numField}' must be a positive number, got '${s[numField]}'.
252
+ See https://github.com/dipen-code/preship for config docs.`
253
+ );
254
+ }
255
+ }
256
+ }
257
+ if (config.secrets !== void 0) {
258
+ if (typeof config.secrets !== "object" || config.secrets === null || Array.isArray(config.secrets)) {
259
+ throw new Error(
260
+ `Invalid preship-config at ${filePath}:
261
+ 'secrets' must be an object.
262
+ See https://github.com/dipen-code/preship for config docs.`
263
+ );
264
+ }
265
+ const sec = config.secrets;
266
+ for (const arrField of ["scanPaths", "allowPaths", "allowRules"]) {
267
+ if (sec[arrField] !== void 0) {
268
+ if (!Array.isArray(sec[arrField])) {
269
+ throw new Error(
270
+ `Invalid preship-config at ${filePath}:
271
+ 'secrets.${arrField}' must be an array of strings.
272
+ See https://github.com/dipen-code/preship for config docs.`
273
+ );
274
+ }
275
+ for (const item of sec[arrField]) {
276
+ if (typeof item !== "string") {
277
+ throw new Error(
278
+ `Invalid preship-config at ${filePath}:
279
+ 'secrets.${arrField}' must contain only strings, found ${typeof item}.
280
+ See https://github.com/dipen-code/preship for config docs.`
281
+ );
282
+ }
283
+ }
284
+ }
285
+ }
286
+ }
193
287
  return config;
194
288
  }
195
289
  function getDefaultConfig() {
@@ -205,8 +299,27 @@ function getDefaultConfig() {
205
299
  cache: true,
206
300
  cacheTTL: 604800,
207
301
  // 7 days in seconds
208
- scanTimeout: 6e4
302
+ scanTimeout: 6e4,
209
303
  // 60 seconds in ms (0 = disabled)
304
+ modules: {
305
+ license: true,
306
+ security: true,
307
+ secrets: true
308
+ },
309
+ security: {
310
+ severity: "default",
311
+ failOn: "high",
312
+ checkOutdated: true,
313
+ checkDeprecated: true,
314
+ checkUnmaintained: true,
315
+ outdatedMajorThreshold: 3,
316
+ unmaintainedYears: 2
317
+ },
318
+ secrets: {
319
+ scanPaths: [],
320
+ allowPaths: [],
321
+ allowRules: []
322
+ }
210
323
  };
211
324
  }
212
325
  function loadConfig(projectPath) {
@@ -244,7 +357,19 @@ function loadConfig(projectPath) {
244
357
  return {
245
358
  ...defaults,
246
359
  ...validated,
247
- exceptions: validated.exceptions ?? defaults.exceptions
360
+ exceptions: validated.exceptions ?? defaults.exceptions,
361
+ modules: {
362
+ ...defaults.modules,
363
+ ...validated.modules ?? {}
364
+ },
365
+ security: {
366
+ ...defaults.security,
367
+ ...validated.security ?? {}
368
+ },
369
+ secrets: {
370
+ ...defaults.secrets,
371
+ ...validated.secrets ?? {}
372
+ }
248
373
  };
249
374
  }
250
375
  return getDefaultConfig();
@@ -901,6 +1026,7 @@ function createScanTimeoutController(timeout) {
901
1026
  createScanTimeoutController,
902
1027
  detectProjects,
903
1028
  getCacheEntry,
1029
+ getDefaultConfig,
904
1030
  getOrCreateKey,
905
1031
  loadCache,
906
1032
  loadConfig,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@preship/core",
3
- "version": "1.0.2",
3
+ "version": "2.0.0",
4
4
  "description": "Core infrastructure for PreShip — types, config, detection, parsing, caching, and rate limiting",
5
5
  "author": "Cyfox Inc.",
6
6
  "license": "Apache-2.0",