@push.rocks/smartregistry 1.1.1 → 1.3.1

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.
Files changed (51) hide show
  1. package/dist_ts/00_commitinfo_data.js +1 -1
  2. package/dist_ts/cargo/classes.cargoregistry.d.ts +79 -0
  3. package/dist_ts/cargo/classes.cargoregistry.js +490 -0
  4. package/dist_ts/cargo/index.d.ts +5 -0
  5. package/dist_ts/cargo/index.js +6 -0
  6. package/dist_ts/cargo/interfaces.cargo.d.ts +160 -0
  7. package/dist_ts/cargo/interfaces.cargo.js +6 -0
  8. package/dist_ts/classes.smartregistry.d.ts +2 -2
  9. package/dist_ts/classes.smartregistry.js +50 -2
  10. package/dist_ts/composer/classes.composerregistry.d.ts +26 -0
  11. package/dist_ts/composer/classes.composerregistry.js +366 -0
  12. package/dist_ts/composer/helpers.composer.d.ts +35 -0
  13. package/dist_ts/composer/helpers.composer.js +120 -0
  14. package/dist_ts/composer/index.d.ts +7 -0
  15. package/dist_ts/composer/index.js +8 -0
  16. package/dist_ts/composer/interfaces.composer.d.ts +102 -0
  17. package/dist_ts/composer/interfaces.composer.js +6 -0
  18. package/dist_ts/core/classes.authmanager.d.ts +46 -1
  19. package/dist_ts/core/classes.authmanager.js +121 -12
  20. package/dist_ts/core/classes.registrystorage.d.ts +99 -0
  21. package/dist_ts/core/classes.registrystorage.js +246 -1
  22. package/dist_ts/core/interfaces.core.d.ts +4 -1
  23. package/dist_ts/index.d.ts +4 -1
  24. package/dist_ts/index.js +8 -2
  25. package/dist_ts/maven/classes.mavenregistry.d.ts +35 -0
  26. package/dist_ts/maven/classes.mavenregistry.js +407 -0
  27. package/dist_ts/maven/helpers.maven.d.ts +68 -0
  28. package/dist_ts/maven/helpers.maven.js +286 -0
  29. package/dist_ts/maven/index.d.ts +6 -0
  30. package/dist_ts/maven/index.js +7 -0
  31. package/dist_ts/maven/interfaces.maven.d.ts +116 -0
  32. package/dist_ts/maven/interfaces.maven.js +6 -0
  33. package/package.json +3 -2
  34. package/readme.md +288 -14
  35. package/ts/00_commitinfo_data.ts +1 -1
  36. package/ts/cargo/classes.cargoregistry.ts +604 -0
  37. package/ts/cargo/index.ts +6 -0
  38. package/ts/cargo/interfaces.cargo.ts +169 -0
  39. package/ts/classes.smartregistry.ts +56 -2
  40. package/ts/composer/classes.composerregistry.ts +475 -0
  41. package/ts/composer/helpers.composer.ts +139 -0
  42. package/ts/composer/index.ts +8 -0
  43. package/ts/composer/interfaces.composer.ts +111 -0
  44. package/ts/core/classes.authmanager.ts +145 -12
  45. package/ts/core/classes.registrystorage.ts +323 -0
  46. package/ts/core/interfaces.core.ts +4 -1
  47. package/ts/index.ts +10 -1
  48. package/ts/maven/classes.mavenregistry.ts +580 -0
  49. package/ts/maven/helpers.maven.ts +346 -0
  50. package/ts/maven/index.ts +7 -0
  51. package/ts/maven/interfaces.maven.ts +127 -0
@@ -0,0 +1,407 @@
1
+ /**
2
+ * Maven Registry Implementation
3
+ * Implements Maven repository protocol for Java artifacts
4
+ */
5
+ import { BaseRegistry } from '../core/classes.baseregistry.js';
6
+ import { pathToGAV, buildFilename, calculateChecksums, generateMetadataXml, parseMetadataXml, formatMavenTimestamp, isSnapshot, validatePom, extractGAVFromPom, gavToPath, } from './helpers.maven.js';
7
+ /**
8
+ * Maven Registry class
9
+ * Handles Maven repository HTTP protocol
10
+ */
11
+ export class MavenRegistry extends BaseRegistry {
12
+ storage;
13
+ authManager;
14
+ basePath = '/maven';
15
+ registryUrl;
16
+ constructor(storage, authManager, basePath, registryUrl) {
17
+ super();
18
+ this.storage = storage;
19
+ this.authManager = authManager;
20
+ this.basePath = basePath;
21
+ this.registryUrl = registryUrl;
22
+ }
23
+ async init() {
24
+ // No special initialization needed for Maven
25
+ }
26
+ getBasePath() {
27
+ return this.basePath;
28
+ }
29
+ async handleRequest(context) {
30
+ // Remove base path from URL
31
+ const path = context.path.replace(this.basePath, '');
32
+ // Extract token from Authorization header
33
+ const authHeader = context.headers['authorization'] || context.headers['Authorization'];
34
+ let token = null;
35
+ if (authHeader) {
36
+ const tokenString = authHeader.replace(/^(Bearer|Basic)\s+/i, '');
37
+ // For now, try to validate as Maven token (reuse npm token type)
38
+ token = await this.authManager.validateToken(tokenString, 'maven');
39
+ }
40
+ // Parse path to determine request type
41
+ const coordinate = pathToGAV(path);
42
+ if (!coordinate) {
43
+ // Not a valid artifact path, could be metadata or root
44
+ if (path.endsWith('/maven-metadata.xml')) {
45
+ return this.handleMetadataRequest(context.method, path, token);
46
+ }
47
+ return {
48
+ status: 404,
49
+ headers: { 'Content-Type': 'application/json' },
50
+ body: { error: 'NOT_FOUND', message: 'Invalid Maven path' },
51
+ };
52
+ }
53
+ // Check if it's a checksum file
54
+ if (coordinate.extension === 'md5' || coordinate.extension === 'sha1' ||
55
+ coordinate.extension === 'sha256' || coordinate.extension === 'sha512') {
56
+ return this.handleChecksumRequest(context.method, coordinate, token, path);
57
+ }
58
+ // Handle artifact requests (JAR, POM, WAR, etc.)
59
+ return this.handleArtifactRequest(context.method, coordinate, token, context.body);
60
+ }
61
+ async checkPermission(token, resource, action) {
62
+ if (!token)
63
+ return false;
64
+ return this.authManager.authorize(token, `maven:artifact:${resource}`, action);
65
+ }
66
+ // ========================================================================
67
+ // REQUEST HANDLERS
68
+ // ========================================================================
69
+ async handleArtifactRequest(method, coordinate, token, body) {
70
+ const { groupId, artifactId, version } = coordinate;
71
+ const filename = buildFilename(coordinate);
72
+ const resource = `${groupId}:${artifactId}`;
73
+ switch (method) {
74
+ case 'GET':
75
+ case 'HEAD':
76
+ // Maven repositories typically allow anonymous reads
77
+ return method === 'GET'
78
+ ? this.getArtifact(groupId, artifactId, version, filename)
79
+ : this.headArtifact(groupId, artifactId, version, filename);
80
+ case 'PUT':
81
+ // Write permission required
82
+ if (!await this.checkPermission(token, resource, 'write')) {
83
+ return {
84
+ status: 401,
85
+ headers: {
86
+ 'WWW-Authenticate': `Bearer realm="${this.basePath}",service="maven-registry"`,
87
+ },
88
+ body: { error: 'UNAUTHORIZED', message: 'Write permission required' },
89
+ };
90
+ }
91
+ if (!body) {
92
+ return {
93
+ status: 400,
94
+ headers: {},
95
+ body: { error: 'BAD_REQUEST', message: 'Request body required' },
96
+ };
97
+ }
98
+ return this.putArtifact(groupId, artifactId, version, filename, coordinate, body);
99
+ case 'DELETE':
100
+ // Delete permission required
101
+ if (!await this.checkPermission(token, resource, 'delete')) {
102
+ return {
103
+ status: 401,
104
+ headers: {
105
+ 'WWW-Authenticate': `Bearer realm="${this.basePath}",service="maven-registry"`,
106
+ },
107
+ body: { error: 'UNAUTHORIZED', message: 'Delete permission required' },
108
+ };
109
+ }
110
+ return this.deleteArtifact(groupId, artifactId, version, filename);
111
+ default:
112
+ return {
113
+ status: 405,
114
+ headers: { 'Allow': 'GET, HEAD, PUT, DELETE' },
115
+ body: { error: 'METHOD_NOT_ALLOWED', message: 'Method not allowed' },
116
+ };
117
+ }
118
+ }
119
+ async handleChecksumRequest(method, coordinate, token, path) {
120
+ const { groupId, artifactId, version, extension } = coordinate;
121
+ const resource = `${groupId}:${artifactId}`;
122
+ // Checksums follow the same permissions as their artifacts (public read)
123
+ if (method === 'GET' || method === 'HEAD') {
124
+ return this.getChecksum(groupId, artifactId, version, coordinate, path);
125
+ }
126
+ return {
127
+ status: 405,
128
+ headers: { 'Allow': 'GET, HEAD' },
129
+ body: { error: 'METHOD_NOT_ALLOWED', message: 'Checksums are auto-generated' },
130
+ };
131
+ }
132
+ async handleMetadataRequest(method, path, token) {
133
+ // Parse path to extract groupId and artifactId
134
+ // Path format: /com/example/my-lib/maven-metadata.xml
135
+ const parts = path.split('/').filter(p => p && p !== 'maven-metadata.xml');
136
+ if (parts.length < 2) {
137
+ return {
138
+ status: 400,
139
+ headers: {},
140
+ body: { error: 'BAD_REQUEST', message: 'Invalid metadata path' },
141
+ };
142
+ }
143
+ const artifactId = parts[parts.length - 1];
144
+ const groupId = parts.slice(0, -1).join('.');
145
+ const resource = `${groupId}:${artifactId}`;
146
+ if (method === 'GET') {
147
+ // Metadata is usually public (read permission optional)
148
+ // Some registries allow anonymous metadata access
149
+ return this.getMetadata(groupId, artifactId);
150
+ }
151
+ return {
152
+ status: 405,
153
+ headers: { 'Allow': 'GET' },
154
+ body: { error: 'METHOD_NOT_ALLOWED', message: 'Metadata is auto-generated' },
155
+ };
156
+ }
157
+ // ========================================================================
158
+ // ARTIFACT OPERATIONS
159
+ // ========================================================================
160
+ async getArtifact(groupId, artifactId, version, filename) {
161
+ const data = await this.storage.getMavenArtifact(groupId, artifactId, version, filename);
162
+ if (!data) {
163
+ return {
164
+ status: 404,
165
+ headers: {},
166
+ body: { error: 'NOT_FOUND', message: 'Artifact not found' },
167
+ };
168
+ }
169
+ // Determine content type based on extension
170
+ const extension = filename.split('.').pop() || '';
171
+ const contentType = this.getContentType(extension);
172
+ return {
173
+ status: 200,
174
+ headers: {
175
+ 'Content-Type': contentType,
176
+ 'Content-Length': data.length.toString(),
177
+ },
178
+ body: data,
179
+ };
180
+ }
181
+ async headArtifact(groupId, artifactId, version, filename) {
182
+ const exists = await this.storage.mavenArtifactExists(groupId, artifactId, version, filename);
183
+ if (!exists) {
184
+ return {
185
+ status: 404,
186
+ headers: {},
187
+ body: null,
188
+ };
189
+ }
190
+ // Get file size for Content-Length header
191
+ const data = await this.storage.getMavenArtifact(groupId, artifactId, version, filename);
192
+ const extension = filename.split('.').pop() || '';
193
+ const contentType = this.getContentType(extension);
194
+ return {
195
+ status: 200,
196
+ headers: {
197
+ 'Content-Type': contentType,
198
+ 'Content-Length': data ? data.length.toString() : '0',
199
+ },
200
+ body: null,
201
+ };
202
+ }
203
+ async putArtifact(groupId, artifactId, version, filename, coordinate, body) {
204
+ const data = Buffer.isBuffer(body) ? body : Buffer.from(JSON.stringify(body));
205
+ // Validate POM if uploading .pom file
206
+ if (coordinate.extension === 'pom') {
207
+ const pomValid = validatePom(data.toString('utf-8'));
208
+ if (!pomValid) {
209
+ return {
210
+ status: 400,
211
+ headers: {},
212
+ body: { error: 'INVALID_POM', message: 'Invalid POM file' },
213
+ };
214
+ }
215
+ // Verify GAV matches path
216
+ const pomGAV = extractGAVFromPom(data.toString('utf-8'));
217
+ if (pomGAV && (pomGAV.groupId !== groupId || pomGAV.artifactId !== artifactId || pomGAV.version !== version)) {
218
+ return {
219
+ status: 400,
220
+ headers: {},
221
+ body: { error: 'GAV_MISMATCH', message: 'POM coordinates do not match upload path' },
222
+ };
223
+ }
224
+ }
225
+ // Store the artifact
226
+ await this.storage.putMavenArtifact(groupId, artifactId, version, filename, data);
227
+ // Generate and store checksums
228
+ const checksums = await calculateChecksums(data);
229
+ await this.storeChecksums(groupId, artifactId, version, filename, checksums);
230
+ // Update maven-metadata.xml if this is a primary artifact (jar, pom, war)
231
+ if (['jar', 'pom', 'war', 'ear', 'aar'].includes(coordinate.extension)) {
232
+ await this.updateMetadata(groupId, artifactId, version);
233
+ }
234
+ return {
235
+ status: 201,
236
+ headers: {
237
+ 'Location': `${this.registryUrl}/${gavToPath(groupId, artifactId, version)}/${filename}`,
238
+ },
239
+ body: { success: true, message: 'Artifact uploaded successfully' },
240
+ };
241
+ }
242
+ async deleteArtifact(groupId, artifactId, version, filename) {
243
+ const exists = await this.storage.mavenArtifactExists(groupId, artifactId, version, filename);
244
+ if (!exists) {
245
+ return {
246
+ status: 404,
247
+ headers: {},
248
+ body: { error: 'NOT_FOUND', message: 'Artifact not found' },
249
+ };
250
+ }
251
+ await this.storage.deleteMavenArtifact(groupId, artifactId, version, filename);
252
+ // Also delete checksums
253
+ for (const ext of ['md5', 'sha1', 'sha256', 'sha512']) {
254
+ const checksumFile = `${filename}.${ext}`;
255
+ const checksumExists = await this.storage.mavenArtifactExists(groupId, artifactId, version, checksumFile);
256
+ if (checksumExists) {
257
+ await this.storage.deleteMavenArtifact(groupId, artifactId, version, checksumFile);
258
+ }
259
+ }
260
+ return {
261
+ status: 204,
262
+ headers: {},
263
+ body: null,
264
+ };
265
+ }
266
+ // ========================================================================
267
+ // CHECKSUM OPERATIONS
268
+ // ========================================================================
269
+ async getChecksum(groupId, artifactId, version, coordinate, fullPath) {
270
+ // Extract the filename from the full path (last component)
271
+ // The fullPath might be something like /com/example/test/test-artifact/1.0.0/test-artifact-1.0.0.jar.md5
272
+ const pathParts = fullPath.split('/');
273
+ const checksumFilename = pathParts[pathParts.length - 1];
274
+ const data = await this.storage.getMavenArtifact(groupId, artifactId, version, checksumFilename);
275
+ if (!data) {
276
+ return {
277
+ status: 404,
278
+ headers: {},
279
+ body: { error: 'NOT_FOUND', message: 'Checksum not found' },
280
+ };
281
+ }
282
+ return {
283
+ status: 200,
284
+ headers: {
285
+ 'Content-Type': 'text/plain',
286
+ 'Content-Length': data.length.toString(),
287
+ },
288
+ body: data,
289
+ };
290
+ }
291
+ async storeChecksums(groupId, artifactId, version, filename, checksums) {
292
+ // Store each checksum as a separate file
293
+ await this.storage.putMavenArtifact(groupId, artifactId, version, `${filename}.md5`, Buffer.from(checksums.md5, 'utf-8'));
294
+ await this.storage.putMavenArtifact(groupId, artifactId, version, `${filename}.sha1`, Buffer.from(checksums.sha1, 'utf-8'));
295
+ if (checksums.sha256) {
296
+ await this.storage.putMavenArtifact(groupId, artifactId, version, `${filename}.sha256`, Buffer.from(checksums.sha256, 'utf-8'));
297
+ }
298
+ if (checksums.sha512) {
299
+ await this.storage.putMavenArtifact(groupId, artifactId, version, `${filename}.sha512`, Buffer.from(checksums.sha512, 'utf-8'));
300
+ }
301
+ }
302
+ // ========================================================================
303
+ // METADATA OPERATIONS
304
+ // ========================================================================
305
+ async getMetadata(groupId, artifactId) {
306
+ const metadataBuffer = await this.storage.getMavenMetadata(groupId, artifactId);
307
+ if (!metadataBuffer) {
308
+ // Generate empty metadata if none exists
309
+ const emptyMetadata = {
310
+ groupId,
311
+ artifactId,
312
+ versioning: {
313
+ versions: [],
314
+ lastUpdated: formatMavenTimestamp(new Date()),
315
+ },
316
+ };
317
+ const xml = generateMetadataXml(emptyMetadata);
318
+ return {
319
+ status: 200,
320
+ headers: {
321
+ 'Content-Type': 'application/xml',
322
+ 'Content-Length': xml.length.toString(),
323
+ },
324
+ body: Buffer.from(xml, 'utf-8'),
325
+ };
326
+ }
327
+ return {
328
+ status: 200,
329
+ headers: {
330
+ 'Content-Type': 'application/xml',
331
+ 'Content-Length': metadataBuffer.length.toString(),
332
+ },
333
+ body: metadataBuffer,
334
+ };
335
+ }
336
+ async updateMetadata(groupId, artifactId, newVersion) {
337
+ // Get existing metadata or create new
338
+ const existingBuffer = await this.storage.getMavenMetadata(groupId, artifactId);
339
+ let metadata;
340
+ if (existingBuffer) {
341
+ const parsed = parseMetadataXml(existingBuffer.toString('utf-8'));
342
+ if (parsed) {
343
+ metadata = parsed;
344
+ }
345
+ else {
346
+ // Create new if parsing failed
347
+ metadata = {
348
+ groupId,
349
+ artifactId,
350
+ versioning: {
351
+ versions: [],
352
+ lastUpdated: formatMavenTimestamp(new Date()),
353
+ },
354
+ };
355
+ }
356
+ }
357
+ else {
358
+ metadata = {
359
+ groupId,
360
+ artifactId,
361
+ versioning: {
362
+ versions: [],
363
+ lastUpdated: formatMavenTimestamp(new Date()),
364
+ },
365
+ };
366
+ }
367
+ // Add new version if not already present
368
+ if (!metadata.versioning.versions.includes(newVersion)) {
369
+ metadata.versioning.versions.push(newVersion);
370
+ metadata.versioning.versions.sort(); // Sort versions
371
+ }
372
+ // Update latest and release
373
+ const versions = metadata.versioning.versions;
374
+ metadata.versioning.latest = versions[versions.length - 1];
375
+ // Release is the latest non-SNAPSHOT version
376
+ const releaseVersions = versions.filter(v => !isSnapshot(v));
377
+ if (releaseVersions.length > 0) {
378
+ metadata.versioning.release = releaseVersions[releaseVersions.length - 1];
379
+ }
380
+ // Update timestamp
381
+ metadata.versioning.lastUpdated = formatMavenTimestamp(new Date());
382
+ // Generate and store XML
383
+ const xml = generateMetadataXml(metadata);
384
+ await this.storage.putMavenMetadata(groupId, artifactId, Buffer.from(xml, 'utf-8'));
385
+ // Note: Checksums for maven-metadata.xml are optional and not critical
386
+ // They would need special handling since metadata uses a different storage path
387
+ }
388
+ // ========================================================================
389
+ // UTILITY METHODS
390
+ // ========================================================================
391
+ getContentType(extension) {
392
+ const contentTypes = {
393
+ 'jar': 'application/java-archive',
394
+ 'war': 'application/java-archive',
395
+ 'ear': 'application/java-archive',
396
+ 'aar': 'application/java-archive',
397
+ 'pom': 'application/xml',
398
+ 'xml': 'application/xml',
399
+ 'md5': 'text/plain',
400
+ 'sha1': 'text/plain',
401
+ 'sha256': 'text/plain',
402
+ 'sha512': 'text/plain',
403
+ };
404
+ return contentTypes[extension] || 'application/octet-stream';
405
+ }
406
+ }
407
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5tYXZlbnJlZ2lzdHJ5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvbWF2ZW4vY2xhc3Nlcy5tYXZlbnJlZ2lzdHJ5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUVILE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUsvRCxPQUFPLEVBQ0wsU0FBUyxFQUNULGFBQWEsRUFDYixrQkFBa0IsRUFDbEIsbUJBQW1CLEVBQ25CLGdCQUFnQixFQUNoQixvQkFBb0IsRUFDcEIsVUFBVSxFQUNWLFdBQVcsRUFDWCxpQkFBaUIsRUFDakIsU0FBUyxHQUNWLE1BQU0sb0JBQW9CLENBQUM7QUFFNUI7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLGFBQWMsU0FBUSxZQUFZO0lBQ3JDLE9BQU8sQ0FBa0I7SUFDekIsV0FBVyxDQUFjO0lBQ3pCLFFBQVEsR0FBVyxRQUFRLENBQUM7SUFDNUIsV0FBVyxDQUFTO0lBRTVCLFlBQ0UsT0FBd0IsRUFDeEIsV0FBd0IsRUFDeEIsUUFBZ0IsRUFDaEIsV0FBbUI7UUFFbkIsS0FBSyxFQUFFLENBQUM7UUFDUixJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztRQUN2QixJQUFJLENBQUMsV0FBVyxHQUFHLFdBQVcsQ0FBQztRQUMvQixJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztRQUN6QixJQUFJLENBQUMsV0FBVyxHQUFHLFdBQVcsQ0FBQztJQUNqQyxDQUFDO0lBRU0sS0FBSyxDQUFDLElBQUk7UUFDZiw2Q0FBNkM7SUFDL0MsQ0FBQztJQUVNLFdBQVc7UUFDaEIsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDO0lBQ3ZCLENBQUM7SUFFTSxLQUFLLENBQUMsYUFBYSxDQUFDLE9BQXdCO1FBQ2pELDRCQUE0QjtRQUM1QixNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLEVB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
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Maven helper utilities
3
+ * Path conversion, XML generation, checksum calculation
4
+ */
5
+ import type { IMavenCoordinate, IMavenMetadata, IChecksums } from './interfaces.maven.js';
6
+ /**
7
+ * Convert Maven GAV coordinates to storage path
8
+ * Example: com.example:my-lib:1.0.0 → com/example/my-lib/1.0.0
9
+ */
10
+ export declare function gavToPath(groupId: string, artifactId: string, version?: string): string;
11
+ /**
12
+ * Parse Maven path to GAV coordinates
13
+ * Example: com/example/my-lib/1.0.0/my-lib-1.0.0.jar → {groupId, artifactId, version, ...}
14
+ */
15
+ export declare function pathToGAV(path: string): IMavenCoordinate | null;
16
+ /**
17
+ * Parse Maven artifact filename
18
+ * Example: my-lib-1.0.0-sources.jar → {classifier: 'sources', extension: 'jar'}
19
+ * Example: my-lib-1.0.0.jar.md5 → {extension: 'md5'}
20
+ */
21
+ export declare function parseFilename(filename: string, artifactId: string, version: string): {
22
+ classifier?: string;
23
+ extension: string;
24
+ } | null;
25
+ /**
26
+ * Build Maven artifact filename
27
+ * Example: {artifactId: 'my-lib', version: '1.0.0', classifier: 'sources', extension: 'jar'}
28
+ * → 'my-lib-1.0.0-sources.jar'
29
+ */
30
+ export declare function buildFilename(coordinate: IMavenCoordinate): string;
31
+ /**
32
+ * Calculate checksums for Maven artifact
33
+ * Returns MD5, SHA-1, SHA-256, SHA-512
34
+ */
35
+ export declare function calculateChecksums(data: Buffer): Promise<IChecksums>;
36
+ /**
37
+ * Generate maven-metadata.xml from metadata object
38
+ */
39
+ export declare function generateMetadataXml(metadata: IMavenMetadata): string;
40
+ /**
41
+ * Parse maven-metadata.xml to metadata object
42
+ * Basic XML parsing for Maven metadata
43
+ */
44
+ export declare function parseMetadataXml(xml: string): IMavenMetadata | null;
45
+ /**
46
+ * Format timestamp in Maven format: yyyyMMddHHmmss
47
+ */
48
+ export declare function formatMavenTimestamp(date: Date): string;
49
+ /**
50
+ * Format SNAPSHOT timestamp: yyyyMMdd.HHmmss
51
+ */
52
+ export declare function formatSnapshotTimestamp(date: Date): string;
53
+ /**
54
+ * Check if version is a SNAPSHOT
55
+ */
56
+ export declare function isSnapshot(version: string): boolean;
57
+ /**
58
+ * Validate POM basic structure
59
+ */
60
+ export declare function validatePom(pomXml: string): boolean;
61
+ /**
62
+ * Extract GAV from POM XML
63
+ */
64
+ export declare function extractGAVFromPom(pomXml: string): {
65
+ groupId: string;
66
+ artifactId: string;
67
+ version: string;
68
+ } | null;