@dependabit/manifest 0.1.13 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/config.d.ts +66 -6
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +66 -6
- package/dist/config.js.map +1 -1
- package/dist/manifest.d.ts +131 -8
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +131 -8
- package/dist/manifest.js.map +1 -1
- package/dist/schema.d.ts +129 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +42 -0
- package/dist/schema.js.map +1 -1
- package/dist/size-check.js.map +1 -1
- package/dist/validator.d.ts +7 -1
- package/dist/validator.d.ts.map +1 -1
- package/dist/validator.js +7 -1
- package/dist/validator.js.map +1 -1
- package/package.json +25 -8
- package/src/config.test.ts +0 -266
- package/src/config.ts +0 -96
- package/src/index.ts +0 -16
- package/src/manifest.test.ts +0 -400
- package/src/manifest.ts +0 -278
- package/src/schema.test.ts +0 -293
- package/src/schema.ts +0 -266
- package/src/size-check.test.ts +0 -246
- package/src/size-check.ts +0 -124
- package/src/validator.test.ts +0 -161
- package/src/validator.ts +0 -131
- package/tsconfig.json +0 -10
- package/tsconfig.tsbuildinfo +0 -1
package/src/manifest.ts
DELETED
|
@@ -1,278 +0,0 @@
|
|
|
1
|
-
import { readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
2
|
-
import { dirname } from 'node:path';
|
|
3
|
-
import { type DependencyManifest, type DependencyEntry } from './schema.js';
|
|
4
|
-
import { validateManifest, validateDependencyEntry, safeValidateManifest } from './validator.js';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Read and parse a manifest file
|
|
8
|
-
*/
|
|
9
|
-
export async function readManifest(path: string): Promise<DependencyManifest> {
|
|
10
|
-
const content = await readFile(path, 'utf-8');
|
|
11
|
-
const data = JSON.parse(content);
|
|
12
|
-
return validateManifest(data);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Write a manifest to file
|
|
17
|
-
*/
|
|
18
|
-
export async function writeManifest(
|
|
19
|
-
path: string,
|
|
20
|
-
manifest: DependencyManifest,
|
|
21
|
-
options?: { strict?: boolean }
|
|
22
|
-
): Promise<{ validationErrors?: string[] }> {
|
|
23
|
-
const strict = options?.strict ?? false;
|
|
24
|
-
const result: { validationErrors?: string[] } = {};
|
|
25
|
-
|
|
26
|
-
// Validate before writing
|
|
27
|
-
const validation = safeValidateManifest(manifest);
|
|
28
|
-
if (!validation.success) {
|
|
29
|
-
const errors = validation.error!.getFormattedErrors();
|
|
30
|
-
if (strict) {
|
|
31
|
-
throw validation.error!;
|
|
32
|
-
}
|
|
33
|
-
// Non-strict: record warnings but still write the manifest
|
|
34
|
-
result.validationErrors = errors;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Ensure directory exists
|
|
38
|
-
await mkdir(dirname(path), { recursive: true });
|
|
39
|
-
|
|
40
|
-
// Write formatted JSON
|
|
41
|
-
const content = JSON.stringify(manifest, null, 2);
|
|
42
|
-
await writeFile(path, content, 'utf-8');
|
|
43
|
-
|
|
44
|
-
return result;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Update a dependency entry in the manifest
|
|
49
|
-
*/
|
|
50
|
-
export async function updateDependency(
|
|
51
|
-
path: string,
|
|
52
|
-
dependencyId: string,
|
|
53
|
-
updates: Partial<DependencyEntry>
|
|
54
|
-
): Promise<DependencyManifest> {
|
|
55
|
-
const manifest = await readManifest(path);
|
|
56
|
-
|
|
57
|
-
const dep = manifest.dependencies.find((d) => d.id === dependencyId);
|
|
58
|
-
if (!dep) {
|
|
59
|
-
throw new Error(`Dependency with id ${dependencyId} not found`);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Update the dependency in place
|
|
63
|
-
Object.assign(dep, updates);
|
|
64
|
-
|
|
65
|
-
// Validate the merged dependency
|
|
66
|
-
validateDependencyEntry(dep);
|
|
67
|
-
|
|
68
|
-
// Update statistics
|
|
69
|
-
manifest.statistics = calculateStatistics(manifest.dependencies);
|
|
70
|
-
|
|
71
|
-
// Write back
|
|
72
|
-
await writeManifest(path, manifest);
|
|
73
|
-
|
|
74
|
-
return manifest;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Add a new dependency to the manifest
|
|
79
|
-
*/
|
|
80
|
-
export async function addDependency(
|
|
81
|
-
path: string,
|
|
82
|
-
dependency: DependencyEntry
|
|
83
|
-
): Promise<DependencyManifest> {
|
|
84
|
-
const manifest = await readManifest(path);
|
|
85
|
-
|
|
86
|
-
// Check for duplicates by ID or URL
|
|
87
|
-
const existingById = manifest.dependencies.find((dep) => dep.id === dependency.id);
|
|
88
|
-
const existingByUrl = manifest.dependencies.find((dep) => dep.url === dependency.url);
|
|
89
|
-
|
|
90
|
-
if (existingById) {
|
|
91
|
-
throw new Error(`Dependency with id ${dependency.id} already exists`);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (existingByUrl) {
|
|
95
|
-
throw new Error(`Dependency with url ${dependency.url} already exists`);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Add dependency
|
|
99
|
-
manifest.dependencies.push(dependency);
|
|
100
|
-
|
|
101
|
-
// Update statistics
|
|
102
|
-
manifest.statistics = calculateStatistics(manifest.dependencies);
|
|
103
|
-
|
|
104
|
-
// Write back
|
|
105
|
-
await writeManifest(path, manifest);
|
|
106
|
-
|
|
107
|
-
return manifest;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Remove a dependency from the manifest
|
|
112
|
-
*/
|
|
113
|
-
export async function removeDependency(
|
|
114
|
-
path: string,
|
|
115
|
-
dependencyId: string
|
|
116
|
-
): Promise<DependencyManifest> {
|
|
117
|
-
const manifest = await readManifest(path);
|
|
118
|
-
|
|
119
|
-
const index = manifest.dependencies.findIndex((dep) => dep.id === dependencyId);
|
|
120
|
-
if (index === -1) {
|
|
121
|
-
throw new Error(`Dependency with id ${dependencyId} not found`);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// Remove dependency
|
|
125
|
-
manifest.dependencies.splice(index, 1);
|
|
126
|
-
|
|
127
|
-
// Update statistics
|
|
128
|
-
manifest.statistics = calculateStatistics(manifest.dependencies);
|
|
129
|
-
|
|
130
|
-
// Write back
|
|
131
|
-
await writeManifest(path, manifest);
|
|
132
|
-
|
|
133
|
-
return manifest;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Merge two manifests, preserving manual entries
|
|
138
|
-
* Manual entries are those with detectionMethod === 'manual'
|
|
139
|
-
*/
|
|
140
|
-
export function mergeManifests(
|
|
141
|
-
existing: DependencyManifest,
|
|
142
|
-
updated: DependencyManifest,
|
|
143
|
-
options: {
|
|
144
|
-
preserveManual?: boolean;
|
|
145
|
-
preserveHistory?: boolean;
|
|
146
|
-
} = {}
|
|
147
|
-
): DependencyManifest {
|
|
148
|
-
const { preserveManual = true, preserveHistory = true } = options;
|
|
149
|
-
|
|
150
|
-
// Create a deep copy of the updated manifest to avoid mutations
|
|
151
|
-
const merged: DependencyManifest = {
|
|
152
|
-
...updated,
|
|
153
|
-
dependencies: updated.dependencies.map((dep) => ({
|
|
154
|
-
...dep,
|
|
155
|
-
changeHistory: dep.changeHistory ? [...dep.changeHistory] : [],
|
|
156
|
-
referencedIn: dep.referencedIn ? [...dep.referencedIn] : []
|
|
157
|
-
}))
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
if (preserveManual) {
|
|
161
|
-
// Find manual entries in existing manifest
|
|
162
|
-
const manualEntries = existing.dependencies.filter((dep) => dep.detectionMethod === 'manual');
|
|
163
|
-
|
|
164
|
-
// Add manual entries that aren't in the updated manifest
|
|
165
|
-
for (const manualEntry of manualEntries) {
|
|
166
|
-
const existsInUpdated = merged.dependencies.some(
|
|
167
|
-
(dep) => dep.id === manualEntry.id || dep.url === manualEntry.url
|
|
168
|
-
);
|
|
169
|
-
|
|
170
|
-
if (!existsInUpdated) {
|
|
171
|
-
merged.dependencies.push({
|
|
172
|
-
...manualEntry,
|
|
173
|
-
changeHistory: manualEntry.changeHistory ? [...manualEntry.changeHistory] : [],
|
|
174
|
-
referencedIn: manualEntry.referencedIn ? [...manualEntry.referencedIn] : []
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
if (preserveHistory) {
|
|
181
|
-
// Preserve change history for matching dependencies
|
|
182
|
-
merged.dependencies = merged.dependencies.map((dep) => {
|
|
183
|
-
const existingDep = existing.dependencies.find((d) => d.id === dep.id || d.url === dep.url);
|
|
184
|
-
|
|
185
|
-
if (existingDep && existingDep.changeHistory && existingDep.changeHistory.length > 0) {
|
|
186
|
-
return {
|
|
187
|
-
...dep,
|
|
188
|
-
changeHistory: [...existingDep.changeHistory, ...(dep.changeHistory || [])]
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
return dep;
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// Recalculate statistics
|
|
197
|
-
merged.statistics = calculateStatistics(merged.dependencies);
|
|
198
|
-
|
|
199
|
-
return merged;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* Calculate statistics for a list of dependencies
|
|
204
|
-
*/
|
|
205
|
-
function calculateStatistics(dependencies: DependencyEntry[]): DependencyManifest['statistics'] {
|
|
206
|
-
const byType: Record<string, number> = {};
|
|
207
|
-
const byAccessMethod: Record<string, number> = {};
|
|
208
|
-
const byDetectionMethod: Record<string, number> = {};
|
|
209
|
-
let totalConfidence = 0;
|
|
210
|
-
let falsePositiveCount = 0;
|
|
211
|
-
let totalChangeCount = 0;
|
|
212
|
-
|
|
213
|
-
for (const dep of dependencies) {
|
|
214
|
-
byType[dep.type] = (byType[dep.type] || 0) + 1;
|
|
215
|
-
byAccessMethod[dep.accessMethod] = (byAccessMethod[dep.accessMethod] || 0) + 1;
|
|
216
|
-
byDetectionMethod[dep.detectionMethod] = (byDetectionMethod[dep.detectionMethod] || 0) + 1;
|
|
217
|
-
totalConfidence += dep.detectionConfidence;
|
|
218
|
-
|
|
219
|
-
// Count false positives in change history
|
|
220
|
-
const changeHistory = dep.changeHistory || [];
|
|
221
|
-
const fpCount = changeHistory.filter((change) => change.falsePositive).length;
|
|
222
|
-
falsePositiveCount += fpCount;
|
|
223
|
-
totalChangeCount += changeHistory.length;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
const averageConfidence = dependencies.length > 0 ? totalConfidence / dependencies.length : 0;
|
|
227
|
-
|
|
228
|
-
const falsePositiveRate =
|
|
229
|
-
totalChangeCount > 0 ? falsePositiveCount / totalChangeCount : undefined;
|
|
230
|
-
|
|
231
|
-
return {
|
|
232
|
-
totalDependencies: dependencies.length,
|
|
233
|
-
byType,
|
|
234
|
-
byAccessMethod,
|
|
235
|
-
byDetectionMethod,
|
|
236
|
-
averageConfidence,
|
|
237
|
-
falsePositiveRate
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* Create an empty manifest template
|
|
243
|
-
*/
|
|
244
|
-
export function createEmptyManifest(options: {
|
|
245
|
-
owner: string;
|
|
246
|
-
name: string;
|
|
247
|
-
branch: string;
|
|
248
|
-
commit: string;
|
|
249
|
-
action?: string;
|
|
250
|
-
version?: string;
|
|
251
|
-
llmProvider?: string;
|
|
252
|
-
llmModel?: string;
|
|
253
|
-
}): DependencyManifest {
|
|
254
|
-
return {
|
|
255
|
-
version: '1.0.0',
|
|
256
|
-
generatedAt: new Date().toISOString(),
|
|
257
|
-
generatedBy: {
|
|
258
|
-
action: options.action || 'dependabit',
|
|
259
|
-
version: options.version || '0.1.0',
|
|
260
|
-
llmProvider: options.llmProvider || 'github-copilot',
|
|
261
|
-
llmModel: options.llmModel
|
|
262
|
-
},
|
|
263
|
-
repository: {
|
|
264
|
-
owner: options.owner,
|
|
265
|
-
name: options.name,
|
|
266
|
-
branch: options.branch,
|
|
267
|
-
commit: options.commit
|
|
268
|
-
},
|
|
269
|
-
dependencies: [],
|
|
270
|
-
statistics: {
|
|
271
|
-
totalDependencies: 0,
|
|
272
|
-
byType: {},
|
|
273
|
-
byAccessMethod: {},
|
|
274
|
-
byDetectionMethod: {},
|
|
275
|
-
averageConfidence: 0
|
|
276
|
-
}
|
|
277
|
-
};
|
|
278
|
-
}
|
package/src/schema.test.ts
DELETED
|
@@ -1,293 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import {
|
|
3
|
-
DependencyManifestSchema,
|
|
4
|
-
DependencyEntrySchema,
|
|
5
|
-
DependabitConfigSchema,
|
|
6
|
-
AccessMethodSchema,
|
|
7
|
-
DependencyTypeSchema,
|
|
8
|
-
DetectionMethodSchema,
|
|
9
|
-
SeveritySchema
|
|
10
|
-
} from '../src/schema.js';
|
|
11
|
-
|
|
12
|
-
describe('Schema Tests', () => {
|
|
13
|
-
describe('AccessMethodSchema', () => {
|
|
14
|
-
it('should accept valid access methods', () => {
|
|
15
|
-
expect(AccessMethodSchema.parse('context7')).toBe('context7');
|
|
16
|
-
expect(AccessMethodSchema.parse('arxiv')).toBe('arxiv');
|
|
17
|
-
expect(AccessMethodSchema.parse('openapi')).toBe('openapi');
|
|
18
|
-
expect(AccessMethodSchema.parse('github-api')).toBe('github-api');
|
|
19
|
-
expect(AccessMethodSchema.parse('http')).toBe('http');
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it('should reject invalid access methods', () => {
|
|
23
|
-
expect(() => AccessMethodSchema.parse('invalid')).toThrow();
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
describe('DependencyTypeSchema', () => {
|
|
28
|
-
it('should accept valid dependency types', () => {
|
|
29
|
-
expect(DependencyTypeSchema.parse('reference-implementation')).toBe(
|
|
30
|
-
'reference-implementation'
|
|
31
|
-
);
|
|
32
|
-
expect(DependencyTypeSchema.parse('schema')).toBe('schema');
|
|
33
|
-
expect(DependencyTypeSchema.parse('documentation')).toBe('documentation');
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it('should reject invalid dependency types', () => {
|
|
37
|
-
expect(() => DependencyTypeSchema.parse('invalid')).toThrow();
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
describe('DetectionMethodSchema', () => {
|
|
42
|
-
it('should accept valid detection methods', () => {
|
|
43
|
-
expect(DetectionMethodSchema.parse('llm-analysis')).toBe('llm-analysis');
|
|
44
|
-
expect(DetectionMethodSchema.parse('manual')).toBe('manual');
|
|
45
|
-
expect(DetectionMethodSchema.parse('package-json')).toBe('package-json');
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
describe('SeveritySchema', () => {
|
|
50
|
-
it('should accept valid severity levels', () => {
|
|
51
|
-
expect(SeveritySchema.parse('breaking')).toBe('breaking');
|
|
52
|
-
expect(SeveritySchema.parse('major')).toBe('major');
|
|
53
|
-
expect(SeveritySchema.parse('minor')).toBe('minor');
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
describe('DependencyEntrySchema', () => {
|
|
58
|
-
it('should validate a complete dependency entry', () => {
|
|
59
|
-
const entry = {
|
|
60
|
-
id: '550e8400-e29b-41d4-a716-446655440000',
|
|
61
|
-
url: 'https://github.com/microsoft/TypeScript',
|
|
62
|
-
type: 'reference-implementation',
|
|
63
|
-
accessMethod: 'github-api',
|
|
64
|
-
name: 'TypeScript',
|
|
65
|
-
description: 'TypeScript compiler',
|
|
66
|
-
currentVersion: '5.9.3',
|
|
67
|
-
currentStateHash: 'sha256:abc123',
|
|
68
|
-
detectionMethod: 'package-json',
|
|
69
|
-
detectionConfidence: 1.0,
|
|
70
|
-
detectedAt: '2026-01-29T10:30:00Z',
|
|
71
|
-
lastChecked: '2026-01-29T10:30:00Z',
|
|
72
|
-
auth: undefined,
|
|
73
|
-
referencedIn: [
|
|
74
|
-
{
|
|
75
|
-
file: 'package.json',
|
|
76
|
-
line: 15,
|
|
77
|
-
context: '"typescript": "^5.9.3"'
|
|
78
|
-
}
|
|
79
|
-
],
|
|
80
|
-
changeHistory: []
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
const result = DependencyEntrySchema.parse(entry);
|
|
84
|
-
expect(result.id).toBe(entry.id);
|
|
85
|
-
expect(result.name).toBe('TypeScript');
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
it('should require all mandatory fields', () => {
|
|
89
|
-
expect(() =>
|
|
90
|
-
DependencyEntrySchema.parse({
|
|
91
|
-
url: 'https://example.com'
|
|
92
|
-
})
|
|
93
|
-
).toThrow();
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it('should validate UUID format', () => {
|
|
97
|
-
const entry = {
|
|
98
|
-
id: 'not-a-uuid',
|
|
99
|
-
url: 'https://github.com/microsoft/TypeScript',
|
|
100
|
-
type: 'reference-implementation',
|
|
101
|
-
accessMethod: 'github-api',
|
|
102
|
-
name: 'TypeScript',
|
|
103
|
-
currentStateHash: 'sha256:abc123',
|
|
104
|
-
detectionMethod: 'manual',
|
|
105
|
-
detectionConfidence: 1.0,
|
|
106
|
-
detectedAt: '2026-01-29T10:30:00Z',
|
|
107
|
-
lastChecked: '2026-01-29T10:30:00Z',
|
|
108
|
-
referencedIn: []
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
expect(() => DependencyEntrySchema.parse(entry)).toThrow();
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it('should validate URL format', () => {
|
|
115
|
-
const entry = {
|
|
116
|
-
id: '550e8400-e29b-41d4-a716-446655440000',
|
|
117
|
-
url: 'not-a-url',
|
|
118
|
-
type: 'reference-implementation',
|
|
119
|
-
accessMethod: 'github-api',
|
|
120
|
-
name: 'TypeScript',
|
|
121
|
-
currentStateHash: 'sha256:abc123',
|
|
122
|
-
detectionMethod: 'manual',
|
|
123
|
-
detectionConfidence: 1.0,
|
|
124
|
-
detectedAt: '2026-01-29T10:30:00Z',
|
|
125
|
-
lastChecked: '2026-01-29T10:30:00Z',
|
|
126
|
-
referencedIn: []
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
expect(() => DependencyEntrySchema.parse(entry)).toThrow();
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
it('should validate confidence range', () => {
|
|
133
|
-
const entry = {
|
|
134
|
-
id: '550e8400-e29b-41d4-a716-446655440000',
|
|
135
|
-
url: 'https://github.com/microsoft/TypeScript',
|
|
136
|
-
type: 'reference-implementation',
|
|
137
|
-
accessMethod: 'github-api',
|
|
138
|
-
name: 'TypeScript',
|
|
139
|
-
currentStateHash: 'sha256:abc123',
|
|
140
|
-
detectionMethod: 'manual',
|
|
141
|
-
detectionConfidence: 1.5,
|
|
142
|
-
detectedAt: '2026-01-29T10:30:00Z',
|
|
143
|
-
lastChecked: '2026-01-29T10:30:00Z',
|
|
144
|
-
referencedIn: []
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
expect(() => DependencyEntrySchema.parse(entry)).toThrow();
|
|
148
|
-
});
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
describe('DependencyManifestSchema', () => {
|
|
152
|
-
it('should validate a complete manifest', () => {
|
|
153
|
-
const manifest = {
|
|
154
|
-
version: '1.0.0',
|
|
155
|
-
generatedAt: '2026-01-29T10:30:00Z',
|
|
156
|
-
generatedBy: {
|
|
157
|
-
action: 'dependabit',
|
|
158
|
-
version: '1.0.0',
|
|
159
|
-
llmProvider: 'github-copilot',
|
|
160
|
-
llmModel: 'gpt-4'
|
|
161
|
-
},
|
|
162
|
-
repository: {
|
|
163
|
-
owner: 'pradeepmouli',
|
|
164
|
-
name: 'dependabit',
|
|
165
|
-
branch: 'main',
|
|
166
|
-
commit: 'abc123def456'
|
|
167
|
-
},
|
|
168
|
-
dependencies: [
|
|
169
|
-
{
|
|
170
|
-
id: '550e8400-e29b-41d4-a716-446655440000',
|
|
171
|
-
url: 'https://github.com/microsoft/TypeScript',
|
|
172
|
-
type: 'reference-implementation',
|
|
173
|
-
accessMethod: 'github-api',
|
|
174
|
-
name: 'TypeScript',
|
|
175
|
-
currentStateHash: 'sha256:abc123',
|
|
176
|
-
detectionMethod: 'package-json',
|
|
177
|
-
detectionConfidence: 1.0,
|
|
178
|
-
detectedAt: '2026-01-29T10:30:00Z',
|
|
179
|
-
lastChecked: '2026-01-29T10:30:00Z',
|
|
180
|
-
referencedIn: []
|
|
181
|
-
}
|
|
182
|
-
],
|
|
183
|
-
statistics: {
|
|
184
|
-
totalDependencies: 1,
|
|
185
|
-
byType: { 'reference-implementation': 1 },
|
|
186
|
-
byAccessMethod: { 'github-api': 1 },
|
|
187
|
-
byDetectionMethod: { 'package-json': 1 },
|
|
188
|
-
averageConfidence: 1.0
|
|
189
|
-
}
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
const result = DependencyManifestSchema.parse(manifest);
|
|
193
|
-
expect(result.version).toBe('1.0.0');
|
|
194
|
-
expect(result.dependencies).toHaveLength(1);
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
it('should require correct version', () => {
|
|
198
|
-
const manifest = {
|
|
199
|
-
version: '2.0.0',
|
|
200
|
-
generatedAt: '2026-01-29T10:30:00Z',
|
|
201
|
-
generatedBy: {
|
|
202
|
-
action: 'dependabit',
|
|
203
|
-
version: '1.0.0',
|
|
204
|
-
llmProvider: 'github-copilot'
|
|
205
|
-
},
|
|
206
|
-
repository: {
|
|
207
|
-
owner: 'pradeepmouli',
|
|
208
|
-
name: 'dependabit',
|
|
209
|
-
branch: 'main',
|
|
210
|
-
commit: 'abc123'
|
|
211
|
-
},
|
|
212
|
-
dependencies: [],
|
|
213
|
-
statistics: {
|
|
214
|
-
totalDependencies: 0,
|
|
215
|
-
byType: {},
|
|
216
|
-
byAccessMethod: {},
|
|
217
|
-
byDetectionMethod: {},
|
|
218
|
-
averageConfidence: 0
|
|
219
|
-
}
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
expect(() => DependencyManifestSchema.parse(manifest)).toThrow();
|
|
223
|
-
});
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
describe('DependabitConfigSchema', () => {
|
|
227
|
-
it('should validate a complete config', () => {
|
|
228
|
-
const config = {
|
|
229
|
-
version: '1',
|
|
230
|
-
llm: {
|
|
231
|
-
provider: 'github-copilot',
|
|
232
|
-
model: 'gpt-4',
|
|
233
|
-
maxTokens: 4000,
|
|
234
|
-
temperature: 0.3
|
|
235
|
-
},
|
|
236
|
-
schedule: {
|
|
237
|
-
interval: 'daily',
|
|
238
|
-
time: '02:00',
|
|
239
|
-
timezone: 'UTC'
|
|
240
|
-
},
|
|
241
|
-
issues: {
|
|
242
|
-
labels: ['dependabit', 'dependency-update'],
|
|
243
|
-
assignees: ['pradeepmouli'],
|
|
244
|
-
titleTemplate: '[dependabit] {name}: {change}'
|
|
245
|
-
},
|
|
246
|
-
monitoring: {
|
|
247
|
-
enabled: true,
|
|
248
|
-
autoUpdate: true,
|
|
249
|
-
falsePositiveThreshold: 0.1
|
|
250
|
-
}
|
|
251
|
-
};
|
|
252
|
-
|
|
253
|
-
const result = DependabitConfigSchema.parse(config);
|
|
254
|
-
expect(result.version).toBe('1');
|
|
255
|
-
expect(result.llm?.provider).toBe('github-copilot');
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
it('should apply defaults', () => {
|
|
259
|
-
const config = {
|
|
260
|
-
version: '1'
|
|
261
|
-
};
|
|
262
|
-
|
|
263
|
-
const result = DependabitConfigSchema.parse(config);
|
|
264
|
-
expect(result.schedule.interval).toBe('daily');
|
|
265
|
-
expect(result.schedule.timezone).toBe('UTC');
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
it('should validate schedule time format', () => {
|
|
269
|
-
const config = {
|
|
270
|
-
version: '1',
|
|
271
|
-
schedule: {
|
|
272
|
-
interval: 'daily',
|
|
273
|
-
time: '25:00',
|
|
274
|
-
timezone: 'UTC'
|
|
275
|
-
}
|
|
276
|
-
};
|
|
277
|
-
|
|
278
|
-
expect(() => DependabitConfigSchema.parse(config)).toThrow();
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
it('should validate LLM temperature range', () => {
|
|
282
|
-
const config = {
|
|
283
|
-
version: '1',
|
|
284
|
-
llm: {
|
|
285
|
-
provider: 'github-copilot',
|
|
286
|
-
temperature: 3.0
|
|
287
|
-
}
|
|
288
|
-
};
|
|
289
|
-
|
|
290
|
-
expect(() => DependabitConfigSchema.parse(config)).toThrow();
|
|
291
|
-
});
|
|
292
|
-
});
|
|
293
|
-
});
|