dep-oracle 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +33 -8
  2. package/dist/action/index.js +398 -16
  3. package/dist/badge-5Z3WAD2B.js +89 -0
  4. package/dist/badge-5Z3WAD2B.js.map +1 -0
  5. package/dist/chunk-32B3QIPY.js +1505 -0
  6. package/dist/chunk-32B3QIPY.js.map +1 -0
  7. package/dist/chunk-7DST6SNA.js +258 -0
  8. package/dist/chunk-7DST6SNA.js.map +1 -0
  9. package/dist/{chunk-TXSNFX3N.js → chunk-DLWG22RC.js} +403 -17
  10. package/dist/chunk-DLWG22RC.js.map +1 -0
  11. package/dist/chunk-HX6MGNBD.js +271 -0
  12. package/dist/chunk-HX6MGNBD.js.map +1 -0
  13. package/dist/chunk-IVXGOPRU.js +145 -0
  14. package/dist/chunk-IVXGOPRU.js.map +1 -0
  15. package/dist/chunk-SP3VYPXX.js +218 -0
  16. package/dist/chunk-SP3VYPXX.js.map +1 -0
  17. package/dist/chunk-T5EVLWZM.js +4234 -0
  18. package/dist/chunk-T5EVLWZM.js.map +1 -0
  19. package/dist/chunk-UMB5MJHL.js +239 -0
  20. package/dist/chunk-UMB5MJHL.js.map +1 -0
  21. package/dist/cli/index.js +163 -6499
  22. package/dist/cli/index.js.map +1 -1
  23. package/dist/index.js +9 -84
  24. package/dist/index.js.map +1 -1
  25. package/dist/mcp/server.js +33 -12
  26. package/dist/mcp/server.js.map +1 -1
  27. package/dist/npm-UB54H37N.js +9 -0
  28. package/dist/npm-UB54H37N.js.map +1 -0
  29. package/dist/orchestrator-VOOYKDPT.js +8 -0
  30. package/dist/orchestrator-VOOYKDPT.js.map +1 -0
  31. package/dist/python-U4G2GK4J.js +9 -0
  32. package/dist/python-U4G2GK4J.js.map +1 -0
  33. package/dist/server-WONIBSG4.js +640 -0
  34. package/dist/server-WONIBSG4.js.map +1 -0
  35. package/dist/store-Z5UANEBB.js +8 -0
  36. package/dist/store-Z5UANEBB.js.map +1 -0
  37. package/dist/trust-score-YXYDFVPZ.js +8 -0
  38. package/dist/trust-score-YXYDFVPZ.js.map +1 -0
  39. package/package.json +1 -1
  40. package/server.json +2 -2
  41. package/dist/chunk-TXSNFX3N.js.map +0 -1
@@ -0,0 +1,239 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/parsers/schema.ts
4
+ import { z } from "zod";
5
+ var RegistryEnum = z.enum(["npm", "pypi"]);
6
+ var DependencyNodeSchema = z.object({
7
+ /** Package name (e.g. "express", "requests") */
8
+ name: z.string().min(1),
9
+ /** Resolved or declared version string */
10
+ version: z.string(),
11
+ /** 0 = direct dependency, 1+ = transitive depth */
12
+ depth: z.number().int().min(0),
13
+ /** Convenience flag: true when depth === 0 */
14
+ isDirect: z.boolean(),
15
+ /** Parent package name, null for direct deps */
16
+ parent: z.string().nullable(),
17
+ /** Which registry this package comes from */
18
+ registry: RegistryEnum
19
+ });
20
+ var DependencyTreeSchema = z.object({
21
+ /** Project / root package name */
22
+ root: z.string(),
23
+ /** Absolute path to the manifest file that was parsed */
24
+ manifest: z.string(),
25
+ /** All resolved dependency nodes keyed by "name@version" */
26
+ nodes: z.map(z.string(), DependencyNodeSchema),
27
+ /** Count of direct dependencies (depth === 0) */
28
+ totalDirect: z.number().int().min(0),
29
+ /** Count of transitive dependencies (depth > 0) */
30
+ totalTransitive: z.number().int().min(0)
31
+ });
32
+ var CollectorStatusEnum = z.enum(["success", "error", "cached", "offline"]);
33
+ var RegistryDataSchema = z.object({
34
+ /** Package name */
35
+ packageName: z.string(),
36
+ /** Resolved version string */
37
+ version: z.string(),
38
+ /** Short description from the registry */
39
+ description: z.string().nullable(),
40
+ /** ISO-8601 timestamp of the last publish, null if unknown */
41
+ lastPublishDate: z.string().nullable(),
42
+ /** Total number of published versions */
43
+ versionCount: z.number().int().min(0),
44
+ /** Deprecation message string, null if not deprecated */
45
+ deprecated: z.string().nullable(),
46
+ /** Downloads in the last 7 days */
47
+ weeklyDownloads: z.number().int().min(0),
48
+ /** SPDX license identifier from the registry */
49
+ license: z.string().nullable(),
50
+ /** Normalised repository URL */
51
+ repositoryUrl: z.string().nullable()
52
+ });
53
+ var GitHubDataSchema = z.object({
54
+ /** GitHub repository owner */
55
+ owner: z.string(),
56
+ /** GitHub repository name */
57
+ repo: z.string(),
58
+ stars: z.number().int().min(0),
59
+ forks: z.number().int().min(0),
60
+ openIssues: z.number().int().min(0),
61
+ /** ISO-8601 timestamp of the last repo update */
62
+ updatedAt: z.string(),
63
+ /** Whether the repository is archived */
64
+ archived: z.boolean(),
65
+ /** Default branch name */
66
+ defaultBranch: z.string(),
67
+ contributorCount: z.number().int().min(0),
68
+ /** Number of commits in the last 30 days */
69
+ recentCommitCount: z.number().int().min(0),
70
+ /** ISO-8601 timestamp of the most recent commit, null if unknown */
71
+ lastCommitDate: z.string().nullable(),
72
+ /** SHA of the most recent commit, null if unknown */
73
+ lastCommitSha: z.string().nullable(),
74
+ /** Whether a .github/FUNDING.yml file exists */
75
+ hasFundingYml: z.boolean()
76
+ });
77
+ var VulnerabilityEntrySchema = z.object({
78
+ id: z.string(),
79
+ summary: z.string().nullable(),
80
+ severity: z.enum(["critical", "high", "medium", "low", "unknown"]),
81
+ published: z.string()
82
+ });
83
+ var SecurityDataSchema = z.object({
84
+ /** Package name */
85
+ packageName: z.string(),
86
+ /** Resolved version string */
87
+ version: z.string(),
88
+ /** Total number of known vulnerabilities */
89
+ totalVulnerabilities: z.number().int().min(0),
90
+ /** Vulnerability counts by severity level */
91
+ severityCounts: z.record(z.string(), z.number().int().min(0)),
92
+ /** ISO-8601 timestamp of the most recent vulnerability, null if none */
93
+ latestVulnDate: z.string().nullable(),
94
+ /** Average days from disclosure to patch, null when unknown */
95
+ averagePatchDays: z.number().nullable(),
96
+ /** List of individual vulnerabilities */
97
+ vulnerabilities: z.array(VulnerabilityEntrySchema)
98
+ });
99
+ var FundingDataSchema = z.object({
100
+ /** Package name */
101
+ packageName: z.string(),
102
+ /** Whether GitHub sponsors exist (via FUNDING.yml) */
103
+ hasSponsors: z.boolean(),
104
+ /** Whether an OpenCollective profile is active */
105
+ hasOpenCollective: z.boolean(),
106
+ /** Whether the npm registry "funding" field is set */
107
+ hasNpmFunding: z.boolean(),
108
+ /** OpenCollective slug, null if none */
109
+ openCollectiveSlug: z.string().nullable(),
110
+ /** Number of OpenCollective backers */
111
+ openCollectiveBackers: z.number().int().min(0),
112
+ /** Rough USD estimate of annual funding, 0 when unknown */
113
+ estimatedAnnualFunding: z.number().min(0),
114
+ /** Collected funding URLs from all sources */
115
+ fundingUrls: z.array(z.string())
116
+ });
117
+ var DownloadTrendEnum = z.enum(["rising", "stable", "declining"]);
118
+ var PopularityDataSchema = z.object({
119
+ /** Package name */
120
+ packageName: z.string(),
121
+ /** Downloads in the last 7 days */
122
+ weeklyDownloads: z.number().int().min(0),
123
+ /** Downloads in the last 30 days */
124
+ monthlyDownloads: z.number().int().min(0),
125
+ /** Download trend direction */
126
+ trend: DownloadTrendEnum,
127
+ /** Number of packages that depend on this one */
128
+ dependentCount: z.number().int().min(0)
129
+ });
130
+ var LicenseRiskEnum = z.enum(["safe", "cautious", "risky", "unknown"]);
131
+ var LicenseDataSchema = z.object({
132
+ /** Package name */
133
+ packageName: z.string(),
134
+ /** Resolved version string */
135
+ version: z.string(),
136
+ /** Raw license string from the registry */
137
+ raw: z.string().nullable(),
138
+ /** Normalised SPDX identifier, null if unrecognised */
139
+ spdx: z.string().nullable(),
140
+ /** Risk classification */
141
+ risk: LicenseRiskEnum,
142
+ /** Whether the license is OSI-approved */
143
+ osiApproved: z.boolean()
144
+ });
145
+ var scoreField = z.number().min(0).max(100);
146
+ var TrustMetricsSchema = z.object({
147
+ security: scoreField,
148
+ maintainer: scoreField,
149
+ activity: scoreField,
150
+ popularity: scoreField,
151
+ funding: scoreField,
152
+ license: scoreField
153
+ });
154
+ var TrustReportSchema = z.object({
155
+ /** Package name */
156
+ package: z.string(),
157
+ /** Analyzed version */
158
+ version: z.string(),
159
+ /** Weighted overall score 0-100 */
160
+ trustScore: scoreField,
161
+ /** Breakdown by dimension */
162
+ metrics: TrustMetricsSchema,
163
+ /** True when the package shows signs of abandonment */
164
+ isZombie: z.boolean(),
165
+ /** Number of project files that import this package */
166
+ blastRadius: z.number().int().min(0),
167
+ /** Suggested replacement packages if the score is low */
168
+ alternatives: z.array(z.string()),
169
+ /** Download trend for quick triage */
170
+ trend: DownloadTrendEnum,
171
+ /** Probability (0-1) that the package name is a typosquat */
172
+ typosquatRisk: z.number().min(0).max(1)
173
+ });
174
+ var ScanResultSchema = z.object({
175
+ tree: DependencyTreeSchema,
176
+ reports: z.array(TrustReportSchema),
177
+ /** Weighted average of all package trust scores */
178
+ overallScore: scoreField,
179
+ /** Human-readable summary paragraph */
180
+ summary: z.string()
181
+ });
182
+ var ConfigSchema = z.object({
183
+ /** Minimum trust score before a warning is emitted */
184
+ minTrustScore: z.number().min(0).max(100).default(50),
185
+ /** How long collector responses are cached, in seconds */
186
+ cacheTtl: z.number().int().min(0).default(86400),
187
+ /** GitHub personal access token (increases rate limit) */
188
+ githubToken: z.string().optional(),
189
+ /** Packages to exclude from scanning */
190
+ ignore: z.array(z.string()).default([]),
191
+ /** Weight overrides for the trust-score dimensions (must sum to ~1) */
192
+ weights: z.object({
193
+ security: z.number().min(0).max(1).default(0.3),
194
+ maintainer: z.number().min(0).max(1).default(0.2),
195
+ activity: z.number().min(0).max(1).default(0.15),
196
+ popularity: z.number().min(0).max(1).default(0.15),
197
+ funding: z.number().min(0).max(1).default(0.1),
198
+ license: z.number().min(0).max(1).default(0.1)
199
+ }).default({}),
200
+ /** Maximum concurrent network requests */
201
+ concurrency: z.number().int().min(1).max(20).default(6),
202
+ /** Registries to query */
203
+ registries: z.array(RegistryEnum).default(["npm"]),
204
+ /** Output format */
205
+ outputFormat: z.enum(["table", "json", "markdown"]).default("table"),
206
+ /** Days of inactivity after which a package is considered a zombie */
207
+ zombieThresholdDays: z.number().int().min(1).default(365),
208
+ /** Enable offline mode (only use cache, never hit network) */
209
+ offline: z.boolean().default(false)
210
+ });
211
+ function createDependencyNode(partial) {
212
+ return {
213
+ depth: 0,
214
+ isDirect: partial.depth === void 0 || partial.depth === 0,
215
+ parent: null,
216
+ ...partial
217
+ };
218
+ }
219
+ function createDependencyTree(root, manifest) {
220
+ return {
221
+ root,
222
+ manifest,
223
+ nodes: /* @__PURE__ */ new Map(),
224
+ totalDirect: 0,
225
+ totalTransitive: 0
226
+ };
227
+ }
228
+
229
+ // src/parsers/base.ts
230
+ var BaseParser = class {
231
+ };
232
+
233
+ export {
234
+ ConfigSchema,
235
+ createDependencyNode,
236
+ createDependencyTree,
237
+ BaseParser
238
+ };
239
+ //# sourceMappingURL=chunk-UMB5MJHL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/parsers/schema.ts","../src/parsers/base.ts"],"sourcesContent":["import { z } from \"zod\";\n\n// ---------------------------------------------------------------------------\n// Registry enum\n// ---------------------------------------------------------------------------\n\nexport const RegistryEnum = z.enum([\"npm\", \"pypi\"]);\nexport type Registry = z.infer<typeof RegistryEnum>;\n\n// ---------------------------------------------------------------------------\n// DependencyNode\n// ---------------------------------------------------------------------------\n\nexport const DependencyNodeSchema = z.object({\n /** Package name (e.g. \"express\", \"requests\") */\n name: z.string().min(1),\n /** Resolved or declared version string */\n version: z.string(),\n /** 0 = direct dependency, 1+ = transitive depth */\n depth: z.number().int().min(0),\n /** Convenience flag: true when depth === 0 */\n isDirect: z.boolean(),\n /** Parent package name, null for direct deps */\n parent: z.string().nullable(),\n /** Which registry this package comes from */\n registry: RegistryEnum,\n});\n\nexport type DependencyNode = z.infer<typeof DependencyNodeSchema>;\n\n// ---------------------------------------------------------------------------\n// DependencyTree\n// ---------------------------------------------------------------------------\n\nexport const DependencyTreeSchema = z.object({\n /** Project / root package name */\n root: z.string(),\n /** Absolute path to the manifest file that was parsed */\n manifest: z.string(),\n /** All resolved dependency nodes keyed by \"name@version\" */\n nodes: z.map(z.string(), DependencyNodeSchema),\n /** Count of direct dependencies (depth === 0) */\n totalDirect: z.number().int().min(0),\n /** Count of transitive dependencies (depth > 0) */\n totalTransitive: z.number().int().min(0),\n});\n\nexport type DependencyTree = z.infer<typeof DependencyTreeSchema>;\n\n// ---------------------------------------------------------------------------\n// CollectorResult<T> — generic wrapper for any data-fetching operation\n// ---------------------------------------------------------------------------\n\nexport const CollectorStatusEnum = z.enum([\"success\", \"error\", \"cached\", \"offline\"]);\nexport type CollectorStatus = z.infer<typeof CollectorStatusEnum>;\n\nexport function CollectorResultSchema<T extends z.ZodTypeAny>(dataSchema: T) {\n return z.object({\n status: CollectorStatusEnum,\n data: dataSchema.nullable(),\n error: z.string().optional(),\n collectedAt: z.string().datetime().optional(),\n });\n}\n\nexport interface CollectorResult<T> {\n status: CollectorStatus;\n data: T | null;\n error?: string;\n collectedAt?: string;\n}\n\n// ---------------------------------------------------------------------------\n// RegistryData\n// ---------------------------------------------------------------------------\n\nexport const RegistryDataSchema = z.object({\n /** Package name */\n packageName: z.string(),\n /** Resolved version string */\n version: z.string(),\n /** Short description from the registry */\n description: z.string().nullable(),\n /** ISO-8601 timestamp of the last publish, null if unknown */\n lastPublishDate: z.string().nullable(),\n /** Total number of published versions */\n versionCount: z.number().int().min(0),\n /** Deprecation message string, null if not deprecated */\n deprecated: z.string().nullable(),\n /** Downloads in the last 7 days */\n weeklyDownloads: z.number().int().min(0),\n /** SPDX license identifier from the registry */\n license: z.string().nullable(),\n /** Normalised repository URL */\n repositoryUrl: z.string().nullable(),\n});\n\nexport type RegistryData = z.infer<typeof RegistryDataSchema>;\n\n// ---------------------------------------------------------------------------\n// GitHubData\n// ---------------------------------------------------------------------------\n\nexport const GitHubDataSchema = z.object({\n /** GitHub repository owner */\n owner: z.string(),\n /** GitHub repository name */\n repo: z.string(),\n stars: z.number().int().min(0),\n forks: z.number().int().min(0),\n openIssues: z.number().int().min(0),\n /** ISO-8601 timestamp of the last repo update */\n updatedAt: z.string(),\n /** Whether the repository is archived */\n archived: z.boolean(),\n /** Default branch name */\n defaultBranch: z.string(),\n contributorCount: z.number().int().min(0),\n /** Number of commits in the last 30 days */\n recentCommitCount: z.number().int().min(0),\n /** ISO-8601 timestamp of the most recent commit, null if unknown */\n lastCommitDate: z.string().nullable(),\n /** SHA of the most recent commit, null if unknown */\n lastCommitSha: z.string().nullable(),\n /** Whether a .github/FUNDING.yml file exists */\n hasFundingYml: z.boolean(),\n});\n\nexport type GitHubData = z.infer<typeof GitHubDataSchema>;\n\n// ---------------------------------------------------------------------------\n// SecurityData\n// ---------------------------------------------------------------------------\n\nexport const VulnerabilityEntrySchema = z.object({\n id: z.string(),\n summary: z.string().nullable(),\n severity: z.enum([\"critical\", \"high\", \"medium\", \"low\", \"unknown\"]),\n published: z.string(),\n});\n\nexport type VulnerabilityEntry = z.infer<typeof VulnerabilityEntrySchema>;\n\nexport const SecurityDataSchema = z.object({\n /** Package name */\n packageName: z.string(),\n /** Resolved version string */\n version: z.string(),\n /** Total number of known vulnerabilities */\n totalVulnerabilities: z.number().int().min(0),\n /** Vulnerability counts by severity level */\n severityCounts: z.record(z.string(), z.number().int().min(0)),\n /** ISO-8601 timestamp of the most recent vulnerability, null if none */\n latestVulnDate: z.string().nullable(),\n /** Average days from disclosure to patch, null when unknown */\n averagePatchDays: z.number().nullable(),\n /** List of individual vulnerabilities */\n vulnerabilities: z.array(VulnerabilityEntrySchema),\n});\n\nexport type SecurityData = z.infer<typeof SecurityDataSchema>;\n\n// ---------------------------------------------------------------------------\n// FundingData\n// ---------------------------------------------------------------------------\n\nexport const FundingDataSchema = z.object({\n /** Package name */\n packageName: z.string(),\n /** Whether GitHub sponsors exist (via FUNDING.yml) */\n hasSponsors: z.boolean(),\n /** Whether an OpenCollective profile is active */\n hasOpenCollective: z.boolean(),\n /** Whether the npm registry \"funding\" field is set */\n hasNpmFunding: z.boolean(),\n /** OpenCollective slug, null if none */\n openCollectiveSlug: z.string().nullable(),\n /** Number of OpenCollective backers */\n openCollectiveBackers: z.number().int().min(0),\n /** Rough USD estimate of annual funding, 0 when unknown */\n estimatedAnnualFunding: z.number().min(0),\n /** Collected funding URLs from all sources */\n fundingUrls: z.array(z.string()),\n});\n\nexport type FundingData = z.infer<typeof FundingDataSchema>;\n\n// ---------------------------------------------------------------------------\n// PopularityData\n// ---------------------------------------------------------------------------\n\nexport const DownloadTrendEnum = z.enum([\"rising\", \"stable\", \"declining\"]);\nexport type DownloadTrend = z.infer<typeof DownloadTrendEnum>;\n\nexport const PopularityDataSchema = z.object({\n /** Package name */\n packageName: z.string(),\n /** Downloads in the last 7 days */\n weeklyDownloads: z.number().int().min(0),\n /** Downloads in the last 30 days */\n monthlyDownloads: z.number().int().min(0),\n /** Download trend direction */\n trend: DownloadTrendEnum,\n /** Number of packages that depend on this one */\n dependentCount: z.number().int().min(0),\n});\n\nexport type PopularityData = z.infer<typeof PopularityDataSchema>;\n\n// ---------------------------------------------------------------------------\n// LicenseData\n// ---------------------------------------------------------------------------\n\nexport const LicenseRiskEnum = z.enum([\"safe\", \"cautious\", \"risky\", \"unknown\"]);\nexport type LicenseRisk = z.infer<typeof LicenseRiskEnum>;\n\nexport const LicenseDataSchema = z.object({\n /** Package name */\n packageName: z.string(),\n /** Resolved version string */\n version: z.string(),\n /** Raw license string from the registry */\n raw: z.string().nullable(),\n /** Normalised SPDX identifier, null if unrecognised */\n spdx: z.string().nullable(),\n /** Risk classification */\n risk: LicenseRiskEnum,\n /** Whether the license is OSI-approved */\n osiApproved: z.boolean(),\n});\n\nexport type LicenseData = z.infer<typeof LicenseDataSchema>;\n\n// ---------------------------------------------------------------------------\n// TrustMetrics (each dimension scored 0-100)\n// ---------------------------------------------------------------------------\n\nconst scoreField = z.number().min(0).max(100);\n\nexport const TrustMetricsSchema = z.object({\n security: scoreField,\n maintainer: scoreField,\n activity: scoreField,\n popularity: scoreField,\n funding: scoreField,\n license: scoreField,\n});\n\nexport type TrustMetrics = z.infer<typeof TrustMetricsSchema>;\n\n// ---------------------------------------------------------------------------\n// TrustReport (per-package output of the analysis pipeline)\n// ---------------------------------------------------------------------------\n\nexport const TrustReportSchema = z.object({\n /** Package name */\n package: z.string(),\n /** Analyzed version */\n version: z.string(),\n /** Weighted overall score 0-100 */\n trustScore: scoreField,\n /** Breakdown by dimension */\n metrics: TrustMetricsSchema,\n /** True when the package shows signs of abandonment */\n isZombie: z.boolean(),\n /** Number of project files that import this package */\n blastRadius: z.number().int().min(0),\n /** Suggested replacement packages if the score is low */\n alternatives: z.array(z.string()),\n /** Download trend for quick triage */\n trend: DownloadTrendEnum,\n /** Probability (0-1) that the package name is a typosquat */\n typosquatRisk: z.number().min(0).max(1),\n});\n\nexport type TrustReport = z.infer<typeof TrustReportSchema>;\n\n// ---------------------------------------------------------------------------\n// ScanResult (top-level output of a full scan)\n// ---------------------------------------------------------------------------\n\nexport const ScanResultSchema = z.object({\n tree: DependencyTreeSchema,\n reports: z.array(TrustReportSchema),\n /** Weighted average of all package trust scores */\n overallScore: scoreField,\n /** Human-readable summary paragraph */\n summary: z.string(),\n});\n\nexport type ScanResult = z.infer<typeof ScanResultSchema>;\n\n// ---------------------------------------------------------------------------\n// Config (user-facing configuration via cosmiconfig / .dep-oraclerc etc.)\n// ---------------------------------------------------------------------------\n\nexport const ConfigSchema = z.object({\n /** Minimum trust score before a warning is emitted */\n minTrustScore: z.number().min(0).max(100).default(50),\n\n /** How long collector responses are cached, in seconds */\n cacheTtl: z.number().int().min(0).default(86_400),\n\n /** GitHub personal access token (increases rate limit) */\n githubToken: z.string().optional(),\n\n /** Packages to exclude from scanning */\n ignore: z.array(z.string()).default([]),\n\n /** Weight overrides for the trust-score dimensions (must sum to ~1) */\n weights: z\n .object({\n security: z.number().min(0).max(1).default(0.30),\n maintainer: z.number().min(0).max(1).default(0.20),\n activity: z.number().min(0).max(1).default(0.15),\n popularity: z.number().min(0).max(1).default(0.15),\n funding: z.number().min(0).max(1).default(0.10),\n license: z.number().min(0).max(1).default(0.10),\n })\n .default({}),\n\n /** Maximum concurrent network requests */\n concurrency: z.number().int().min(1).max(20).default(6),\n\n /** Registries to query */\n registries: z.array(RegistryEnum).default([\"npm\"]),\n\n /** Output format */\n outputFormat: z.enum([\"table\", \"json\", \"markdown\"]).default(\"table\"),\n\n /** Days of inactivity after which a package is considered a zombie */\n zombieThresholdDays: z.number().int().min(1).default(365),\n\n /** Enable offline mode (only use cache, never hit network) */\n offline: z.boolean().default(false),\n});\n\nexport type Config = z.infer<typeof ConfigSchema>;\n\n// ---------------------------------------------------------------------------\n// Convenience factory helpers\n// ---------------------------------------------------------------------------\n\n/** Create a DependencyNode with sensible defaults. */\nexport function createDependencyNode(\n partial: Pick<DependencyNode, \"name\" | \"version\" | \"registry\"> &\n Partial<Omit<DependencyNode, \"name\" | \"version\" | \"registry\">>,\n): DependencyNode {\n return {\n depth: 0,\n isDirect: partial.depth === undefined || partial.depth === 0,\n parent: null,\n ...partial,\n };\n}\n\n/** Create an empty DependencyTree for a project. */\nexport function createDependencyTree(\n root: string,\n manifest: string,\n): DependencyTree {\n return {\n root,\n manifest,\n nodes: new Map(),\n totalDirect: 0,\n totalTransitive: 0,\n };\n}\n\n/** Wrap a successful collector response. */\nexport function collectorSuccess<T>(data: T): CollectorResult<T> {\n return { status: \"success\", data };\n}\n\n/** Wrap a failed collector response. */\nexport function collectorError<T>(error: string): CollectorResult<T> {\n return { status: \"error\", data: null, error };\n}\n\n/** Wrap a cached collector response. */\nexport function collectorCached<T>(data: T, collectedAt: string): CollectorResult<T> {\n return { status: \"cached\", data, collectedAt };\n}\n\n/** Wrap an offline collector response. */\nexport function collectorOffline<T>(): CollectorResult<T> {\n return { status: \"offline\", data: null, error: \"Network unavailable — offline mode\" };\n}\n","import type { DependencyTree } from \"./schema.js\";\n\n/**\n * Abstract base class that every manifest parser must extend.\n *\n * Each parser is responsible for a single ecosystem (npm, pypi, etc.) and\n * knows how to:\n * 1. Detect whether its manifest file exists in a given directory.\n * 2. Parse that manifest (and optional lock file) into a DependencyTree.\n */\nexport abstract class BaseParser {\n /** Human-readable name used in logs and reports (e.g. \"npm\", \"python\"). */\n abstract readonly name: string;\n\n /**\n * Return `true` when the parser's manifest file(s) exist in `dir`.\n *\n * Implementations should use `fs.access` (or equivalent) and must never\n * throw — return `false` for any I/O error.\n */\n abstract detect(dir: string): Promise<boolean>;\n\n /**\n * Parse the manifest (and optional lock file) found in `dir` and return a\n * fully populated DependencyTree.\n *\n * Implementations may throw when the manifest is present but malformed.\n */\n abstract parse(dir: string): Promise<DependencyTree>;\n}\n"],"mappings":"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","names":[]}