@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,346 @@
1
+ /**
2
+ * Maven helper utilities
3
+ * Path conversion, XML generation, checksum calculation
4
+ */
5
+
6
+ import * as plugins from '../plugins.js';
7
+ import type {
8
+ IMavenCoordinate,
9
+ IMavenMetadata,
10
+ IChecksums,
11
+ IMavenPom,
12
+ } from './interfaces.maven.js';
13
+
14
+ /**
15
+ * Convert Maven GAV coordinates to storage path
16
+ * Example: com.example:my-lib:1.0.0 → com/example/my-lib/1.0.0
17
+ */
18
+ export function gavToPath(
19
+ groupId: string,
20
+ artifactId: string,
21
+ version?: string
22
+ ): string {
23
+ const groupPath = groupId.replace(/\./g, '/');
24
+ if (version) {
25
+ return `${groupPath}/${artifactId}/${version}`;
26
+ }
27
+ return `${groupPath}/${artifactId}`;
28
+ }
29
+
30
+ /**
31
+ * Parse Maven path to GAV coordinates
32
+ * Example: com/example/my-lib/1.0.0/my-lib-1.0.0.jar → {groupId, artifactId, version, ...}
33
+ */
34
+ export function pathToGAV(path: string): IMavenCoordinate | null {
35
+ // Remove leading slash if present
36
+ const cleanPath = path.startsWith('/') ? path.substring(1) : path;
37
+
38
+ // Split path into parts
39
+ const parts = cleanPath.split('/');
40
+ if (parts.length < 4) {
41
+ return null; // Not a valid artifact path
42
+ }
43
+
44
+ // Last part is filename
45
+ const filename = parts[parts.length - 1];
46
+ const version = parts[parts.length - 2];
47
+ const artifactId = parts[parts.length - 3];
48
+ const groupId = parts.slice(0, -3).join('.');
49
+
50
+ // Parse filename to extract classifier and extension
51
+ const parsed = parseFilename(filename, artifactId, version);
52
+ if (!parsed) {
53
+ return null;
54
+ }
55
+
56
+ return {
57
+ groupId,
58
+ artifactId,
59
+ version,
60
+ classifier: parsed.classifier,
61
+ extension: parsed.extension,
62
+ };
63
+ }
64
+
65
+ /**
66
+ * Parse Maven artifact filename
67
+ * Example: my-lib-1.0.0-sources.jar → {classifier: 'sources', extension: 'jar'}
68
+ * Example: my-lib-1.0.0.jar.md5 → {extension: 'md5'}
69
+ */
70
+ export function parseFilename(
71
+ filename: string,
72
+ artifactId: string,
73
+ version: string
74
+ ): { classifier?: string; extension: string } | null {
75
+ // Expected format: {artifactId}-{version}[-{classifier}].{extension}[.checksum]
76
+ const prefix = `${artifactId}-${version}`;
77
+
78
+ if (!filename.startsWith(prefix)) {
79
+ return null;
80
+ }
81
+
82
+ let remainder = filename.substring(prefix.length);
83
+
84
+ // Check if this is a checksum file (double extension like .jar.md5)
85
+ const checksumExtensions = ['md5', 'sha1', 'sha256', 'sha512'];
86
+ const lastDotIndex = remainder.lastIndexOf('.');
87
+ if (lastDotIndex !== -1) {
88
+ const possibleChecksum = remainder.substring(lastDotIndex + 1);
89
+ if (checksumExtensions.includes(possibleChecksum)) {
90
+ // This is a checksum file - just return the checksum extension
91
+ // The base artifact extension doesn't matter for checksum retrieval
92
+ return { extension: possibleChecksum };
93
+ }
94
+ }
95
+
96
+ // Regular artifact file parsing
97
+ const dotIndex = remainder.lastIndexOf('.');
98
+ if (dotIndex === -1) {
99
+ return null; // No extension
100
+ }
101
+
102
+ const extension = remainder.substring(dotIndex + 1);
103
+ const classifierPart = remainder.substring(0, dotIndex);
104
+
105
+ if (classifierPart.length === 0) {
106
+ // No classifier
107
+ return { extension };
108
+ }
109
+
110
+ if (classifierPart.startsWith('-')) {
111
+ // Has classifier
112
+ const classifier = classifierPart.substring(1);
113
+ return { classifier, extension };
114
+ }
115
+
116
+ return null; // Invalid format
117
+ }
118
+
119
+ /**
120
+ * Build Maven artifact filename
121
+ * Example: {artifactId: 'my-lib', version: '1.0.0', classifier: 'sources', extension: 'jar'}
122
+ * → 'my-lib-1.0.0-sources.jar'
123
+ */
124
+ export function buildFilename(coordinate: IMavenCoordinate): string {
125
+ const { artifactId, version, classifier, extension } = coordinate;
126
+
127
+ let filename = `${artifactId}-${version}`;
128
+ if (classifier) {
129
+ filename += `-${classifier}`;
130
+ }
131
+ filename += `.${extension}`;
132
+
133
+ return filename;
134
+ }
135
+
136
+ /**
137
+ * Calculate checksums for Maven artifact
138
+ * Returns MD5, SHA-1, SHA-256, SHA-512
139
+ */
140
+ export async function calculateChecksums(data: Buffer): Promise<IChecksums> {
141
+ const crypto = await import('crypto');
142
+
143
+ return {
144
+ md5: crypto.createHash('md5').update(data).digest('hex'),
145
+ sha1: crypto.createHash('sha1').update(data).digest('hex'),
146
+ sha256: crypto.createHash('sha256').update(data).digest('hex'),
147
+ sha512: crypto.createHash('sha512').update(data).digest('hex'),
148
+ };
149
+ }
150
+
151
+ /**
152
+ * Generate maven-metadata.xml from metadata object
153
+ */
154
+ export function generateMetadataXml(metadata: IMavenMetadata): string {
155
+ const { groupId, artifactId, versioning } = metadata;
156
+ const { latest, release, versions, lastUpdated, snapshot, snapshotVersions } = versioning;
157
+
158
+ let xml = '<?xml version="1.0" encoding="UTF-8"?>\n';
159
+ xml += '<metadata>\n';
160
+ xml += ` <groupId>${escapeXml(groupId)}</groupId>\n`;
161
+ xml += ` <artifactId>${escapeXml(artifactId)}</artifactId>\n`;
162
+
163
+ // Add version if SNAPSHOT
164
+ if (snapshot) {
165
+ const snapshotVersion = versions[versions.length - 1]; // Assume last version is the SNAPSHOT
166
+ xml += ` <version>${escapeXml(snapshotVersion)}</version>\n`;
167
+ }
168
+
169
+ xml += ' <versioning>\n';
170
+
171
+ if (latest) {
172
+ xml += ` <latest>${escapeXml(latest)}</latest>\n`;
173
+ }
174
+
175
+ if (release) {
176
+ xml += ` <release>${escapeXml(release)}</release>\n`;
177
+ }
178
+
179
+ xml += ' <versions>\n';
180
+ for (const version of versions) {
181
+ xml += ` <version>${escapeXml(version)}</version>\n`;
182
+ }
183
+ xml += ' </versions>\n';
184
+
185
+ xml += ` <lastUpdated>${lastUpdated}</lastUpdated>\n`;
186
+
187
+ // Add SNAPSHOT info if present
188
+ if (snapshot) {
189
+ xml += ' <snapshot>\n';
190
+ xml += ` <timestamp>${escapeXml(snapshot.timestamp)}</timestamp>\n`;
191
+ xml += ` <buildNumber>${snapshot.buildNumber}</buildNumber>\n`;
192
+ xml += ' </snapshot>\n';
193
+ }
194
+
195
+ // Add SNAPSHOT versions if present
196
+ if (snapshotVersions && snapshotVersions.length > 0) {
197
+ xml += ' <snapshotVersions>\n';
198
+ for (const sv of snapshotVersions) {
199
+ xml += ' <snapshotVersion>\n';
200
+ if (sv.classifier) {
201
+ xml += ` <classifier>${escapeXml(sv.classifier)}</classifier>\n`;
202
+ }
203
+ xml += ` <extension>${escapeXml(sv.extension)}</extension>\n`;
204
+ xml += ` <value>${escapeXml(sv.value)}</value>\n`;
205
+ xml += ` <updated>${sv.updated}</updated>\n`;
206
+ xml += ' </snapshotVersion>\n';
207
+ }
208
+ xml += ' </snapshotVersions>\n';
209
+ }
210
+
211
+ xml += ' </versioning>\n';
212
+ xml += '</metadata>\n';
213
+
214
+ return xml;
215
+ }
216
+
217
+ /**
218
+ * Parse maven-metadata.xml to metadata object
219
+ * Basic XML parsing for Maven metadata
220
+ */
221
+ export function parseMetadataXml(xml: string): IMavenMetadata | null {
222
+ try {
223
+ // Simple regex-based parsing (for basic metadata)
224
+ // In production, use a proper XML parser
225
+
226
+ const groupIdMatch = xml.match(/<groupId>([^<]+)<\/groupId>/);
227
+ const artifactIdMatch = xml.match(/<artifactId>([^<]+)<\/artifactId>/);
228
+ const latestMatch = xml.match(/<latest>([^<]+)<\/latest>/);
229
+ const releaseMatch = xml.match(/<release>([^<]+)<\/release>/);
230
+ const lastUpdatedMatch = xml.match(/<lastUpdated>([^<]+)<\/lastUpdated>/);
231
+
232
+ if (!groupIdMatch || !artifactIdMatch) {
233
+ return null;
234
+ }
235
+
236
+ // Parse versions
237
+ const versionsMatch = xml.match(/<versions>([\s\S]*?)<\/versions>/);
238
+ const versions: string[] = [];
239
+ if (versionsMatch) {
240
+ const versionMatches = versionsMatch[1].matchAll(/<version>([^<]+)<\/version>/g);
241
+ for (const match of versionMatches) {
242
+ versions.push(match[1]);
243
+ }
244
+ }
245
+
246
+ return {
247
+ groupId: groupIdMatch[1],
248
+ artifactId: artifactIdMatch[1],
249
+ versioning: {
250
+ latest: latestMatch ? latestMatch[1] : undefined,
251
+ release: releaseMatch ? releaseMatch[1] : undefined,
252
+ versions,
253
+ lastUpdated: lastUpdatedMatch ? lastUpdatedMatch[1] : formatMavenTimestamp(new Date()),
254
+ },
255
+ };
256
+ } catch (error) {
257
+ return null;
258
+ }
259
+ }
260
+
261
+ /**
262
+ * Escape XML special characters
263
+ */
264
+ function escapeXml(str: string): string {
265
+ return str
266
+ .replace(/&/g, '&amp;')
267
+ .replace(/</g, '&lt;')
268
+ .replace(/>/g, '&gt;')
269
+ .replace(/"/g, '&quot;')
270
+ .replace(/'/g, '&apos;');
271
+ }
272
+
273
+ /**
274
+ * Format timestamp in Maven format: yyyyMMddHHmmss
275
+ */
276
+ export function formatMavenTimestamp(date: Date): string {
277
+ const year = date.getUTCFullYear();
278
+ const month = String(date.getUTCMonth() + 1).padStart(2, '0');
279
+ const day = String(date.getUTCDate()).padStart(2, '0');
280
+ const hours = String(date.getUTCHours()).padStart(2, '0');
281
+ const minutes = String(date.getUTCMinutes()).padStart(2, '0');
282
+ const seconds = String(date.getUTCSeconds()).padStart(2, '0');
283
+
284
+ return `${year}${month}${day}${hours}${minutes}${seconds}`;
285
+ }
286
+
287
+ /**
288
+ * Format SNAPSHOT timestamp: yyyyMMdd.HHmmss
289
+ */
290
+ export function formatSnapshotTimestamp(date: Date): string {
291
+ const year = date.getUTCFullYear();
292
+ const month = String(date.getUTCMonth() + 1).padStart(2, '0');
293
+ const day = String(date.getUTCDate()).padStart(2, '0');
294
+ const hours = String(date.getUTCHours()).padStart(2, '0');
295
+ const minutes = String(date.getUTCMinutes()).padStart(2, '0');
296
+ const seconds = String(date.getUTCSeconds()).padStart(2, '0');
297
+
298
+ return `${year}${month}${day}.${hours}${minutes}${seconds}`;
299
+ }
300
+
301
+ /**
302
+ * Check if version is a SNAPSHOT
303
+ */
304
+ export function isSnapshot(version: string): boolean {
305
+ return version.endsWith('-SNAPSHOT');
306
+ }
307
+
308
+ /**
309
+ * Validate POM basic structure
310
+ */
311
+ export function validatePom(pomXml: string): boolean {
312
+ try {
313
+ // Basic validation - check for required fields
314
+ return (
315
+ pomXml.includes('<groupId>') &&
316
+ pomXml.includes('<artifactId>') &&
317
+ pomXml.includes('<version>') &&
318
+ pomXml.includes('<modelVersion>')
319
+ );
320
+ } catch (error) {
321
+ return false;
322
+ }
323
+ }
324
+
325
+ /**
326
+ * Extract GAV from POM XML
327
+ */
328
+ export function extractGAVFromPom(pomXml: string): { groupId: string; artifactId: string; version: string } | null {
329
+ try {
330
+ const groupIdMatch = pomXml.match(/<groupId>([^<]+)<\/groupId>/);
331
+ const artifactIdMatch = pomXml.match(/<artifactId>([^<]+)<\/artifactId>/);
332
+ const versionMatch = pomXml.match(/<version>([^<]+)<\/version>/);
333
+
334
+ if (groupIdMatch && artifactIdMatch && versionMatch) {
335
+ return {
336
+ groupId: groupIdMatch[1],
337
+ artifactId: artifactIdMatch[1],
338
+ version: versionMatch[1],
339
+ };
340
+ }
341
+
342
+ return null;
343
+ } catch (error) {
344
+ return null;
345
+ }
346
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Maven Registry module exports
3
+ */
4
+
5
+ export { MavenRegistry } from './classes.mavenregistry.js';
6
+ export * from './interfaces.maven.js';
7
+ export * from './helpers.maven.js';
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Maven registry type definitions
3
+ * Supports Maven repository protocol for Java artifacts
4
+ */
5
+
6
+ /**
7
+ * Maven coordinate system (GAV + optional classifier)
8
+ * Example: com.example:my-library:1.0.0:sources:jar
9
+ */
10
+ export interface IMavenCoordinate {
11
+ groupId: string; // e.g., "com.example.myapp"
12
+ artifactId: string; // e.g., "my-library"
13
+ version: string; // e.g., "1.0.0" or "1.0-SNAPSHOT"
14
+ classifier?: string; // e.g., "sources", "javadoc"
15
+ extension: string; // e.g., "jar", "war", "pom"
16
+ }
17
+
18
+ /**
19
+ * Maven metadata (maven-metadata.xml) structure
20
+ * Contains version list and latest/release information
21
+ */
22
+ export interface IMavenMetadata {
23
+ groupId: string;
24
+ artifactId: string;
25
+ versioning: IMavenVersioning;
26
+ }
27
+
28
+ /**
29
+ * Maven versioning information
30
+ */
31
+ export interface IMavenVersioning {
32
+ latest?: string; // Latest version (including SNAPSHOTs)
33
+ release?: string; // Latest release version (excluding SNAPSHOTs)
34
+ versions: string[]; // List of all versions
35
+ lastUpdated: string; // Format: yyyyMMddHHmmss
36
+ snapshot?: IMavenSnapshot; // For SNAPSHOT versions
37
+ snapshotVersions?: IMavenSnapshotVersion[]; // For SNAPSHOT builds
38
+ }
39
+
40
+ /**
41
+ * SNAPSHOT build information
42
+ */
43
+ export interface IMavenSnapshot {
44
+ timestamp: string; // Format: yyyyMMdd.HHmmss
45
+ buildNumber: number; // Incremental build number
46
+ }
47
+
48
+ /**
49
+ * SNAPSHOT version entry
50
+ */
51
+ export interface IMavenSnapshotVersion {
52
+ classifier?: string;
53
+ extension: string;
54
+ value: string; // Timestamped version
55
+ updated: string; // Format: yyyyMMddHHmmss
56
+ }
57
+
58
+ /**
59
+ * Checksums for Maven artifacts
60
+ * Maven requires separate checksum files for each artifact
61
+ */
62
+ export interface IChecksums {
63
+ md5: string; // MD5 hash
64
+ sha1: string; // SHA-1 hash (required)
65
+ sha256?: string; // SHA-256 hash (optional)
66
+ sha512?: string; // SHA-512 hash (optional)
67
+ }
68
+
69
+ /**
70
+ * Maven artifact file information
71
+ */
72
+ export interface IMavenArtifactFile {
73
+ filename: string; // Full filename with extension
74
+ data: Buffer; // File content
75
+ coordinate: IMavenCoordinate; // Parsed GAV coordinates
76
+ checksums?: IChecksums; // Calculated checksums
77
+ }
78
+
79
+ /**
80
+ * Maven upload request
81
+ * Contains all files for a single version (JAR, POM, sources, etc.)
82
+ */
83
+ export interface IMavenUploadRequest {
84
+ groupId: string;
85
+ artifactId: string;
86
+ version: string;
87
+ files: IMavenArtifactFile[];
88
+ }
89
+
90
+ /**
91
+ * Maven protocol configuration
92
+ */
93
+ export interface IMavenProtocolConfig {
94
+ enabled: boolean;
95
+ basePath: string; // Default: '/maven'
96
+ features?: {
97
+ snapshots?: boolean; // Support SNAPSHOT versions (default: true)
98
+ checksums?: boolean; // Auto-generate checksums (default: true)
99
+ metadata?: boolean; // Auto-generate maven-metadata.xml (default: true)
100
+ allowedExtensions?: string[]; // Allowed file extensions (default: jar, war, pom, etc.)
101
+ };
102
+ }
103
+
104
+ /**
105
+ * Maven POM (Project Object Model) minimal structure
106
+ * Only essential fields for validation
107
+ */
108
+ export interface IMavenPom {
109
+ modelVersion: string; // Always "4.0.0"
110
+ groupId: string;
111
+ artifactId: string;
112
+ version: string;
113
+ packaging?: string; // jar, war, pom, etc.
114
+ name?: string;
115
+ description?: string;
116
+ }
117
+
118
+ /**
119
+ * Maven repository search result
120
+ */
121
+ export interface IMavenSearchResult {
122
+ groupId: string;
123
+ artifactId: string;
124
+ latestVersion: string;
125
+ versions: string[];
126
+ lastUpdated: string;
127
+ }