@push.rocks/smartregistry 2.2.3 → 2.4.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.
Files changed (110) hide show
  1. package/dist_ts/00_commitinfo_data.js +1 -1
  2. package/dist_ts/cargo/classes.cargoregistry.d.ts +7 -1
  3. package/dist_ts/cargo/classes.cargoregistry.js +42 -4
  4. package/dist_ts/cargo/classes.cargoupstream.d.ts +44 -0
  5. package/dist_ts/cargo/classes.cargoupstream.js +129 -0
  6. package/dist_ts/cargo/index.d.ts +1 -0
  7. package/dist_ts/cargo/index.js +2 -1
  8. package/dist_ts/classes.smartregistry.d.ts +33 -2
  9. package/dist_ts/classes.smartregistry.js +45 -12
  10. package/dist_ts/composer/classes.composerregistry.d.ts +7 -1
  11. package/dist_ts/composer/classes.composerregistry.js +34 -3
  12. package/dist_ts/composer/classes.composerupstream.d.ts +40 -0
  13. package/dist_ts/composer/classes.composerupstream.js +159 -0
  14. package/dist_ts/composer/index.d.ts +1 -0
  15. package/dist_ts/composer/index.js +2 -1
  16. package/dist_ts/core/classes.authmanager.d.ts +30 -80
  17. package/dist_ts/core/classes.authmanager.js +63 -337
  18. package/dist_ts/core/classes.defaultauthprovider.d.ts +78 -0
  19. package/dist_ts/core/classes.defaultauthprovider.js +311 -0
  20. package/dist_ts/core/classes.registrystorage.d.ts +70 -4
  21. package/dist_ts/core/classes.registrystorage.js +165 -5
  22. package/dist_ts/core/index.d.ts +3 -0
  23. package/dist_ts/core/index.js +7 -2
  24. package/dist_ts/core/interfaces.auth.d.ts +83 -0
  25. package/dist_ts/core/interfaces.auth.js +2 -0
  26. package/dist_ts/core/interfaces.core.d.ts +38 -0
  27. package/dist_ts/core/interfaces.storage.d.ts +120 -0
  28. package/dist_ts/core/interfaces.storage.js +2 -0
  29. package/dist_ts/index.d.ts +1 -0
  30. package/dist_ts/index.js +3 -1
  31. package/dist_ts/maven/classes.mavenregistry.d.ts +12 -1
  32. package/dist_ts/maven/classes.mavenregistry.js +69 -4
  33. package/dist_ts/maven/classes.mavenupstream.d.ts +45 -0
  34. package/dist_ts/maven/classes.mavenupstream.js +153 -0
  35. package/dist_ts/maven/index.d.ts +1 -0
  36. package/dist_ts/maven/index.js +2 -1
  37. package/dist_ts/npm/classes.npmregistry.d.ts +3 -1
  38. package/dist_ts/npm/classes.npmregistry.js +55 -6
  39. package/dist_ts/npm/classes.npmupstream.d.ts +51 -0
  40. package/dist_ts/npm/classes.npmupstream.js +206 -0
  41. package/dist_ts/npm/index.d.ts +1 -0
  42. package/dist_ts/npm/index.js +2 -1
  43. package/dist_ts/oci/classes.ociregistry.d.ts +4 -1
  44. package/dist_ts/oci/classes.ociregistry.js +78 -17
  45. package/dist_ts/oci/classes.ociupstream.d.ts +62 -0
  46. package/dist_ts/oci/classes.ociupstream.js +206 -0
  47. package/dist_ts/oci/index.d.ts +1 -0
  48. package/dist_ts/oci/index.js +2 -1
  49. package/dist_ts/plugins.d.ts +4 -1
  50. package/dist_ts/plugins.js +6 -2
  51. package/dist_ts/pypi/classes.pypiregistry.d.ts +7 -1
  52. package/dist_ts/pypi/classes.pypiregistry.js +60 -4
  53. package/dist_ts/pypi/classes.pypiupstream.d.ts +48 -0
  54. package/dist_ts/pypi/classes.pypiupstream.js +165 -0
  55. package/dist_ts/pypi/index.d.ts +1 -0
  56. package/dist_ts/pypi/index.js +2 -1
  57. package/dist_ts/rubygems/classes.rubygemsregistry.d.ts +7 -1
  58. package/dist_ts/rubygems/classes.rubygemsregistry.js +35 -4
  59. package/dist_ts/rubygems/classes.rubygemsupstream.d.ts +47 -0
  60. package/dist_ts/rubygems/classes.rubygemsupstream.js +184 -0
  61. package/dist_ts/rubygems/index.d.ts +1 -0
  62. package/dist_ts/rubygems/index.js +2 -1
  63. package/dist_ts/upstream/classes.baseupstream.d.ts +112 -0
  64. package/dist_ts/upstream/classes.baseupstream.js +411 -0
  65. package/dist_ts/upstream/classes.circuitbreaker.d.ts +111 -0
  66. package/dist_ts/upstream/classes.circuitbreaker.js +192 -0
  67. package/dist_ts/upstream/classes.upstreamcache.d.ts +170 -0
  68. package/dist_ts/upstream/classes.upstreamcache.js +485 -0
  69. package/dist_ts/upstream/index.d.ts +6 -0
  70. package/dist_ts/upstream/index.js +7 -0
  71. package/dist_ts/upstream/interfaces.upstream.d.ts +169 -0
  72. package/dist_ts/upstream/interfaces.upstream.js +23 -0
  73. package/package.json +4 -2
  74. package/ts/00_commitinfo_data.ts +1 -1
  75. package/ts/cargo/classes.cargoregistry.ts +48 -3
  76. package/ts/cargo/classes.cargoupstream.ts +159 -0
  77. package/ts/cargo/index.ts +1 -0
  78. package/ts/classes.smartregistry.ts +88 -11
  79. package/ts/composer/classes.composerregistry.ts +39 -2
  80. package/ts/composer/classes.composerupstream.ts +200 -0
  81. package/ts/composer/index.ts +1 -0
  82. package/ts/core/classes.authmanager.ts +74 -412
  83. package/ts/core/classes.defaultauthprovider.ts +393 -0
  84. package/ts/core/classes.registrystorage.ts +199 -5
  85. package/ts/core/index.ts +8 -1
  86. package/ts/core/interfaces.auth.ts +91 -0
  87. package/ts/core/interfaces.core.ts +42 -0
  88. package/ts/core/interfaces.storage.ts +130 -0
  89. package/ts/index.ts +3 -0
  90. package/ts/maven/classes.mavenregistry.ts +84 -3
  91. package/ts/maven/classes.mavenupstream.ts +220 -0
  92. package/ts/maven/index.ts +1 -0
  93. package/ts/npm/classes.npmregistry.ts +61 -5
  94. package/ts/npm/classes.npmupstream.ts +260 -0
  95. package/ts/npm/index.ts +1 -0
  96. package/ts/oci/classes.ociregistry.ts +89 -17
  97. package/ts/oci/classes.ociupstream.ts +263 -0
  98. package/ts/oci/index.ts +1 -0
  99. package/ts/plugins.ts +7 -1
  100. package/ts/pypi/classes.pypiregistry.ts +68 -3
  101. package/ts/pypi/classes.pypiupstream.ts +211 -0
  102. package/ts/pypi/index.ts +1 -0
  103. package/ts/rubygems/classes.rubygemsregistry.ts +40 -3
  104. package/ts/rubygems/classes.rubygemsupstream.ts +230 -0
  105. package/ts/rubygems/index.ts +1 -0
  106. package/ts/upstream/classes.baseupstream.ts +526 -0
  107. package/ts/upstream/classes.circuitbreaker.ts +238 -0
  108. package/ts/upstream/classes.upstreamcache.ts +626 -0
  109. package/ts/upstream/index.ts +11 -0
  110. package/ts/upstream/interfaces.upstream.ts +195 -0
@@ -7,6 +7,7 @@ import { BaseRegistry } from '../core/classes.baseregistry.js';
7
7
  import type { RegistryStorage } from '../core/classes.registrystorage.js';
8
8
  import type { AuthManager } from '../core/classes.authmanager.js';
9
9
  import type { IRequestContext, IResponse, IAuthToken } from '../core/interfaces.core.js';
10
+ import type { IProtocolUpstreamConfig } from '../upstream/interfaces.upstream.js';
10
11
  import { isBinaryData, toBuffer } from '../core/helpers.buffer.js';
11
12
  import type {
12
13
  IComposerPackage,
@@ -22,24 +23,41 @@ import {
22
23
  generatePackagesJson,
23
24
  sortVersions,
24
25
  } from './helpers.composer.js';
26
+ import { ComposerUpstream } from './classes.composerupstream.js';
25
27
 
26
28
  export class ComposerRegistry extends BaseRegistry {
27
29
  private storage: RegistryStorage;
28
30
  private authManager: AuthManager;
29
31
  private basePath: string = '/composer';
30
32
  private registryUrl: string;
33
+ private upstream: ComposerUpstream | null = null;
31
34
 
32
35
  constructor(
33
36
  storage: RegistryStorage,
34
37
  authManager: AuthManager,
35
38
  basePath: string = '/composer',
36
- registryUrl: string = 'http://localhost:5000/composer'
39
+ registryUrl: string = 'http://localhost:5000/composer',
40
+ upstreamConfig?: IProtocolUpstreamConfig
37
41
  ) {
38
42
  super();
39
43
  this.storage = storage;
40
44
  this.authManager = authManager;
41
45
  this.basePath = basePath;
42
46
  this.registryUrl = registryUrl;
47
+
48
+ // Initialize upstream if configured
49
+ if (upstreamConfig?.enabled) {
50
+ this.upstream = new ComposerUpstream(upstreamConfig);
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Clean up resources (timers, connections, etc.)
56
+ */
57
+ public destroy(): void {
58
+ if (this.upstream) {
59
+ this.upstream.stop();
60
+ }
43
61
  }
44
62
 
45
63
  public async init(): Promise<void> {
@@ -161,7 +179,26 @@ export class ComposerRegistry extends BaseRegistry {
161
179
  token: IAuthToken | null
162
180
  ): Promise<IResponse> {
163
181
  // Read operations are public, no authentication required
164
- const metadata = await this.storage.getComposerPackageMetadata(vendorPackage);
182
+ let metadata = await this.storage.getComposerPackageMetadata(vendorPackage);
183
+
184
+ // Try upstream if not found locally
185
+ if (!metadata && this.upstream) {
186
+ const [vendor, packageName] = vendorPackage.split('/');
187
+ if (vendor && packageName) {
188
+ const upstreamMetadata = includeDev
189
+ ? await this.upstream.fetchPackageDevMetadata(vendor, packageName)
190
+ : await this.upstream.fetchPackageMetadata(vendor, packageName);
191
+
192
+ if (upstreamMetadata && upstreamMetadata.packages) {
193
+ // Store upstream metadata locally
194
+ metadata = {
195
+ packages: upstreamMetadata.packages,
196
+ lastModified: new Date().toUTCString(),
197
+ };
198
+ await this.storage.putComposerPackageMetadata(vendorPackage, metadata);
199
+ }
200
+ }
201
+ }
165
202
 
166
203
  if (!metadata) {
167
204
  return {
@@ -0,0 +1,200 @@
1
+ import * as plugins from '../plugins.js';
2
+ import { BaseUpstream } from '../upstream/classes.baseupstream.js';
3
+ import type {
4
+ IProtocolUpstreamConfig,
5
+ IUpstreamFetchContext,
6
+ IUpstreamRegistryConfig,
7
+ } from '../upstream/interfaces.upstream.js';
8
+
9
+ /**
10
+ * Composer-specific upstream implementation.
11
+ *
12
+ * Handles:
13
+ * - Package metadata fetching (packages.json, provider-includes)
14
+ * - Package version metadata (p2/{vendor}/{package}.json)
15
+ * - Dist file (zip) proxying
16
+ * - Packagist v2 API support
17
+ */
18
+ export class ComposerUpstream extends BaseUpstream {
19
+ protected readonly protocolName = 'composer';
20
+
21
+ constructor(
22
+ config: IProtocolUpstreamConfig,
23
+ logger?: plugins.smartlog.Smartlog,
24
+ ) {
25
+ super(config, logger);
26
+ }
27
+
28
+ /**
29
+ * Fetch the root packages.json from upstream.
30
+ */
31
+ public async fetchPackagesJson(): Promise<any | null> {
32
+ const context: IUpstreamFetchContext = {
33
+ protocol: 'composer',
34
+ resource: '*',
35
+ resourceType: 'root',
36
+ path: '/packages.json',
37
+ method: 'GET',
38
+ headers: {
39
+ 'accept': 'application/json',
40
+ },
41
+ query: {},
42
+ };
43
+
44
+ const result = await this.fetch(context);
45
+
46
+ if (!result || !result.success) {
47
+ return null;
48
+ }
49
+
50
+ if (Buffer.isBuffer(result.body)) {
51
+ return JSON.parse(result.body.toString('utf8'));
52
+ }
53
+
54
+ return result.body;
55
+ }
56
+
57
+ /**
58
+ * Fetch package metadata using v2 API (p2/{vendor}/{package}.json).
59
+ */
60
+ public async fetchPackageMetadata(vendor: string, packageName: string): Promise<any | null> {
61
+ const fullName = `${vendor}/${packageName}`;
62
+ const path = `/p2/${vendor}/${packageName}.json`;
63
+
64
+ const context: IUpstreamFetchContext = {
65
+ protocol: 'composer',
66
+ resource: fullName,
67
+ resourceType: 'metadata',
68
+ path,
69
+ method: 'GET',
70
+ headers: {
71
+ 'accept': 'application/json',
72
+ },
73
+ query: {},
74
+ };
75
+
76
+ const result = await this.fetch(context);
77
+
78
+ if (!result || !result.success) {
79
+ return null;
80
+ }
81
+
82
+ if (Buffer.isBuffer(result.body)) {
83
+ return JSON.parse(result.body.toString('utf8'));
84
+ }
85
+
86
+ return result.body;
87
+ }
88
+
89
+ /**
90
+ * Fetch package metadata with dev versions (p2/{vendor}/{package}~dev.json).
91
+ */
92
+ public async fetchPackageDevMetadata(vendor: string, packageName: string): Promise<any | null> {
93
+ const fullName = `${vendor}/${packageName}`;
94
+ const path = `/p2/${vendor}/${packageName}~dev.json`;
95
+
96
+ const context: IUpstreamFetchContext = {
97
+ protocol: 'composer',
98
+ resource: fullName,
99
+ resourceType: 'metadata-dev',
100
+ path,
101
+ method: 'GET',
102
+ headers: {
103
+ 'accept': 'application/json',
104
+ },
105
+ query: {},
106
+ };
107
+
108
+ const result = await this.fetch(context);
109
+
110
+ if (!result || !result.success) {
111
+ return null;
112
+ }
113
+
114
+ if (Buffer.isBuffer(result.body)) {
115
+ return JSON.parse(result.body.toString('utf8'));
116
+ }
117
+
118
+ return result.body;
119
+ }
120
+
121
+ /**
122
+ * Fetch a provider-includes file.
123
+ */
124
+ public async fetchProviderIncludes(path: string): Promise<any | null> {
125
+ const context: IUpstreamFetchContext = {
126
+ protocol: 'composer',
127
+ resource: '*',
128
+ resourceType: 'provider',
129
+ path: path.startsWith('/') ? path : `/${path}`,
130
+ method: 'GET',
131
+ headers: {
132
+ 'accept': 'application/json',
133
+ },
134
+ query: {},
135
+ };
136
+
137
+ const result = await this.fetch(context);
138
+
139
+ if (!result || !result.success) {
140
+ return null;
141
+ }
142
+
143
+ if (Buffer.isBuffer(result.body)) {
144
+ return JSON.parse(result.body.toString('utf8'));
145
+ }
146
+
147
+ return result.body;
148
+ }
149
+
150
+ /**
151
+ * Fetch a dist file (zip) from upstream.
152
+ */
153
+ public async fetchDist(url: string): Promise<Buffer | null> {
154
+ // Parse the URL to get the path
155
+ let path: string;
156
+ try {
157
+ const parsed = new URL(url);
158
+ path = parsed.pathname;
159
+ } catch {
160
+ path = url;
161
+ }
162
+
163
+ const context: IUpstreamFetchContext = {
164
+ protocol: 'composer',
165
+ resource: '*',
166
+ resourceType: 'dist',
167
+ path,
168
+ method: 'GET',
169
+ headers: {
170
+ 'accept': 'application/zip, application/octet-stream',
171
+ },
172
+ query: {},
173
+ };
174
+
175
+ const result = await this.fetch(context);
176
+
177
+ if (!result || !result.success) {
178
+ return null;
179
+ }
180
+
181
+ return Buffer.isBuffer(result.body) ? result.body : Buffer.from(result.body);
182
+ }
183
+
184
+ /**
185
+ * Override URL building for Composer-specific handling.
186
+ */
187
+ protected buildUpstreamUrl(
188
+ upstream: IUpstreamRegistryConfig,
189
+ context: IUpstreamFetchContext,
190
+ ): string {
191
+ let baseUrl = upstream.url;
192
+
193
+ // Remove trailing slash
194
+ if (baseUrl.endsWith('/')) {
195
+ baseUrl = baseUrl.slice(0, -1);
196
+ }
197
+
198
+ return `${baseUrl}${context.path}`;
199
+ }
200
+ }
@@ -4,5 +4,6 @@
4
4
  */
5
5
 
6
6
  export { ComposerRegistry } from './classes.composerregistry.js';
7
+ export { ComposerUpstream } from './classes.composerupstream.js';
7
8
  export * from './interfaces.composer.js';
8
9
  export * from './helpers.composer.js';