@push.rocks/smartregistry 1.5.0 → 1.7.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_ts/00_commitinfo_data.js +3 -3
- package/dist_ts/classes.smartregistry.d.ts +2 -2
- package/dist_ts/classes.smartregistry.js +37 -2
- package/dist_ts/core/classes.registrystorage.d.ts +77 -0
- package/dist_ts/core/classes.registrystorage.js +200 -9
- package/dist_ts/core/interfaces.core.d.ts +3 -7
- package/dist_ts/index.d.ts +3 -1
- package/dist_ts/index.js +6 -2
- package/dist_ts/plugins.d.ts +2 -0
- package/dist_ts/plugins.js +4 -1
- package/dist_ts/pypi/classes.pypiregistry.js +22 -10
- package/dist_ts/rubygems/classes.rubygemsregistry.d.ts +86 -0
- package/dist_ts/rubygems/classes.rubygemsregistry.js +475 -0
- package/dist_ts/rubygems/helpers.rubygems.d.ts +143 -0
- package/dist_ts/rubygems/helpers.rubygems.js +312 -0
- package/dist_ts/rubygems/index.d.ts +7 -0
- package/dist_ts/rubygems/index.js +8 -0
- package/dist_ts/rubygems/interfaces.rubygems.d.ts +236 -0
- package/dist_ts/rubygems/interfaces.rubygems.js +6 -0
- package/package.json +3 -2
- package/readme.hints.md +108 -4
- package/readme.md +301 -17
- package/ts/00_commitinfo_data.ts +2 -2
- package/ts/classes.smartregistry.ts +41 -2
- package/ts/core/classes.registrystorage.ts +238 -8
- package/ts/core/interfaces.core.ts +4 -7
- package/ts/index.ts +7 -1
- package/ts/plugins.ts +5 -0
- package/ts/pypi/classes.pypiregistry.ts +24 -8
- package/ts/rubygems/classes.rubygemsregistry.ts +598 -0
- package/ts/rubygems/helpers.rubygems.ts +398 -0
- package/ts/rubygems/index.ts +8 -0
- package/ts/rubygems/interfaces.rubygems.ts +251 -0
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helper functions for RubyGems registry
|
|
3
|
+
* Compact Index generation, dependency formatting, etc.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type {
|
|
7
|
+
IRubyGemsVersion,
|
|
8
|
+
IRubyGemsDependency,
|
|
9
|
+
IRubyGemsRequirement,
|
|
10
|
+
ICompactIndexVersionsEntry,
|
|
11
|
+
ICompactIndexInfoEntry,
|
|
12
|
+
IRubyGemsMetadata,
|
|
13
|
+
} from './interfaces.rubygems.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Generate Compact Index versions file
|
|
17
|
+
* Format: GEMNAME [-]VERSION_PLATFORM[,VERSION_PLATFORM,...] MD5
|
|
18
|
+
* @param entries - Version entries for all gems
|
|
19
|
+
* @returns Compact Index versions file content
|
|
20
|
+
*/
|
|
21
|
+
export function generateCompactIndexVersions(entries: ICompactIndexVersionsEntry[]): string {
|
|
22
|
+
const lines: string[] = [];
|
|
23
|
+
|
|
24
|
+
// Add metadata header
|
|
25
|
+
lines.push(`created_at: ${new Date().toISOString()}`);
|
|
26
|
+
lines.push('---');
|
|
27
|
+
|
|
28
|
+
// Add gem entries
|
|
29
|
+
for (const entry of entries) {
|
|
30
|
+
const versions = entry.versions
|
|
31
|
+
.map(v => {
|
|
32
|
+
const yanked = v.yanked ? '-' : '';
|
|
33
|
+
const platform = v.platform && v.platform !== 'ruby' ? `_${v.platform}` : '';
|
|
34
|
+
return `${yanked}${v.version}${platform}`;
|
|
35
|
+
})
|
|
36
|
+
.join(',');
|
|
37
|
+
|
|
38
|
+
lines.push(`${entry.name} ${versions} ${entry.infoChecksum}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return lines.join('\n');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Generate Compact Index info file for a gem
|
|
46
|
+
* Format: VERSION[-PLATFORM] [DEP[,DEP,...]]|REQ[,REQ,...]
|
|
47
|
+
* @param entries - Info entries for gem versions
|
|
48
|
+
* @returns Compact Index info file content
|
|
49
|
+
*/
|
|
50
|
+
export function generateCompactIndexInfo(entries: ICompactIndexInfoEntry[]): string {
|
|
51
|
+
const lines: string[] = ['---']; // Info files start with ---
|
|
52
|
+
|
|
53
|
+
for (const entry of entries) {
|
|
54
|
+
// Build version string with optional platform
|
|
55
|
+
const versionStr = entry.platform && entry.platform !== 'ruby'
|
|
56
|
+
? `${entry.version}-${entry.platform}`
|
|
57
|
+
: entry.version;
|
|
58
|
+
|
|
59
|
+
// Build dependencies string
|
|
60
|
+
const depsStr = entry.dependencies.length > 0
|
|
61
|
+
? entry.dependencies.map(formatDependency).join(',')
|
|
62
|
+
: '';
|
|
63
|
+
|
|
64
|
+
// Build requirements string (checksum is always required)
|
|
65
|
+
const reqParts: string[] = [`checksum:${entry.checksum}`];
|
|
66
|
+
|
|
67
|
+
for (const req of entry.requirements) {
|
|
68
|
+
reqParts.push(`${req.type}:${req.requirement}`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const reqStr = reqParts.join(',');
|
|
72
|
+
|
|
73
|
+
// Combine: VERSION[-PLATFORM] [DEPS]|REQS
|
|
74
|
+
const depPart = depsStr ? ` ${depsStr}` : '';
|
|
75
|
+
lines.push(`${versionStr}${depPart}|${reqStr}`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return lines.join('\n');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Format a dependency for Compact Index
|
|
83
|
+
* Format: GEM:CONSTRAINT[&CONSTRAINT]
|
|
84
|
+
* @param dep - Dependency object
|
|
85
|
+
* @returns Formatted dependency string
|
|
86
|
+
*/
|
|
87
|
+
export function formatDependency(dep: IRubyGemsDependency): string {
|
|
88
|
+
return `${dep.name}:${dep.requirement}`;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Parse dependency string from Compact Index
|
|
93
|
+
* @param depStr - Dependency string
|
|
94
|
+
* @returns Dependency object
|
|
95
|
+
*/
|
|
96
|
+
export function parseDependency(depStr: string): IRubyGemsDependency {
|
|
97
|
+
const [name, ...reqParts] = depStr.split(':');
|
|
98
|
+
const requirement = reqParts.join(':'); // Handle :: in gem names
|
|
99
|
+
|
|
100
|
+
return { name, requirement };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Generate names file (newline-separated gem names)
|
|
105
|
+
* @param names - List of gem names
|
|
106
|
+
* @returns Names file content
|
|
107
|
+
*/
|
|
108
|
+
export function generateNamesFile(names: string[]): string {
|
|
109
|
+
return `---\n${names.sort().join('\n')}`;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Calculate MD5 hash for Compact Index checksum
|
|
114
|
+
* @param content - Content to hash
|
|
115
|
+
* @returns MD5 hash (hex)
|
|
116
|
+
*/
|
|
117
|
+
export async function calculateMD5(content: string): Promise<string> {
|
|
118
|
+
const crypto = await import('crypto');
|
|
119
|
+
return crypto.createHash('md5').update(content).digest('hex');
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Calculate SHA256 hash for gem files
|
|
124
|
+
* @param data - Data to hash
|
|
125
|
+
* @returns SHA256 hash (hex)
|
|
126
|
+
*/
|
|
127
|
+
export async function calculateSHA256(data: Buffer): Promise<string> {
|
|
128
|
+
const crypto = await import('crypto');
|
|
129
|
+
return crypto.createHash('sha256').update(data).digest('hex');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Parse gem filename to extract name, version, and platform
|
|
134
|
+
* @param filename - Gem filename (e.g., "rails-7.0.0-x86_64-linux.gem")
|
|
135
|
+
* @returns Parsed info or null
|
|
136
|
+
*/
|
|
137
|
+
export function parseGemFilename(filename: string): {
|
|
138
|
+
name: string;
|
|
139
|
+
version: string;
|
|
140
|
+
platform?: string;
|
|
141
|
+
} | null {
|
|
142
|
+
if (!filename.endsWith('.gem')) return null;
|
|
143
|
+
|
|
144
|
+
const withoutExt = filename.slice(0, -4); // Remove .gem
|
|
145
|
+
|
|
146
|
+
// Try to match: name-version-platform
|
|
147
|
+
// Platform can contain hyphens (e.g., x86_64-linux)
|
|
148
|
+
const parts = withoutExt.split('-');
|
|
149
|
+
if (parts.length < 2) return null;
|
|
150
|
+
|
|
151
|
+
// Find version (first part that starts with a digit)
|
|
152
|
+
let versionIndex = -1;
|
|
153
|
+
for (let i = 1; i < parts.length; i++) {
|
|
154
|
+
if (/^\d/.test(parts[i])) {
|
|
155
|
+
versionIndex = i;
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (versionIndex === -1) return null;
|
|
161
|
+
|
|
162
|
+
const name = parts.slice(0, versionIndex).join('-');
|
|
163
|
+
const version = parts[versionIndex];
|
|
164
|
+
const platform = versionIndex + 1 < parts.length
|
|
165
|
+
? parts.slice(versionIndex + 1).join('-')
|
|
166
|
+
: undefined;
|
|
167
|
+
|
|
168
|
+
return {
|
|
169
|
+
name,
|
|
170
|
+
version,
|
|
171
|
+
platform: platform && platform !== 'ruby' ? platform : undefined,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Validate gem name
|
|
177
|
+
* Must contain only ASCII letters, numbers, _, and -
|
|
178
|
+
* @param name - Gem name
|
|
179
|
+
* @returns true if valid
|
|
180
|
+
*/
|
|
181
|
+
export function isValidGemName(name: string): boolean {
|
|
182
|
+
return /^[a-zA-Z0-9_-]+$/.test(name);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Validate version string
|
|
187
|
+
* Basic semantic versioning check
|
|
188
|
+
* @param version - Version string
|
|
189
|
+
* @returns true if valid
|
|
190
|
+
*/
|
|
191
|
+
export function isValidVersion(version: string): boolean {
|
|
192
|
+
// Allow semver and other common Ruby version formats
|
|
193
|
+
return /^[\d.a-zA-Z_-]+$/.test(version);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Build version list entry for Compact Index
|
|
198
|
+
* @param versions - Version info
|
|
199
|
+
* @returns Version list string
|
|
200
|
+
*/
|
|
201
|
+
export function buildVersionList(versions: Array<{
|
|
202
|
+
version: string;
|
|
203
|
+
platform?: string;
|
|
204
|
+
yanked: boolean;
|
|
205
|
+
}>): string {
|
|
206
|
+
return versions
|
|
207
|
+
.map(v => {
|
|
208
|
+
const yanked = v.yanked ? '-' : '';
|
|
209
|
+
const platform = v.platform && v.platform !== 'ruby' ? `_${v.platform}` : '';
|
|
210
|
+
return `${yanked}${v.version}${platform}`;
|
|
211
|
+
})
|
|
212
|
+
.join(',');
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Parse version list from Compact Index
|
|
217
|
+
* @param versionStr - Version list string
|
|
218
|
+
* @returns Parsed versions
|
|
219
|
+
*/
|
|
220
|
+
export function parseVersionList(versionStr: string): Array<{
|
|
221
|
+
version: string;
|
|
222
|
+
platform?: string;
|
|
223
|
+
yanked: boolean;
|
|
224
|
+
}> {
|
|
225
|
+
return versionStr.split(',').map(v => {
|
|
226
|
+
const yanked = v.startsWith('-');
|
|
227
|
+
const withoutYank = yanked ? v.substring(1) : v;
|
|
228
|
+
|
|
229
|
+
// Split on _ to separate version from platform
|
|
230
|
+
const [version, ...platformParts] = withoutYank.split('_');
|
|
231
|
+
const platform = platformParts.length > 0 ? platformParts.join('_') : undefined;
|
|
232
|
+
|
|
233
|
+
return {
|
|
234
|
+
version,
|
|
235
|
+
platform: platform && platform !== 'ruby' ? platform : undefined,
|
|
236
|
+
yanked,
|
|
237
|
+
};
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Generate JSON response for /api/v1/versions/{gem}.json
|
|
243
|
+
* @param gemName - Gem name
|
|
244
|
+
* @param versions - Version list
|
|
245
|
+
* @returns JSON response object
|
|
246
|
+
*/
|
|
247
|
+
export function generateVersionsJson(
|
|
248
|
+
gemName: string,
|
|
249
|
+
versions: Array<{
|
|
250
|
+
version: string;
|
|
251
|
+
platform?: string;
|
|
252
|
+
uploadTime?: string;
|
|
253
|
+
}>
|
|
254
|
+
): any {
|
|
255
|
+
return {
|
|
256
|
+
name: gemName,
|
|
257
|
+
versions: versions.map(v => ({
|
|
258
|
+
number: v.version,
|
|
259
|
+
platform: v.platform || 'ruby',
|
|
260
|
+
built_at: v.uploadTime,
|
|
261
|
+
})),
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Generate JSON response for /api/v1/dependencies
|
|
267
|
+
* @param gems - Map of gem names to version dependencies
|
|
268
|
+
* @returns JSON response array
|
|
269
|
+
*/
|
|
270
|
+
export function generateDependenciesJson(gems: Map<string, Array<{
|
|
271
|
+
version: string;
|
|
272
|
+
platform?: string;
|
|
273
|
+
dependencies: IRubyGemsDependency[];
|
|
274
|
+
}>>): any {
|
|
275
|
+
const result: any[] = [];
|
|
276
|
+
|
|
277
|
+
for (const [name, versions] of gems) {
|
|
278
|
+
for (const v of versions) {
|
|
279
|
+
result.push({
|
|
280
|
+
name,
|
|
281
|
+
number: v.version,
|
|
282
|
+
platform: v.platform || 'ruby',
|
|
283
|
+
dependencies: v.dependencies.map(d => ({
|
|
284
|
+
name: d.name,
|
|
285
|
+
requirements: d.requirement,
|
|
286
|
+
})),
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return result;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Update Compact Index versions file with new gem version
|
|
296
|
+
* Handles append-only semantics for the current month
|
|
297
|
+
* @param existingContent - Current versions file content
|
|
298
|
+
* @param gemName - Gem name
|
|
299
|
+
* @param newVersion - New version info
|
|
300
|
+
* @param infoChecksum - MD5 of info file
|
|
301
|
+
* @returns Updated versions file content
|
|
302
|
+
*/
|
|
303
|
+
export function updateCompactIndexVersions(
|
|
304
|
+
existingContent: string,
|
|
305
|
+
gemName: string,
|
|
306
|
+
newVersion: { version: string; platform?: string; yanked: boolean },
|
|
307
|
+
infoChecksum: string
|
|
308
|
+
): string {
|
|
309
|
+
const lines = existingContent.split('\n');
|
|
310
|
+
const headerEndIndex = lines.findIndex(l => l === '---');
|
|
311
|
+
|
|
312
|
+
if (headerEndIndex === -1) {
|
|
313
|
+
throw new Error('Invalid Compact Index versions file');
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
const header = lines.slice(0, headerEndIndex + 1);
|
|
317
|
+
const entries = lines.slice(headerEndIndex + 1).filter(l => l.trim());
|
|
318
|
+
|
|
319
|
+
// Find existing entry for gem
|
|
320
|
+
const gemLineIndex = entries.findIndex(l => l.startsWith(`${gemName} `));
|
|
321
|
+
|
|
322
|
+
const versionStr = buildVersionList([newVersion]);
|
|
323
|
+
|
|
324
|
+
if (gemLineIndex >= 0) {
|
|
325
|
+
// Append to existing entry
|
|
326
|
+
const parts = entries[gemLineIndex].split(' ');
|
|
327
|
+
const existingVersions = parts[1];
|
|
328
|
+
const updatedVersions = `${existingVersions},${versionStr}`;
|
|
329
|
+
entries[gemLineIndex] = `${gemName} ${updatedVersions} ${infoChecksum}`;
|
|
330
|
+
} else {
|
|
331
|
+
// Add new entry
|
|
332
|
+
entries.push(`${gemName} ${versionStr} ${infoChecksum}`);
|
|
333
|
+
entries.sort(); // Keep alphabetical
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return [...header, ...entries].join('\n');
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Update Compact Index info file with new version
|
|
341
|
+
* @param existingContent - Current info file content
|
|
342
|
+
* @param newEntry - New version entry
|
|
343
|
+
* @returns Updated info file content
|
|
344
|
+
*/
|
|
345
|
+
export function updateCompactIndexInfo(
|
|
346
|
+
existingContent: string,
|
|
347
|
+
newEntry: ICompactIndexInfoEntry
|
|
348
|
+
): string {
|
|
349
|
+
const lines = existingContent ? existingContent.split('\n').filter(l => l !== '---') : [];
|
|
350
|
+
|
|
351
|
+
// Build version string
|
|
352
|
+
const versionStr = newEntry.platform && newEntry.platform !== 'ruby'
|
|
353
|
+
? `${newEntry.version}-${newEntry.platform}`
|
|
354
|
+
: newEntry.version;
|
|
355
|
+
|
|
356
|
+
// Build dependencies string
|
|
357
|
+
const depsStr = newEntry.dependencies.length > 0
|
|
358
|
+
? newEntry.dependencies.map(formatDependency).join(',')
|
|
359
|
+
: '';
|
|
360
|
+
|
|
361
|
+
// Build requirements string
|
|
362
|
+
const reqParts: string[] = [`checksum:${newEntry.checksum}`];
|
|
363
|
+
for (const req of newEntry.requirements) {
|
|
364
|
+
reqParts.push(`${req.type}:${req.requirement}`);
|
|
365
|
+
}
|
|
366
|
+
const reqStr = reqParts.join(',');
|
|
367
|
+
|
|
368
|
+
// Combine
|
|
369
|
+
const depPart = depsStr ? ` ${depsStr}` : '';
|
|
370
|
+
const newLine = `${versionStr}${depPart}|${reqStr}`;
|
|
371
|
+
|
|
372
|
+
lines.push(newLine);
|
|
373
|
+
|
|
374
|
+
return `---\n${lines.join('\n')}`;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Extract gem specification from .gem file
|
|
379
|
+
* Note: This is a simplified version. Full implementation would use tar + gzip + Marshal
|
|
380
|
+
* @param gemData - Gem file data
|
|
381
|
+
* @returns Extracted spec or null
|
|
382
|
+
*/
|
|
383
|
+
export async function extractGemSpec(gemData: Buffer): Promise<any | null> {
|
|
384
|
+
try {
|
|
385
|
+
// .gem files are gzipped tar archives
|
|
386
|
+
// They contain metadata.gz which has Marshal-encoded spec
|
|
387
|
+
// This is a placeholder - full implementation would need:
|
|
388
|
+
// 1. Unzip outer gzip
|
|
389
|
+
// 2. Untar to find metadata.gz
|
|
390
|
+
// 3. Unzip metadata.gz
|
|
391
|
+
// 4. Parse Ruby Marshal format
|
|
392
|
+
|
|
393
|
+
// For now, return null and expect metadata to be provided
|
|
394
|
+
return null;
|
|
395
|
+
} catch (error) {
|
|
396
|
+
return null;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RubyGems Registry Type Definitions
|
|
3
|
+
* Compliant with Compact Index API and RubyGems protocol
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Gem version entry in compact index
|
|
8
|
+
*/
|
|
9
|
+
export interface IRubyGemsVersion {
|
|
10
|
+
/** Version number */
|
|
11
|
+
version: string;
|
|
12
|
+
/** Platform (e.g., ruby, x86_64-linux) */
|
|
13
|
+
platform?: string;
|
|
14
|
+
/** Dependencies */
|
|
15
|
+
dependencies?: IRubyGemsDependency[];
|
|
16
|
+
/** Requirements */
|
|
17
|
+
requirements?: IRubyGemsRequirement[];
|
|
18
|
+
/** Whether this version is yanked */
|
|
19
|
+
yanked?: boolean;
|
|
20
|
+
/** SHA256 checksum of .gem file */
|
|
21
|
+
checksum?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Gem dependency specification
|
|
26
|
+
*/
|
|
27
|
+
export interface IRubyGemsDependency {
|
|
28
|
+
/** Gem name */
|
|
29
|
+
name: string;
|
|
30
|
+
/** Version requirement (e.g., ">= 1.0", "~> 2.0") */
|
|
31
|
+
requirement: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Gem requirements (ruby version, rubygems version, etc.)
|
|
36
|
+
*/
|
|
37
|
+
export interface IRubyGemsRequirement {
|
|
38
|
+
/** Requirement type (ruby, rubygems) */
|
|
39
|
+
type: 'ruby' | 'rubygems';
|
|
40
|
+
/** Version requirement */
|
|
41
|
+
requirement: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Complete gem metadata
|
|
46
|
+
*/
|
|
47
|
+
export interface IRubyGemsMetadata {
|
|
48
|
+
/** Gem name */
|
|
49
|
+
name: string;
|
|
50
|
+
/** All versions */
|
|
51
|
+
versions: Record<string, IRubyGemsVersionMetadata>;
|
|
52
|
+
/** Last modified timestamp */
|
|
53
|
+
'last-modified'?: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Version-specific metadata
|
|
58
|
+
*/
|
|
59
|
+
export interface IRubyGemsVersionMetadata {
|
|
60
|
+
/** Version number */
|
|
61
|
+
version: string;
|
|
62
|
+
/** Platform */
|
|
63
|
+
platform?: string;
|
|
64
|
+
/** Authors */
|
|
65
|
+
authors?: string[];
|
|
66
|
+
/** Description */
|
|
67
|
+
description?: string;
|
|
68
|
+
/** Summary */
|
|
69
|
+
summary?: string;
|
|
70
|
+
/** Homepage */
|
|
71
|
+
homepage?: string;
|
|
72
|
+
/** License */
|
|
73
|
+
license?: string;
|
|
74
|
+
/** Dependencies */
|
|
75
|
+
dependencies?: IRubyGemsDependency[];
|
|
76
|
+
/** Requirements */
|
|
77
|
+
requirements?: IRubyGemsRequirement[];
|
|
78
|
+
/** SHA256 checksum */
|
|
79
|
+
checksum: string;
|
|
80
|
+
/** File size */
|
|
81
|
+
size: number;
|
|
82
|
+
/** Upload timestamp */
|
|
83
|
+
'upload-time': string;
|
|
84
|
+
/** Uploader */
|
|
85
|
+
'uploaded-by': string;
|
|
86
|
+
/** Yanked status */
|
|
87
|
+
yanked?: boolean;
|
|
88
|
+
/** Yank reason */
|
|
89
|
+
'yank-reason'?: string;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Compact index versions file entry
|
|
94
|
+
* Format: GEMNAME [-]VERSION_PLATFORM[,VERSION_PLATFORM,...] MD5
|
|
95
|
+
*/
|
|
96
|
+
export interface ICompactIndexVersionsEntry {
|
|
97
|
+
/** Gem name */
|
|
98
|
+
name: string;
|
|
99
|
+
/** Versions (with optional platform and yank flag) */
|
|
100
|
+
versions: Array<{
|
|
101
|
+
version: string;
|
|
102
|
+
platform?: string;
|
|
103
|
+
yanked: boolean;
|
|
104
|
+
}>;
|
|
105
|
+
/** MD5 checksum of info file */
|
|
106
|
+
infoChecksum: string;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Compact index info file entry
|
|
111
|
+
* Format: VERSION[-PLATFORM] [DEP[,DEP,...]]|REQ[,REQ,...]
|
|
112
|
+
*/
|
|
113
|
+
export interface ICompactIndexInfoEntry {
|
|
114
|
+
/** Version number */
|
|
115
|
+
version: string;
|
|
116
|
+
/** Platform (optional) */
|
|
117
|
+
platform?: string;
|
|
118
|
+
/** Dependencies */
|
|
119
|
+
dependencies: IRubyGemsDependency[];
|
|
120
|
+
/** Requirements */
|
|
121
|
+
requirements: IRubyGemsRequirement[];
|
|
122
|
+
/** SHA256 checksum */
|
|
123
|
+
checksum: string;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Gem upload request
|
|
128
|
+
*/
|
|
129
|
+
export interface IRubyGemsUploadRequest {
|
|
130
|
+
/** Gem file data */
|
|
131
|
+
gemData: Buffer;
|
|
132
|
+
/** Gem filename */
|
|
133
|
+
filename: string;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Gem upload response
|
|
138
|
+
*/
|
|
139
|
+
export interface IRubyGemsUploadResponse {
|
|
140
|
+
/** Success message */
|
|
141
|
+
message?: string;
|
|
142
|
+
/** Gem name */
|
|
143
|
+
name?: string;
|
|
144
|
+
/** Version */
|
|
145
|
+
version?: string;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Yank request
|
|
150
|
+
*/
|
|
151
|
+
export interface IRubyGemsYankRequest {
|
|
152
|
+
/** Gem name */
|
|
153
|
+
gem_name: string;
|
|
154
|
+
/** Version to yank */
|
|
155
|
+
version: string;
|
|
156
|
+
/** Platform (optional) */
|
|
157
|
+
platform?: string;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Yank response
|
|
162
|
+
*/
|
|
163
|
+
export interface IRubyGemsYankResponse {
|
|
164
|
+
/** Success indicator */
|
|
165
|
+
success: boolean;
|
|
166
|
+
/** Message */
|
|
167
|
+
message?: string;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Version info response (JSON)
|
|
172
|
+
*/
|
|
173
|
+
export interface IRubyGemsVersionInfo {
|
|
174
|
+
/** Gem name */
|
|
175
|
+
name: string;
|
|
176
|
+
/** Versions list */
|
|
177
|
+
versions: Array<{
|
|
178
|
+
/** Version number */
|
|
179
|
+
number: string;
|
|
180
|
+
/** Platform */
|
|
181
|
+
platform?: string;
|
|
182
|
+
/** Build date */
|
|
183
|
+
built_at?: string;
|
|
184
|
+
/** Download count */
|
|
185
|
+
downloads_count?: number;
|
|
186
|
+
}>;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Dependencies query response
|
|
191
|
+
*/
|
|
192
|
+
export interface IRubyGemsDependenciesResponse {
|
|
193
|
+
/** Dependencies for requested gems */
|
|
194
|
+
dependencies: Array<{
|
|
195
|
+
/** Gem name */
|
|
196
|
+
name: string;
|
|
197
|
+
/** Version */
|
|
198
|
+
number: string;
|
|
199
|
+
/** Platform */
|
|
200
|
+
platform?: string;
|
|
201
|
+
/** Dependencies */
|
|
202
|
+
dependencies: Array<{
|
|
203
|
+
name: string;
|
|
204
|
+
requirements: string;
|
|
205
|
+
}>;
|
|
206
|
+
}>;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Error response structure
|
|
211
|
+
*/
|
|
212
|
+
export interface IRubyGemsError {
|
|
213
|
+
/** Error message */
|
|
214
|
+
message: string;
|
|
215
|
+
/** HTTP status code */
|
|
216
|
+
status?: number;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Gem specification (extracted from .gem file)
|
|
221
|
+
*/
|
|
222
|
+
export interface IRubyGemsSpec {
|
|
223
|
+
/** Gem name */
|
|
224
|
+
name: string;
|
|
225
|
+
/** Version */
|
|
226
|
+
version: string;
|
|
227
|
+
/** Platform */
|
|
228
|
+
platform?: string;
|
|
229
|
+
/** Authors */
|
|
230
|
+
authors?: string[];
|
|
231
|
+
/** Email */
|
|
232
|
+
email?: string;
|
|
233
|
+
/** Homepage */
|
|
234
|
+
homepage?: string;
|
|
235
|
+
/** Summary */
|
|
236
|
+
summary?: string;
|
|
237
|
+
/** Description */
|
|
238
|
+
description?: string;
|
|
239
|
+
/** License */
|
|
240
|
+
license?: string;
|
|
241
|
+
/** Dependencies */
|
|
242
|
+
dependencies?: IRubyGemsDependency[];
|
|
243
|
+
/** Required Ruby version */
|
|
244
|
+
required_ruby_version?: string;
|
|
245
|
+
/** Required RubyGems version */
|
|
246
|
+
required_rubygems_version?: string;
|
|
247
|
+
/** Files */
|
|
248
|
+
files?: string[];
|
|
249
|
+
/** Requirements */
|
|
250
|
+
requirements?: string[];
|
|
251
|
+
}
|