-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathplugin-versioning.zod.ts
More file actions
472 lines (411 loc) · 13 KB
/
plugin-versioning.zod.ts
File metadata and controls
472 lines (411 loc) · 13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
import { z } from 'zod';
/**
* # Plugin Versioning and Compatibility Protocol
*
* Defines comprehensive versioning, compatibility checking, and dependency
* resolution mechanisms for the plugin ecosystem.
*
* Based on semantic versioning (SemVer) with extensions for:
* - Compatibility matrices
* - Breaking change detection
* - Migration paths
* - Multi-version support
*/
/**
* Semantic Version Schema
* Standard SemVer format with optional pre-release and build metadata
*/
export const SemanticVersionSchema = z.object({
major: z.number().int().min(0).describe('Major version (breaking changes)'),
minor: z.number().int().min(0).describe('Minor version (backward compatible features)'),
patch: z.number().int().min(0).describe('Patch version (backward compatible fixes)'),
preRelease: z.string().optional().describe('Pre-release identifier (alpha, beta, rc.1)'),
build: z.string().optional().describe('Build metadata'),
}).describe('Semantic version number');
/**
* Version Constraint Schema
* Defines version requirements using SemVer ranges
*/
export const VersionConstraintSchema = z.union([
z.string().regex(/^[\d.]+$/).describe('Exact version: `1.2.3`'),
z.string().regex(/^\^[\d.]+$/).describe('Compatible with: `^1.2.3` (`>=1.2.3 <2.0.0`)'),
z.string().regex(/^~[\d.]+$/).describe('Approximately: `~1.2.3` (`>=1.2.3 <1.3.0`)'),
z.string().regex(/^>=[\d.]+$/).describe('Greater than or equal: `>=1.2.3`'),
z.string().regex(/^>[\d.]+$/).describe('Greater than: `>1.2.3`'),
z.string().regex(/^<=[\d.]+$/).describe('Less than or equal: `<=1.2.3`'),
z.string().regex(/^<[\d.]+$/).describe('Less than: `<1.2.3`'),
z.string().regex(/^[\d.]+ - [\d.]+$/).describe('Range: `1.2.3 - 2.3.4`'),
z.literal('*').describe('Any version'),
z.literal('latest').describe('Latest stable version'),
]);
/**
* Compatibility Level
* Describes the level of compatibility between versions
*/
export const CompatibilityLevelSchema = z.enum([
'fully-compatible', // 100% compatible, drop-in replacement
'backward-compatible', // Backward compatible, new features added
'deprecated-compatible', // Compatible but uses deprecated features
'breaking-changes', // Breaking changes, migration required
'incompatible', // Completely incompatible
]).describe('Compatibility level between versions');
/**
* Breaking Change
* Documents a breaking change in a version
*/
export const BreakingChangeSchema = z.object({
/**
* Version where the change was introduced
*/
introducedIn: z.string().describe('Version that introduced this breaking change'),
/**
* Type of breaking change
*/
type: z.enum([
'api-removed', // API removed
'api-renamed', // API renamed
'api-signature-changed', // Function signature changed
'behavior-changed', // Behavior changed
'dependency-changed', // Dependency requirement changed
'configuration-changed', // Configuration schema changed
'protocol-changed', // Protocol implementation changed
]),
/**
* What was changed
*/
description: z.string(),
/**
* Migration guide
*/
migrationGuide: z.string().optional().describe('How to migrate from old to new'),
/**
* Deprecated in version
*/
deprecatedIn: z.string().optional().describe('Version where old API was deprecated'),
/**
* Will be removed in version
*/
removedIn: z.string().optional().describe('Version where old API will be removed'),
/**
* Automated migration available
*/
automatedMigration: z.boolean().default(false)
.describe('Whether automated migration tool is available'),
/**
* Impact severity
*/
severity: z.enum(['critical', 'major', 'minor']).describe('Impact severity'),
});
/**
* Deprecation Notice
* Information about deprecated features
*/
export const DeprecationNoticeSchema = z.object({
/**
* Feature or API being deprecated
*/
feature: z.string().describe('Deprecated feature identifier'),
/**
* Version when deprecated
*/
deprecatedIn: z.string(),
/**
* Planned removal version
*/
removeIn: z.string().optional(),
/**
* Reason for deprecation
*/
reason: z.string(),
/**
* Recommended alternative
*/
alternative: z.string().optional().describe('What to use instead'),
/**
* Migration path
*/
migrationPath: z.string().optional().describe('How to migrate to alternative'),
});
/**
* Compatibility Matrix Entry
* Maps compatibility between different plugin versions
*/
export const CompatibilityMatrixEntrySchema = z.object({
/**
* Source version
*/
from: z.string().describe('Version being upgraded from'),
/**
* Target version
*/
to: z.string().describe('Version being upgraded to'),
/**
* Compatibility level
*/
compatibility: CompatibilityLevelSchema,
/**
* Breaking changes list
*/
breakingChanges: z.array(BreakingChangeSchema).optional(),
/**
* Migration required
*/
migrationRequired: z.boolean().default(false),
/**
* Migration complexity
*/
migrationComplexity: z.enum(['trivial', 'simple', 'moderate', 'complex', 'major']).optional(),
/**
* Estimated migration time in hours
*/
estimatedMigrationTime: z.number().optional(),
/**
* Migration script available
*/
migrationScript: z.string().optional().describe('Path to migration script'),
/**
* Test coverage for migration
*/
testCoverage: z.number().min(0).max(100).optional()
.describe('Percentage of migration covered by tests'),
});
/**
* Plugin Compatibility Matrix
* Complete compatibility information for a plugin
*/
export const PluginCompatibilityMatrixSchema = z.object({
/**
* Plugin identifier
*/
pluginId: z.string(),
/**
* Current version
*/
currentVersion: z.string(),
/**
* Compatibility entries
*/
compatibilityMatrix: z.array(CompatibilityMatrixEntrySchema),
/**
* Supported versions
*/
supportedVersions: z.array(z.object({
version: z.string(),
supported: z.boolean(),
endOfLife: z.string().datetime().optional().describe('End of support date'),
securitySupport: z.boolean().default(false).describe('Still receives security updates'),
})),
/**
* Minimum compatible version
*/
minimumCompatibleVersion: z.string().optional()
.describe('Oldest version that can be directly upgraded'),
});
/**
* Dependency Conflict
* Represents a conflict in plugin dependencies at the kernel level.
* Models plugin-to-plugin dependency conflicts with typed conflict categories.
*
* @see hub/plugin-security.zod.ts DependencyConflictSchema for hub-level package version conflicts
* which focuses on marketplace registry resolution.
*/
export const DependencyConflictSchema = z.object({
/**
* Type of conflict
*/
type: z.enum([
'version-mismatch', // Different versions required
'missing-dependency', // Required dependency not found
'circular-dependency', // Circular dependency detected
'incompatible-versions', // Incompatible versions required by different plugins
'conflicting-interfaces', // Plugins implement conflicting interfaces
]),
/**
* Plugins involved in conflict
*/
plugins: z.array(z.object({
pluginId: z.string(),
version: z.string(),
requirement: z.string().optional().describe('What this plugin requires'),
})),
/**
* Conflict description
*/
description: z.string(),
/**
* Possible resolutions
*/
resolutions: z.array(z.object({
strategy: z.enum([
'upgrade', // Upgrade one or more plugins
'downgrade', // Downgrade one or more plugins
'replace', // Replace with alternative plugin
'disable', // Disable conflicting plugin
'manual', // Manual intervention required
]),
description: z.string(),
automaticResolution: z.boolean().default(false),
riskLevel: z.enum(['low', 'medium', 'high']),
})).optional(),
/**
* Severity of conflict
*/
severity: z.enum(['critical', 'error', 'warning', 'info']),
});
/**
* Dependency Resolution Result
* Result of dependency resolution process
*/
export const PluginDependencyResolutionResultSchema = z.object({
/**
* Resolution successful
*/
success: z.boolean(),
/**
* Resolved plugin versions
*/
resolved: z.array(z.object({
pluginId: z.string(),
version: z.string(),
resolvedVersion: z.string(),
})).optional(),
/**
* Conflicts found
*/
conflicts: z.array(DependencyConflictSchema).optional(),
/**
* Warnings
*/
warnings: z.array(z.string()).optional(),
/**
* Installation order (topologically sorted)
*/
installationOrder: z.array(z.string()).optional()
.describe('Plugin IDs in order they should be installed'),
/**
* Dependency graph
*/
dependencyGraph: z.record(z.string(), z.array(z.string())).optional()
.describe('Map of plugin ID to its dependencies'),
});
/**
* Multi-Version Support Configuration
* Allows running multiple versions of a plugin simultaneously
*/
export const MultiVersionSupportSchema = z.object({
/**
* Enable multi-version support
*/
enabled: z.boolean().default(false),
/**
* Maximum concurrent versions
*/
maxConcurrentVersions: z.number().int().min(1).default(2)
.describe('How many versions can run at the same time'),
/**
* Version selection strategy
*/
selectionStrategy: z.enum([
'latest', // Always use latest version
'stable', // Use latest stable version
'compatible', // Use version compatible with dependencies
'pinned', // Use pinned version
'canary', // Use canary/preview version
'custom', // Custom selection logic
]).default('latest'),
/**
* Version routing rules
*/
routing: z.array(z.object({
condition: z.string().describe('Routing condition (e.g., tenant, user, feature flag)'),
version: z.string().describe('Version to use when condition matches'),
priority: z.number().int().default(100).describe('Rule priority'),
})).optional(),
/**
* Gradual rollout configuration
*/
rollout: z.object({
enabled: z.boolean().default(false),
strategy: z.enum(['percentage', 'blue-green', 'canary']),
percentage: z.number().min(0).max(100).optional()
.describe('Percentage of traffic to new version'),
duration: z.number().int().optional()
.describe('Rollout duration in milliseconds'),
}).optional(),
});
/**
* Plugin Version Metadata
* Complete version information for a plugin
*/
export const PluginVersionMetadataSchema = z.object({
/**
* Plugin identifier
*/
pluginId: z.string(),
/**
* Version number
*/
version: SemanticVersionSchema,
/**
* Version string (computed)
*/
versionString: z.string().describe('Full version string (e.g., 1.2.3-beta.1+build.123)'),
/**
* Release date
*/
releaseDate: z.string().datetime(),
/**
* Release notes
*/
releaseNotes: z.string().optional(),
/**
* Breaking changes
*/
breakingChanges: z.array(BreakingChangeSchema).optional(),
/**
* Deprecations
*/
deprecations: z.array(DeprecationNoticeSchema).optional(),
/**
* Compatibility matrix
*/
compatibilityMatrix: z.array(CompatibilityMatrixEntrySchema).optional(),
/**
* Security vulnerabilities fixed
*/
securityFixes: z.array(z.object({
cve: z.string().optional().describe('CVE identifier'),
severity: z.enum(['critical', 'high', 'medium', 'low']),
description: z.string(),
fixedIn: z.string().describe('Version where vulnerability was fixed'),
})).optional(),
/**
* Download statistics
*/
statistics: z.object({
downloads: z.number().int().min(0).optional(),
installations: z.number().int().min(0).optional(),
ratings: z.number().min(0).max(5).optional(),
}).optional(),
/**
* Support status
*/
support: z.object({
status: z.enum(['active', 'maintenance', 'deprecated', 'eol']),
endOfLife: z.string().datetime().optional(),
securitySupport: z.boolean().default(true),
}),
});
// Export types
export type SemanticVersion = z.infer<typeof SemanticVersionSchema>;
export type VersionConstraint = z.infer<typeof VersionConstraintSchema>;
export type CompatibilityLevel = z.infer<typeof CompatibilityLevelSchema>;
export type BreakingChange = z.infer<typeof BreakingChangeSchema>;
export type DeprecationNotice = z.infer<typeof DeprecationNoticeSchema>;
export type CompatibilityMatrixEntry = z.infer<typeof CompatibilityMatrixEntrySchema>;
export type PluginCompatibilityMatrix = z.infer<typeof PluginCompatibilityMatrixSchema>;
export type DependencyConflict = z.infer<typeof DependencyConflictSchema>;
export type PluginDependencyResolutionResult = z.infer<typeof PluginDependencyResolutionResultSchema>;
export type MultiVersionSupport = z.infer<typeof MultiVersionSupportSchema>;
export type PluginVersionMetadata = z.infer<typeof PluginVersionMetadataSchema>;