@dependabit/manifest 0.1.14 → 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/src/schema.ts DELETED
@@ -1,266 +0,0 @@
1
- import { z } from 'zod';
2
-
3
- // Version tracking
4
- export const ManifestVersionSchema = z.literal('1.0.0');
5
-
6
- // Access methods (HOW to retrieve/check dependency)
7
- export const AccessMethodSchema = z.enum(['context7', 'arxiv', 'openapi', 'github-api', 'http']);
8
-
9
- // Dependency types (WHAT the dependency represents)
10
- export const DependencyTypeSchema = z.enum([
11
- 'reference-implementation',
12
- 'schema',
13
- 'documentation',
14
- 'research-paper',
15
- 'api-example',
16
- 'other'
17
- ]);
18
-
19
- // Detection methods
20
- export const DetectionMethodSchema = z.enum([
21
- 'llm-analysis',
22
- 'manual',
23
- 'package-json',
24
- 'requirements-txt',
25
- 'code-comment'
26
- ]);
27
-
28
- // Severity levels
29
- export const SeveritySchema = z.enum(['breaking', 'major', 'minor']);
30
-
31
- // Authentication configuration
32
- export const AuthConfigSchema = z
33
- .object({
34
- type: z.enum(['token', 'basic', 'oauth', 'none']),
35
- // Reference to an environment variable or secret identifier.
36
- // Do NOT store raw secret values directly in the manifest.
37
- secretEnvVar: z.string().optional()
38
- })
39
- .optional();
40
-
41
- // Monitoring rules
42
- export const MonitoringRulesSchema = z.object({
43
- enabled: z.boolean().default(true),
44
- checkFrequency: z.enum(['hourly', 'daily', 'weekly', 'monthly']).default('daily'),
45
- ignoreChanges: z.boolean().default(false),
46
- severityOverride: SeveritySchema.optional()
47
- });
48
-
49
- // Individual dependency entry
50
- export const DependencyEntrySchema = z.object({
51
- id: z.string().uuid(),
52
- url: z.string().url(),
53
- type: DependencyTypeSchema,
54
- accessMethod: AccessMethodSchema,
55
- name: z.string(),
56
- description: z.string().optional(),
57
-
58
- // Version/state tracking
59
- currentVersion: z.string().optional(),
60
- currentStateHash: z.string(),
61
-
62
- // Metadata
63
- detectionMethod: DetectionMethodSchema,
64
- detectionConfidence: z.number().min(0).max(1),
65
- detectedAt: z.string().datetime(),
66
- lastChecked: z.string().datetime(),
67
- lastChanged: z.string().datetime().optional(),
68
-
69
- // Configuration
70
- auth: AuthConfigSchema,
71
- monitoring: MonitoringRulesSchema.optional(),
72
-
73
- // Relationships
74
- referencedIn: z.array(
75
- z.object({
76
- file: z.string(),
77
- line: z.number().optional(),
78
- context: z.string().optional()
79
- })
80
- ),
81
-
82
- // Change history
83
- changeHistory: z
84
- .array(
85
- z.object({
86
- detectedAt: z.string().datetime(),
87
- oldVersion: z.string().optional(),
88
- newVersion: z.string().optional(),
89
- severity: SeveritySchema,
90
- issueNumber: z.number().optional(),
91
- falsePositive: z.boolean().default(false)
92
- })
93
- )
94
- .default([])
95
- });
96
-
97
- // Complete manifest
98
- export const DependencyManifestSchema = z.object({
99
- version: ManifestVersionSchema,
100
- generatedAt: z.string().datetime(),
101
- generatedBy: z.object({
102
- action: z.string(),
103
- version: z.string(),
104
- llmProvider: z.string(),
105
- llmModel: z.string().optional()
106
- }),
107
-
108
- repository: z.object({
109
- owner: z.string(),
110
- name: z.string(),
111
- branch: z.string(),
112
- commit: z.string()
113
- }),
114
-
115
- dependencies: z.array(DependencyEntrySchema),
116
-
117
- statistics: z.object({
118
- totalDependencies: z.number(),
119
- byType: z.record(z.string(), z.number()),
120
- byAccessMethod: z.record(z.string(), z.number()),
121
- byDetectionMethod: z.record(z.string(), z.number()),
122
- averageConfidence: z.number(),
123
- falsePositiveRate: z.number().min(0).max(1).optional()
124
- })
125
- });
126
-
127
- // Schedule configuration (dependabot-compatible)
128
- export const ScheduleSchema = z.object({
129
- interval: z.enum(['hourly', 'daily', 'weekly', 'monthly']),
130
- day: z
131
- .enum(['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'])
132
- .optional(),
133
- time: z
134
- .string()
135
- .regex(/^([01]\d|2[0-3]):([0-5]\d)$/)
136
- .optional(),
137
- timezone: z.string().default('UTC')
138
- });
139
-
140
- // LLM provider configuration
141
- export const LLMConfigSchema = z.object({
142
- provider: z
143
- .enum(['github-copilot', 'claude', 'openai', 'azure-openai'])
144
- .default('github-copilot'),
145
- model: z.string().optional(),
146
- maxTokens: z.number().int().positive().default(4000),
147
- temperature: z.number().min(0).max(2).default(0.3)
148
- });
149
-
150
- // Issue configuration
151
- export const IssueConfigSchema = z.object({
152
- labels: z.array(z.string()).default(['dependabit', 'dependency-update']),
153
- assignees: z.array(z.string()).default([]),
154
- aiAgentAssignment: z
155
- .object({
156
- enabled: z.boolean().default(false),
157
- breaking: z.string().optional(),
158
- major: z.string().optional(),
159
- minor: z.string().optional()
160
- })
161
- .optional(),
162
- titleTemplate: z.string().default('[dependabit] {name}: {change}'),
163
- bodyTemplate: z.string().optional()
164
- });
165
-
166
- // Per-dependency override
167
- export const DependencyOverrideSchema = z.object({
168
- url: z.string().url(),
169
- schedule: ScheduleSchema.optional(),
170
- monitoring: MonitoringRulesSchema.optional(),
171
- issues: IssueConfigSchema.optional()
172
- });
173
-
174
- // Complete configuration
175
- export const DependabitConfigSchema = z.object({
176
- version: z.literal('1'),
177
-
178
- // Global settings
179
- llm: LLMConfigSchema.optional(),
180
- schedule: ScheduleSchema.default({ interval: 'daily', timezone: 'UTC' }),
181
- issues: IssueConfigSchema.optional(),
182
-
183
- // Monitoring behavior
184
- monitoring: z
185
- .object({
186
- enabled: z.boolean().default(true),
187
- autoUpdate: z.boolean().default(true),
188
- falsePositiveThreshold: z.number().min(0).max(1).default(0.1)
189
- })
190
- .optional(),
191
-
192
- // Dependency-specific overrides
193
- dependencies: z.array(DependencyOverrideSchema).optional(),
194
-
195
- // Exclusions
196
- ignore: z
197
- .object({
198
- urls: z.array(z.string()).optional(),
199
- types: z.array(DependencyTypeSchema).optional(),
200
- patterns: z.array(z.string()).optional(),
201
- useGitExcludes: z.boolean().default(true)
202
- })
203
- .optional()
204
- });
205
-
206
- // Change detection schemas
207
- export const ChangeTypeSchema = z.enum([
208
- 'version-bump',
209
- 'content-changed',
210
- 'released',
211
- 'deprecated',
212
- 'unavailable',
213
- 'unknown'
214
- ]);
215
-
216
- export const ChangeDetectionRecordSchema = z.object({
217
- id: z.string().uuid(),
218
- timestamp: z.string().datetime(),
219
-
220
- // Dependency reference
221
- dependencyId: z.string().uuid(),
222
- dependencyUrl: z.string().url(),
223
- dependencyName: z.string(),
224
-
225
- // Change details
226
- changeType: ChangeTypeSchema,
227
- severity: SeveritySchema,
228
-
229
- // State comparison
230
- oldState: z.object({
231
- version: z.string().optional(),
232
- hash: z.string(),
233
- checkedAt: z.string().datetime()
234
- }),
235
- newState: z.object({
236
- version: z.string().optional(),
237
- hash: z.string(),
238
- checkedAt: z.string().datetime()
239
- }),
240
-
241
- // Change description
242
- summary: z.string(),
243
- details: z.string().optional(),
244
- breakingChanges: z.array(z.string()).optional(),
245
-
246
- // Action taken
247
- issueCreated: z.boolean().default(false),
248
- issueNumber: z.number().optional(),
249
- issueUrl: z.string().url().optional()
250
- });
251
-
252
- // TypeScript types
253
- export type DependencyManifest = z.infer<typeof DependencyManifestSchema>;
254
- export type DependencyEntry = z.infer<typeof DependencyEntrySchema>;
255
- export type DependencyType = z.infer<typeof DependencyTypeSchema>;
256
- export type AccessMethod = z.infer<typeof AccessMethodSchema>;
257
- export type DetectionMethod = z.infer<typeof DetectionMethodSchema>;
258
- export type Severity = z.infer<typeof SeveritySchema>;
259
- export type MonitoringRules = z.infer<typeof MonitoringRulesSchema>;
260
- export type DependabitConfig = z.infer<typeof DependabitConfigSchema>;
261
- export type Schedule = z.infer<typeof ScheduleSchema>;
262
- export type LLMConfig = z.infer<typeof LLMConfigSchema>;
263
- export type IssueConfig = z.infer<typeof IssueConfigSchema>;
264
- export type DependencyOverride = z.infer<typeof DependencyOverrideSchema>;
265
- export type ChangeType = z.infer<typeof ChangeTypeSchema>;
266
- export type ChangeDetectionRecord = z.infer<typeof ChangeDetectionRecordSchema>;
@@ -1,246 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import {
3
- checkManifestSize,
4
- formatSize,
5
- validateManifestObject,
6
- estimateEntrySize,
7
- canAddEntry
8
- } from './size-check.js';
9
-
10
- describe('checkManifestSize', () => {
11
- it('should return ok status for small content', () => {
12
- const content = 'small content';
13
- const result = checkManifestSize(content);
14
-
15
- expect(result.status).toBe('ok');
16
- expect(result.message).toBeUndefined();
17
- });
18
-
19
- it('should return warning status when exceeding warn threshold', () => {
20
- const content = Buffer.alloc(1.5 * 1024 * 1024); // 1.5 MB
21
- const result = checkManifestSize(content);
22
-
23
- expect(result.status).toBe('warning');
24
- expect(result.message).toContain('approaching limit');
25
- });
26
-
27
- it('should return error status when exceeding error threshold', () => {
28
- const content = Buffer.alloc(11 * 1024 * 1024); // 11 MB
29
- const result = checkManifestSize(content);
30
-
31
- expect(result.status).toBe('error');
32
- expect(result.message).toContain('exceeds maximum limit');
33
- });
34
-
35
- it('should handle exact threshold values', () => {
36
- const exactWarnSize = 1 * 1024 * 1024; // Exactly 1 MB
37
- const result = checkManifestSize(Buffer.alloc(exactWarnSize));
38
-
39
- expect(result.status).toBe('warning');
40
- });
41
-
42
- it('should support custom thresholds', () => {
43
- const content = Buffer.alloc(2.5 * 1024 * 1024); // 2.5 MB
44
- const result = checkManifestSize(content, {
45
- warnThreshold: 2,
46
- errorThreshold: 5
47
- });
48
-
49
- expect(result.status).toBe('warning');
50
- });
51
-
52
- it('should handle empty content', () => {
53
- const result = checkManifestSize('');
54
-
55
- expect(result.status).toBe('ok');
56
- expect(result.sizeBytes).toBe(0);
57
- expect(result.sizeMB).toBe(0);
58
- });
59
-
60
- it('should handle Buffer input', () => {
61
- const buffer = Buffer.from('test content');
62
- const result = checkManifestSize(buffer);
63
-
64
- expect(result.sizeBytes).toBe(buffer.length);
65
- expect(result.status).toBe('ok');
66
- });
67
-
68
- it('should handle string input with multi-byte characters', () => {
69
- const content = '你好世界🌍'; // Multi-byte UTF-8 characters
70
- const result = checkManifestSize(content);
71
-
72
- expect(result.sizeBytes).toBe(Buffer.byteLength(content, 'utf8'));
73
- });
74
- });
75
-
76
- describe('formatSize', () => {
77
- it('should format bytes correctly', () => {
78
- expect(formatSize(512)).toBe('512 B');
79
- });
80
-
81
- it('should format kilobytes correctly', () => {
82
- expect(formatSize(1024)).toBe('1.00 KB');
83
- expect(formatSize(5 * 1024)).toBe('5.00 KB');
84
- });
85
-
86
- it('should format megabytes correctly', () => {
87
- expect(formatSize(1024 * 1024)).toBe('1.00 MB');
88
- expect(formatSize(2.5 * 1024 * 1024)).toBe('2.50 MB');
89
- });
90
-
91
- it('should handle zero', () => {
92
- expect(formatSize(0)).toBe('0 B');
93
- });
94
-
95
- it('should handle large values', () => {
96
- expect(formatSize(100 * 1024 * 1024)).toBe('100.00 MB');
97
- });
98
- });
99
-
100
- describe('validateManifestObject', () => {
101
- it('should validate small manifest objects', () => {
102
- const manifest = { dependencies: [{ id: '1', name: 'test' }] };
103
- const result = validateManifestObject(manifest);
104
-
105
- expect(result.status).toBe('ok');
106
- });
107
-
108
- it('should detect large manifest objects', () => {
109
- const largeDeps = Array.from({ length: 10000 }, (_, i) => ({
110
- id: `dep-${i}`,
111
- name: `dependency-${i}`,
112
- url: `https://github.com/org/repo-${i}`,
113
- description: 'A'.repeat(100)
114
- }));
115
-
116
- const manifest = { dependencies: largeDeps };
117
- const result = validateManifestObject(manifest);
118
-
119
- expect(result.status).not.toBe('ok');
120
- });
121
-
122
- it('should handle empty objects', () => {
123
- const result = validateManifestObject({});
124
-
125
- expect(result.status).toBe('ok');
126
- });
127
-
128
- it('should support custom thresholds', () => {
129
- const manifest = { data: 'x'.repeat(500 * 1024) }; // ~500 KB
130
- const result = validateManifestObject(manifest, {
131
- warnThreshold: 0.4,
132
- errorThreshold: 1
133
- });
134
-
135
- expect(result.status).toBe('warning');
136
- });
137
- });
138
-
139
- describe('estimateEntrySize', () => {
140
- it('should estimate size of simple entries', () => {
141
- const entry = { id: '1', name: 'test' };
142
- const size = estimateEntrySize(entry);
143
-
144
- expect(size).toBeGreaterThan(0);
145
- expect(size).toBe(JSON.stringify(entry).length);
146
- });
147
-
148
- it('should estimate size of complex entries', () => {
149
- const entry = {
150
- id: '1',
151
- name: 'complex-dependency',
152
- metadata: {
153
- version: '1.0.0',
154
- tags: ['tag1', 'tag2', 'tag3'],
155
- description: 'A long description with multiple words'
156
- }
157
- };
158
-
159
- const size = estimateEntrySize(entry);
160
- expect(size).toBeGreaterThan(50);
161
- });
162
-
163
- it('should handle null', () => {
164
- expect(estimateEntrySize(null)).toBe(4); // "null"
165
- });
166
-
167
- it('should handle arrays', () => {
168
- const entry = [1, 2, 3];
169
- const size = estimateEntrySize(entry);
170
- expect(size).toBe(JSON.stringify(entry).length);
171
- });
172
- });
173
-
174
- describe('canAddEntry', () => {
175
- it('should allow adding small entries to small manifests', () => {
176
- const manifest = { dependencies: [] };
177
- const entry = { id: '1', name: 'test' };
178
-
179
- const result = canAddEntry(manifest, entry);
180
-
181
- expect(result.canAdd).toBe(true);
182
- expect(result.currentSize.status).toBe('ok');
183
- });
184
-
185
- it('should prevent adding entries when it would exceed limit', () => {
186
- // Create a manifest that's already close to the limit
187
- const largeDeps = Array.from({ length: 10000 }, (_, i) => ({
188
- id: `dep-${i}`,
189
- url: `https://example.com/${i}`,
190
- description: 'A'.repeat(800) // ~800 bytes each, total ~8MB
191
- }));
192
-
193
- const manifest = { dependencies: largeDeps };
194
- const newEntry = {
195
- id: 'new-dep',
196
- url: 'https://example.com/new',
197
- description: 'B'.repeat(3000000) // Very large entry ~3MB
198
- };
199
-
200
- const result = canAddEntry(manifest, newEntry, {
201
- errorThreshold: 10
202
- });
203
-
204
- expect(result.canAdd).toBe(false);
205
- expect(result.estimatedSize.message).toContain('exceed size limit');
206
- });
207
-
208
- it('should show warning status when approaching limit', () => {
209
- const deps = Array.from({ length: 1000 }, (_, i) => ({
210
- id: `dep-${i}`,
211
- data: 'x'.repeat(900) // Each ~900 bytes
212
- }));
213
-
214
- const manifest = { dependencies: deps };
215
- const entry = { id: 'new', data: 'y'.repeat(100) };
216
-
217
- const result = canAddEntry(manifest, entry, {
218
- warnThreshold: 0.8,
219
- errorThreshold: 10
220
- });
221
-
222
- expect(result.canAdd).toBe(true);
223
- expect(result.estimatedSize.status).toBe('warning');
224
- });
225
-
226
- it('should handle adding entry to empty manifest', () => {
227
- const manifest = {};
228
- const entry = { id: '1', name: 'first' };
229
-
230
- const result = canAddEntry(manifest, entry);
231
-
232
- expect(result.canAdd).toBe(true);
233
- });
234
-
235
- it('should account for JSON formatting overhead', () => {
236
- const manifest = { dependencies: [{ id: '1' }] };
237
- const entry = { id: '2' };
238
-
239
- const result = canAddEntry(manifest, entry);
240
-
241
- // Estimated size should be larger than current + entry due to formatting buffer
242
- expect(result.estimatedSize.sizeBytes).toBeGreaterThan(
243
- result.currentSize.sizeBytes + estimateEntrySize(entry)
244
- );
245
- });
246
- });
package/src/size-check.ts DELETED
@@ -1,124 +0,0 @@
1
- /**
2
- * Manifest size validation and warnings
3
- * Checks manifest size and warns when approaching limits
4
- */
5
-
6
- export interface SizeCheckResult {
7
- sizeBytes: number;
8
- sizeMB: number;
9
- status: 'ok' | 'warning' | 'error';
10
- message?: string | undefined;
11
- }
12
-
13
- export interface SizeCheckOptions {
14
- warnThreshold?: number; // MB (default: 1)
15
- errorThreshold?: number; // MB (default: 10)
16
- }
17
-
18
- /**
19
- * Check manifest size and return status
20
- */
21
- export function checkManifestSize(
22
- content: string | Buffer,
23
- options?: SizeCheckOptions
24
- ): SizeCheckResult {
25
- const warnThreshold = (options?.warnThreshold ?? 1) * 1024 * 1024; // Convert MB to bytes
26
- const errorThreshold = (options?.errorThreshold ?? 10) * 1024 * 1024;
27
-
28
- const sizeBytes =
29
- typeof content === 'string' ? Buffer.byteLength(content, 'utf8') : content.length;
30
-
31
- const sizeMB = sizeBytes / (1024 * 1024);
32
-
33
- if (sizeBytes >= errorThreshold) {
34
- return {
35
- sizeBytes,
36
- sizeMB,
37
- status: 'error',
38
- message: `Manifest size (${sizeMB.toFixed(2)}MB) exceeds maximum limit of ${(errorThreshold / 1024 / 1024).toFixed(0)}MB. Consider splitting or pruning data.`
39
- };
40
- }
41
-
42
- if (sizeBytes >= warnThreshold) {
43
- return {
44
- sizeBytes,
45
- sizeMB,
46
- status: 'warning',
47
- message: `Manifest size (${sizeMB.toFixed(2)}MB) is approaching limit. Warning threshold: ${(warnThreshold / 1024 / 1024).toFixed(0)}MB, Max: ${(errorThreshold / 1024 / 1024).toFixed(0)}MB.`
48
- };
49
- }
50
-
51
- return {
52
- sizeBytes,
53
- sizeMB,
54
- status: 'ok'
55
- };
56
- }
57
-
58
- /**
59
- * Get formatted size string
60
- */
61
- export function formatSize(bytes: number): string {
62
- if (bytes < 1024) {
63
- return `${bytes} B`;
64
- }
65
- if (bytes < 1024 * 1024) {
66
- return `${(bytes / 1024).toFixed(2)} KB`;
67
- }
68
- return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
69
- }
70
-
71
- /**
72
- * Validate manifest object size before serialization
73
- */
74
- export function validateManifestObject(
75
- manifest: unknown,
76
- options?: SizeCheckOptions
77
- ): SizeCheckResult {
78
- const serialized = JSON.stringify(manifest, null, 2);
79
- return checkManifestSize(serialized, options);
80
- }
81
-
82
- /**
83
- * Estimate manifest size impact of adding an entry
84
- */
85
- export function estimateEntrySize(entry: unknown): number {
86
- const serialized = JSON.stringify(entry);
87
- return Buffer.byteLength(serialized, 'utf8');
88
- }
89
-
90
- /**
91
- * Check if adding an entry would exceed limits
92
- */
93
- export function canAddEntry(
94
- currentManifest: unknown,
95
- newEntry: unknown,
96
- options?: SizeCheckOptions
97
- ): {
98
- canAdd: boolean;
99
- currentSize: SizeCheckResult;
100
- estimatedSize: SizeCheckResult;
101
- } {
102
- const currentSize = validateManifestObject(currentManifest, options);
103
- const entrySize = estimateEntrySize(newEntry);
104
-
105
- // Estimate new size (accounting for JSON formatting)
106
- const estimatedBytes = currentSize.sizeBytes + entrySize + 100; // Add buffer for formatting
107
- const estimatedSizeMB = estimatedBytes / (1024 * 1024);
108
-
109
- const errorThreshold = (options?.errorThreshold ?? 10) * 1024 * 1024;
110
- const canAdd = estimatedBytes < errorThreshold;
111
-
112
- const estimatedResult = checkManifestSize(Buffer.alloc(estimatedBytes), options);
113
-
114
- return {
115
- canAdd,
116
- currentSize,
117
- estimatedSize: {
118
- ...estimatedResult,
119
- message: canAdd
120
- ? estimatedResult.message
121
- : `Adding entry would exceed size limit (estimated: ${estimatedSizeMB.toFixed(2)}MB)`
122
- }
123
- };
124
- }