@push.rocks/smartregistry 2.3.0 → 2.5.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 +1 -1
- package/dist_ts/classes.smartregistry.d.ts +33 -2
- package/dist_ts/classes.smartregistry.js +38 -5
- package/dist_ts/core/classes.authmanager.d.ts +30 -80
- package/dist_ts/core/classes.authmanager.js +63 -337
- package/dist_ts/core/classes.defaultauthprovider.d.ts +78 -0
- package/dist_ts/core/classes.defaultauthprovider.js +311 -0
- package/dist_ts/core/classes.registrystorage.d.ts +70 -4
- package/dist_ts/core/classes.registrystorage.js +165 -5
- package/dist_ts/core/index.d.ts +3 -0
- package/dist_ts/core/index.js +7 -2
- package/dist_ts/core/interfaces.auth.d.ts +83 -0
- package/dist_ts/core/interfaces.auth.js +2 -0
- package/dist_ts/core/interfaces.core.d.ts +35 -0
- package/dist_ts/core/interfaces.storage.d.ts +120 -0
- package/dist_ts/core/interfaces.storage.js +2 -0
- package/dist_ts/upstream/classes.baseupstream.d.ts +2 -2
- package/dist_ts/upstream/classes.baseupstream.js +16 -14
- package/dist_ts/upstream/classes.upstreamcache.d.ts +69 -22
- package/dist_ts/upstream/classes.upstreamcache.js +207 -50
- package/package.json +1 -1
- package/readme.md +225 -1
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.smartregistry.ts +39 -4
- package/ts/core/classes.authmanager.ts +74 -412
- package/ts/core/classes.defaultauthprovider.ts +393 -0
- package/ts/core/classes.registrystorage.ts +199 -5
- package/ts/core/index.ts +8 -1
- package/ts/core/interfaces.auth.ts +91 -0
- package/ts/core/interfaces.core.ts +39 -0
- package/ts/core/interfaces.storage.ts +130 -0
- package/ts/upstream/classes.baseupstream.ts +20 -15
- package/ts/upstream/classes.upstreamcache.ts +256 -53
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { IAuthProvider, ITokenOptions } from './interfaces.auth.js';
|
|
2
|
+
import type { IAuthConfig, IAuthToken, ICredentials, TRegistryProtocol } from './interfaces.core.js';
|
|
3
|
+
/**
|
|
4
|
+
* Default in-memory authentication provider.
|
|
5
|
+
* This is the reference implementation that stores tokens in memory.
|
|
6
|
+
* For production use, implement IAuthProvider with Redis, database, or external auth.
|
|
7
|
+
*/
|
|
8
|
+
export declare class DefaultAuthProvider implements IAuthProvider {
|
|
9
|
+
private config;
|
|
10
|
+
private tokenStore;
|
|
11
|
+
private userCredentials;
|
|
12
|
+
constructor(config: IAuthConfig);
|
|
13
|
+
/**
|
|
14
|
+
* Initialize the auth provider
|
|
15
|
+
*/
|
|
16
|
+
init(): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Authenticate user credentials
|
|
19
|
+
*/
|
|
20
|
+
authenticate(credentials: ICredentials): Promise<string | null>;
|
|
21
|
+
/**
|
|
22
|
+
* Validate any token (NPM, Maven, OCI, PyPI, RubyGems, Composer, Cargo)
|
|
23
|
+
*/
|
|
24
|
+
validateToken(tokenString: string, protocol?: TRegistryProtocol): Promise<IAuthToken | null>;
|
|
25
|
+
/**
|
|
26
|
+
* Create a new token for a user
|
|
27
|
+
*/
|
|
28
|
+
createToken(userId: string, protocol: TRegistryProtocol, options?: ITokenOptions): Promise<string>;
|
|
29
|
+
/**
|
|
30
|
+
* Revoke a token
|
|
31
|
+
*/
|
|
32
|
+
revokeToken(token: string): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Check if token has permission for an action
|
|
35
|
+
*/
|
|
36
|
+
authorize(token: IAuthToken | null, resource: string, action: string): Promise<boolean>;
|
|
37
|
+
/**
|
|
38
|
+
* List all tokens for a user
|
|
39
|
+
*/
|
|
40
|
+
listUserTokens(userId: string): Promise<Array<{
|
|
41
|
+
key: string;
|
|
42
|
+
readonly: boolean;
|
|
43
|
+
created: string;
|
|
44
|
+
protocol?: TRegistryProtocol;
|
|
45
|
+
}>>;
|
|
46
|
+
/**
|
|
47
|
+
* Create an OCI JWT token
|
|
48
|
+
*/
|
|
49
|
+
private createOciToken;
|
|
50
|
+
/**
|
|
51
|
+
* Validate an OCI JWT token
|
|
52
|
+
*/
|
|
53
|
+
private validateOciToken;
|
|
54
|
+
/**
|
|
55
|
+
* Check if a scope matches a resource and action
|
|
56
|
+
*/
|
|
57
|
+
private matchesScope;
|
|
58
|
+
/**
|
|
59
|
+
* Convert unified scopes to OCI access array
|
|
60
|
+
*/
|
|
61
|
+
private scopesToOciAccess;
|
|
62
|
+
/**
|
|
63
|
+
* Convert OCI access array to unified scopes
|
|
64
|
+
*/
|
|
65
|
+
private ociAccessToScopes;
|
|
66
|
+
/**
|
|
67
|
+
* Generate UUID for tokens
|
|
68
|
+
*/
|
|
69
|
+
private generateUuid;
|
|
70
|
+
/**
|
|
71
|
+
* Check if string is a valid UUID
|
|
72
|
+
*/
|
|
73
|
+
private isValidUuid;
|
|
74
|
+
/**
|
|
75
|
+
* Hash a token for identification
|
|
76
|
+
*/
|
|
77
|
+
private hashToken;
|
|
78
|
+
}
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
import * as crypto from 'crypto';
|
|
2
|
+
/**
|
|
3
|
+
* Default in-memory authentication provider.
|
|
4
|
+
* This is the reference implementation that stores tokens in memory.
|
|
5
|
+
* For production use, implement IAuthProvider with Redis, database, or external auth.
|
|
6
|
+
*/
|
|
7
|
+
export class DefaultAuthProvider {
|
|
8
|
+
config;
|
|
9
|
+
tokenStore = new Map();
|
|
10
|
+
userCredentials = new Map(); // username -> password hash (mock)
|
|
11
|
+
constructor(config) {
|
|
12
|
+
this.config = config;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Initialize the auth provider
|
|
16
|
+
*/
|
|
17
|
+
async init() {
|
|
18
|
+
// Initialize token store (in-memory for now)
|
|
19
|
+
// In production, this could be Redis or a database
|
|
20
|
+
}
|
|
21
|
+
// ========================================================================
|
|
22
|
+
// IAuthProvider Implementation
|
|
23
|
+
// ========================================================================
|
|
24
|
+
/**
|
|
25
|
+
* Authenticate user credentials
|
|
26
|
+
*/
|
|
27
|
+
async authenticate(credentials) {
|
|
28
|
+
// Mock authentication - in production, verify against database/LDAP
|
|
29
|
+
const storedPassword = this.userCredentials.get(credentials.username);
|
|
30
|
+
if (!storedPassword) {
|
|
31
|
+
// Auto-register for testing (remove in production)
|
|
32
|
+
this.userCredentials.set(credentials.username, credentials.password);
|
|
33
|
+
return credentials.username;
|
|
34
|
+
}
|
|
35
|
+
if (storedPassword === credentials.password) {
|
|
36
|
+
return credentials.username;
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Validate any token (NPM, Maven, OCI, PyPI, RubyGems, Composer, Cargo)
|
|
42
|
+
*/
|
|
43
|
+
async validateToken(tokenString, protocol) {
|
|
44
|
+
// OCI uses JWT (contains dots), not UUID - check first if OCI is expected
|
|
45
|
+
if (protocol === 'oci' || tokenString.includes('.')) {
|
|
46
|
+
const ociToken = await this.validateOciToken(tokenString);
|
|
47
|
+
if (ociToken && (!protocol || protocol === 'oci')) {
|
|
48
|
+
return ociToken;
|
|
49
|
+
}
|
|
50
|
+
// If protocol was explicitly OCI but validation failed, return null
|
|
51
|
+
if (protocol === 'oci') {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// UUID-based tokens: single O(1) Map lookup
|
|
56
|
+
if (this.isValidUuid(tokenString)) {
|
|
57
|
+
const authToken = this.tokenStore.get(tokenString);
|
|
58
|
+
if (authToken) {
|
|
59
|
+
// If protocol specified, verify it matches
|
|
60
|
+
if (protocol && authToken.type !== protocol) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
// Check expiration
|
|
64
|
+
if (authToken.expiresAt && authToken.expiresAt < new Date()) {
|
|
65
|
+
this.tokenStore.delete(tokenString);
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
return authToken;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Create a new token for a user
|
|
75
|
+
*/
|
|
76
|
+
async createToken(userId, protocol, options) {
|
|
77
|
+
// OCI tokens use JWT
|
|
78
|
+
if (protocol === 'oci') {
|
|
79
|
+
return this.createOciToken(userId, options?.scopes || ['oci:*:*:*'], options?.expiresIn || 3600);
|
|
80
|
+
}
|
|
81
|
+
// All other protocols use UUID tokens
|
|
82
|
+
const token = this.generateUuid();
|
|
83
|
+
const scopes = options?.scopes || (options?.readonly
|
|
84
|
+
? [`${protocol}:*:*:read`]
|
|
85
|
+
: [`${protocol}:*:*:*`]);
|
|
86
|
+
const authToken = {
|
|
87
|
+
type: protocol,
|
|
88
|
+
userId,
|
|
89
|
+
scopes,
|
|
90
|
+
readonly: options?.readonly,
|
|
91
|
+
expiresAt: options?.expiresIn ? new Date(Date.now() + options.expiresIn * 1000) : undefined,
|
|
92
|
+
metadata: {
|
|
93
|
+
created: new Date().toISOString(),
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
this.tokenStore.set(token, authToken);
|
|
97
|
+
return token;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Revoke a token
|
|
101
|
+
*/
|
|
102
|
+
async revokeToken(token) {
|
|
103
|
+
this.tokenStore.delete(token);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Check if token has permission for an action
|
|
107
|
+
*/
|
|
108
|
+
async authorize(token, resource, action) {
|
|
109
|
+
if (!token) {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
// Check readonly flag
|
|
113
|
+
if (token.readonly && ['write', 'push', 'delete'].includes(action)) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
// Check scopes
|
|
117
|
+
for (const scope of token.scopes) {
|
|
118
|
+
if (this.matchesScope(scope, resource, action)) {
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* List all tokens for a user
|
|
126
|
+
*/
|
|
127
|
+
async listUserTokens(userId) {
|
|
128
|
+
const tokens = [];
|
|
129
|
+
for (const [token, authToken] of this.tokenStore.entries()) {
|
|
130
|
+
if (authToken.userId === userId) {
|
|
131
|
+
tokens.push({
|
|
132
|
+
key: this.hashToken(token),
|
|
133
|
+
readonly: authToken.readonly || false,
|
|
134
|
+
created: authToken.metadata?.created || 'unknown',
|
|
135
|
+
protocol: authToken.type,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return tokens;
|
|
140
|
+
}
|
|
141
|
+
// ========================================================================
|
|
142
|
+
// OCI JWT Token Methods
|
|
143
|
+
// ========================================================================
|
|
144
|
+
/**
|
|
145
|
+
* Create an OCI JWT token
|
|
146
|
+
*/
|
|
147
|
+
async createOciToken(userId, scopes, expiresIn = 3600) {
|
|
148
|
+
if (!this.config.ociTokens?.enabled) {
|
|
149
|
+
throw new Error('OCI tokens are not enabled');
|
|
150
|
+
}
|
|
151
|
+
const now = Math.floor(Date.now() / 1000);
|
|
152
|
+
const payload = {
|
|
153
|
+
iss: this.config.ociTokens.realm,
|
|
154
|
+
sub: userId,
|
|
155
|
+
aud: this.config.ociTokens.service,
|
|
156
|
+
exp: now + expiresIn,
|
|
157
|
+
nbf: now,
|
|
158
|
+
iat: now,
|
|
159
|
+
access: this.scopesToOciAccess(scopes),
|
|
160
|
+
};
|
|
161
|
+
// Create JWT with HMAC-SHA256 signature
|
|
162
|
+
const header = { alg: 'HS256', typ: 'JWT' };
|
|
163
|
+
const headerB64 = Buffer.from(JSON.stringify(header)).toString('base64url');
|
|
164
|
+
const payloadB64 = Buffer.from(JSON.stringify(payload)).toString('base64url');
|
|
165
|
+
const signature = crypto
|
|
166
|
+
.createHmac('sha256', this.config.jwtSecret)
|
|
167
|
+
.update(`${headerB64}.${payloadB64}`)
|
|
168
|
+
.digest('base64url');
|
|
169
|
+
return `${headerB64}.${payloadB64}.${signature}`;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Validate an OCI JWT token
|
|
173
|
+
*/
|
|
174
|
+
async validateOciToken(jwt) {
|
|
175
|
+
try {
|
|
176
|
+
const parts = jwt.split('.');
|
|
177
|
+
if (parts.length !== 3) {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
const [headerB64, payloadB64, signatureB64] = parts;
|
|
181
|
+
// Verify signature
|
|
182
|
+
const expectedSignature = crypto
|
|
183
|
+
.createHmac('sha256', this.config.jwtSecret)
|
|
184
|
+
.update(`${headerB64}.${payloadB64}`)
|
|
185
|
+
.digest('base64url');
|
|
186
|
+
if (signatureB64 !== expectedSignature) {
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
// Decode and parse payload
|
|
190
|
+
const payload = JSON.parse(Buffer.from(payloadB64, 'base64url').toString('utf-8'));
|
|
191
|
+
// Check expiration
|
|
192
|
+
const now = Math.floor(Date.now() / 1000);
|
|
193
|
+
if (payload.exp && payload.exp < now) {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
// Check not-before time
|
|
197
|
+
if (payload.nbf && payload.nbf > now) {
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
// Convert to unified token format
|
|
201
|
+
const scopes = this.ociAccessToScopes(payload.access || []);
|
|
202
|
+
return {
|
|
203
|
+
type: 'oci',
|
|
204
|
+
userId: payload.sub,
|
|
205
|
+
scopes,
|
|
206
|
+
expiresAt: payload.exp ? new Date(payload.exp * 1000) : undefined,
|
|
207
|
+
metadata: {
|
|
208
|
+
iss: payload.iss,
|
|
209
|
+
aud: payload.aud,
|
|
210
|
+
},
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
catch (error) {
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
// ========================================================================
|
|
218
|
+
// Helper Methods
|
|
219
|
+
// ========================================================================
|
|
220
|
+
/**
|
|
221
|
+
* Check if a scope matches a resource and action
|
|
222
|
+
*/
|
|
223
|
+
matchesScope(scope, resource, action) {
|
|
224
|
+
const scopeParts = scope.split(':');
|
|
225
|
+
const resourceParts = resource.split(':');
|
|
226
|
+
// Scope must have at least protocol:type:name:action
|
|
227
|
+
if (scopeParts.length < 4) {
|
|
228
|
+
return false;
|
|
229
|
+
}
|
|
230
|
+
const [scopeProtocol, scopeType, scopeName, scopeAction] = scopeParts;
|
|
231
|
+
const [resourceProtocol, resourceType, resourceName] = resourceParts;
|
|
232
|
+
// Check protocol
|
|
233
|
+
if (scopeProtocol !== '*' && scopeProtocol !== resourceProtocol) {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
// Check type
|
|
237
|
+
if (scopeType !== '*' && scopeType !== resourceType) {
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
// Check name
|
|
241
|
+
if (scopeName !== '*' && scopeName !== resourceName) {
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
// Check action
|
|
245
|
+
if (scopeAction !== '*' && scopeAction !== action) {
|
|
246
|
+
// Map action aliases
|
|
247
|
+
const actionAliases = {
|
|
248
|
+
read: ['pull', 'get'],
|
|
249
|
+
write: ['push', 'put', 'post'],
|
|
250
|
+
};
|
|
251
|
+
const aliases = actionAliases[scopeAction] || [];
|
|
252
|
+
if (!aliases.includes(action)) {
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Convert unified scopes to OCI access array
|
|
260
|
+
*/
|
|
261
|
+
scopesToOciAccess(scopes) {
|
|
262
|
+
const access = [];
|
|
263
|
+
for (const scope of scopes) {
|
|
264
|
+
const parts = scope.split(':');
|
|
265
|
+
if (parts.length >= 4 && parts[0] === 'oci') {
|
|
266
|
+
access.push({
|
|
267
|
+
type: parts[1],
|
|
268
|
+
name: parts[2],
|
|
269
|
+
actions: [parts[3]],
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return access;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Convert OCI access array to unified scopes
|
|
277
|
+
*/
|
|
278
|
+
ociAccessToScopes(access) {
|
|
279
|
+
const scopes = [];
|
|
280
|
+
for (const item of access) {
|
|
281
|
+
for (const action of item.actions) {
|
|
282
|
+
scopes.push(`oci:${item.type}:${item.name}:${action}`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
return scopes;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Generate UUID for tokens
|
|
289
|
+
*/
|
|
290
|
+
generateUuid() {
|
|
291
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
292
|
+
const r = (Math.random() * 16) | 0;
|
|
293
|
+
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
294
|
+
return v.toString(16);
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Check if string is a valid UUID
|
|
299
|
+
*/
|
|
300
|
+
isValidUuid(str) {
|
|
301
|
+
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
302
|
+
return uuidRegex.test(str);
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Hash a token for identification
|
|
306
|
+
*/
|
|
307
|
+
hashToken(token) {
|
|
308
|
+
return `sha512-${token.substring(0, 16)}...`;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5kZWZhdWx0YXV0aHByb3ZpZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvY29yZS9jbGFzc2VzLmRlZmF1bHRhdXRocHJvdmlkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE1BQU0sTUFBTSxRQUFRLENBQUM7QUFJakM7Ozs7R0FJRztBQUNILE1BQU0sT0FBTyxtQkFBbUI7SUFJVjtJQUhaLFVBQVUsR0FBNEIsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUNoRCxlQUFlLEdBQXdCLElBQUksR0FBRyxFQUFFLENBQUMsQ0FBQyxtQ0FBbUM7SUFFN0YsWUFBb0IsTUFBbUI7UUFBbkIsV0FBTSxHQUFOLE1BQU0sQ0FBYTtJQUFHLENBQUM7SUFFM0M7O09BRUc7SUFDSSxLQUFLLENBQUMsSUFBSTtRQUNmLDZDQUE2QztRQUM3QyxtREFBbUQ7SUFDckQsQ0FBQztJQUVELDJFQUEyRTtJQUMzRSwrQkFBK0I7SUFDL0IsMkVBQTJFO0lBRTNFOztPQUVHO0lBQ0ksS0FBSyxDQUFDLFlBQVksQ0FBQyxXQUF5QjtRQUNqRCxvRUFBb0U7UUFDcEUsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBRXRFLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUNwQixtREFBbUQ7WUFDbkQsSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLFFBQVEsRUFBRSxXQUFXLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDckUsT0FBTyxXQUFXLENBQUMsUUFBUSxDQUFDO1FBQzlCLENBQUM7UUFFRCxJQUFJLGNBQWMsS0FBSyxXQUFXLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDNUMsT0FBTyxXQUFXLENBQUMsUUFBUSxDQUFDO1FBQzlCLENBQUM7UUFFRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7T0FFRztJ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
|
|
@@ -1,14 +1,42 @@
|
|
|
1
|
-
import type { IStorageConfig, IStorageBackend } from './interfaces.core.js';
|
|
1
|
+
import type { IStorageConfig, IStorageBackend, TRegistryProtocol } from './interfaces.core.js';
|
|
2
|
+
import type { IStorageHooks, IStorageActor, IStorageMetadata } from './interfaces.storage.js';
|
|
2
3
|
/**
|
|
3
|
-
* Storage abstraction layer for registry
|
|
4
|
-
* Provides a unified interface over SmartBucket
|
|
4
|
+
* Storage abstraction layer for registry.
|
|
5
|
+
* Provides a unified interface over SmartBucket with optional hooks
|
|
6
|
+
* for quota tracking, audit logging, cache invalidation, etc.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* // Basic usage
|
|
11
|
+
* const storage = new RegistryStorage(config);
|
|
12
|
+
*
|
|
13
|
+
* // With hooks for quota tracking
|
|
14
|
+
* const storage = new RegistryStorage(config, {
|
|
15
|
+
* beforePut: async (ctx) => {
|
|
16
|
+
* const quota = await getQuota(ctx.actor?.orgId);
|
|
17
|
+
* const usage = await getUsage(ctx.actor?.orgId);
|
|
18
|
+
* if (usage + (ctx.metadata?.size || 0) > quota) {
|
|
19
|
+
* return { allowed: false, reason: 'Quota exceeded' };
|
|
20
|
+
* }
|
|
21
|
+
* return { allowed: true };
|
|
22
|
+
* },
|
|
23
|
+
* afterPut: async (ctx) => {
|
|
24
|
+
* await updateUsage(ctx.actor?.orgId, ctx.metadata?.size || 0);
|
|
25
|
+
* }
|
|
26
|
+
* });
|
|
27
|
+
* ```
|
|
5
28
|
*/
|
|
6
29
|
export declare class RegistryStorage implements IStorageBackend {
|
|
7
30
|
private config;
|
|
8
31
|
private smartBucket;
|
|
9
32
|
private bucket;
|
|
10
33
|
private bucketName;
|
|
11
|
-
|
|
34
|
+
private hooks?;
|
|
35
|
+
constructor(config: IStorageConfig, hooks?: IStorageHooks);
|
|
36
|
+
/**
|
|
37
|
+
* Set storage hooks (can be called after construction)
|
|
38
|
+
*/
|
|
39
|
+
setHooks(hooks: IStorageHooks): void;
|
|
12
40
|
/**
|
|
13
41
|
* Initialize the storage backend
|
|
14
42
|
*/
|
|
@@ -25,6 +53,44 @@ export declare class RegistryStorage implements IStorageBackend {
|
|
|
25
53
|
* Delete an object
|
|
26
54
|
*/
|
|
27
55
|
deleteObject(key: string): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Current operation context for hooks.
|
|
58
|
+
* Set this before performing storage operations to enable hooks.
|
|
59
|
+
*/
|
|
60
|
+
private currentContext?;
|
|
61
|
+
/**
|
|
62
|
+
* Set the current operation context for hooks.
|
|
63
|
+
* Call this before performing storage operations.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* storage.setContext({
|
|
68
|
+
* protocol: 'npm',
|
|
69
|
+
* actor: { userId: 'user123', ip: '192.168.1.1' },
|
|
70
|
+
* metadata: { packageName: 'lodash', version: '4.17.21' }
|
|
71
|
+
* });
|
|
72
|
+
* await storage.putNpmTarball('lodash', '4.17.21', tarball);
|
|
73
|
+
* storage.clearContext();
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
setContext(context: {
|
|
77
|
+
protocol: TRegistryProtocol;
|
|
78
|
+
actor?: IStorageActor;
|
|
79
|
+
metadata?: IStorageMetadata;
|
|
80
|
+
}): void;
|
|
81
|
+
/**
|
|
82
|
+
* Clear the current operation context.
|
|
83
|
+
*/
|
|
84
|
+
clearContext(): void;
|
|
85
|
+
/**
|
|
86
|
+
* Execute a function with a temporary context.
|
|
87
|
+
* Context is automatically cleared after execution.
|
|
88
|
+
*/
|
|
89
|
+
withContext<T>(context: {
|
|
90
|
+
protocol: TRegistryProtocol;
|
|
91
|
+
actor?: IStorageActor;
|
|
92
|
+
metadata?: IStorageMetadata;
|
|
93
|
+
}, fn: () => Promise<T>): Promise<T>;
|
|
28
94
|
/**
|
|
29
95
|
* List objects with a prefix (recursively)
|
|
30
96
|
*/
|