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