@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.
Files changed (33) hide show
  1. package/dist_ts/00_commitinfo_data.js +1 -1
  2. package/dist_ts/classes.smartregistry.d.ts +33 -2
  3. package/dist_ts/classes.smartregistry.js +38 -5
  4. package/dist_ts/core/classes.authmanager.d.ts +30 -80
  5. package/dist_ts/core/classes.authmanager.js +63 -337
  6. package/dist_ts/core/classes.defaultauthprovider.d.ts +78 -0
  7. package/dist_ts/core/classes.defaultauthprovider.js +311 -0
  8. package/dist_ts/core/classes.registrystorage.d.ts +70 -4
  9. package/dist_ts/core/classes.registrystorage.js +165 -5
  10. package/dist_ts/core/index.d.ts +3 -0
  11. package/dist_ts/core/index.js +7 -2
  12. package/dist_ts/core/interfaces.auth.d.ts +83 -0
  13. package/dist_ts/core/interfaces.auth.js +2 -0
  14. package/dist_ts/core/interfaces.core.d.ts +35 -0
  15. package/dist_ts/core/interfaces.storage.d.ts +120 -0
  16. package/dist_ts/core/interfaces.storage.js +2 -0
  17. package/dist_ts/upstream/classes.baseupstream.d.ts +2 -2
  18. package/dist_ts/upstream/classes.baseupstream.js +16 -14
  19. package/dist_ts/upstream/classes.upstreamcache.d.ts +69 -22
  20. package/dist_ts/upstream/classes.upstreamcache.js +207 -50
  21. package/package.json +1 -1
  22. package/readme.md +225 -1
  23. package/ts/00_commitinfo_data.ts +1 -1
  24. package/ts/classes.smartregistry.ts +39 -4
  25. package/ts/core/classes.authmanager.ts +74 -412
  26. package/ts/core/classes.defaultauthprovider.ts +393 -0
  27. package/ts/core/classes.registrystorage.ts +199 -5
  28. package/ts/core/index.ts +8 -1
  29. package/ts/core/interfaces.auth.ts +91 -0
  30. package/ts/core/interfaces.core.ts +39 -0
  31. package/ts/core/interfaces.storage.ts +130 -0
  32. package/ts/upstream/classes.baseupstream.ts +20 -15
  33. package/ts/upstream/classes.upstreamcache.ts +256 -53
@@ -1,87 +1,62 @@
1
- import * as crypto from 'crypto';
1
+ import { DefaultAuthProvider } from './classes.defaultauthprovider.js';
2
2
  /**
3
- * Unified authentication manager for all registry protocols
4
- * Handles both NPM UUID tokens and OCI JWT tokens
3
+ * Unified authentication manager for all registry protocols.
4
+ * Delegates to a pluggable IAuthProvider for actual auth operations.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * // Use default in-memory provider
9
+ * const auth = new AuthManager(config);
10
+ *
11
+ * // Use custom provider (LDAP, OAuth, etc.)
12
+ * const auth = new AuthManager(config, new LdapAuthProvider(ldapClient));
13
+ * ```
5
14
  */
6
15
  export class AuthManager {
7
16
  config;
8
- tokenStore = new Map();
9
- userCredentials = new Map(); // username -> password hash (mock)
10
- constructor(config) {
17
+ provider;
18
+ constructor(config, provider) {
11
19
  this.config = config;
20
+ // Use provided provider or default in-memory implementation
21
+ this.provider = provider || new DefaultAuthProvider(config);
12
22
  }
13
23
  /**
14
24
  * Initialize the auth manager
15
25
  */
16
26
  async init() {
17
- // Initialize token store (in-memory for now)
18
- // In production, this could be Redis or a database
27
+ if (this.provider.init) {
28
+ await this.provider.init();
29
+ }
19
30
  }
20
31
  // ========================================================================
21
- // UUID TOKEN CREATION (Base method for NPM, Maven, etc.)
32
+ // UNIFIED AUTHENTICATION (Delegated to Provider)
22
33
  // ========================================================================
23
34
  /**
24
- * Create a UUID-based token with custom scopes (base method)
25
- * @param userId - User ID
26
- * @param protocol - Protocol type
27
- * @param scopes - Permission scopes
28
- * @param readonly - Whether the token is readonly
29
- * @returns UUID token string
30
- */
31
- async createUuidToken(userId, protocol, scopes, readonly = false) {
32
- const token = this.generateUuid();
33
- const authToken = {
34
- type: protocol,
35
- userId,
36
- scopes,
37
- readonly,
38
- metadata: {
39
- created: new Date().toISOString(),
40
- },
41
- };
42
- this.tokenStore.set(token, authToken);
43
- return token;
44
- }
45
- /**
46
- * Generic protocol token creation (internal helper)
47
- * @param userId - User ID
48
- * @param protocol - Protocol type (npm, maven, composer, etc.)
49
- * @param readonly - Whether the token is readonly
50
- * @returns UUID token string
35
+ * Authenticate user credentials
36
+ * @param credentials - Username and password
37
+ * @returns User ID or null
51
38
  */
52
- async createProtocolToken(userId, protocol, readonly) {
53
- const scopes = readonly
54
- ? [`${protocol}:*:*:read`]
55
- : [`${protocol}:*:*:*`];
56
- return this.createUuidToken(userId, protocol, scopes, readonly);
39
+ async authenticate(credentials) {
40
+ return this.provider.authenticate(credentials);
57
41
  }
58
42
  /**
59
- * Generic protocol token validation (internal helper)
60
- * @param token - UUID token string
61
- * @param protocol - Expected protocol type
43
+ * Validate any token (NPM, Maven, OCI, PyPI, RubyGems, Composer, Cargo)
44
+ * @param tokenString - Token string (UUID or JWT)
45
+ * @param protocol - Expected protocol type (optional, improves performance)
62
46
  * @returns Auth token object or null
63
47
  */
64
- async validateProtocolToken(token, protocol) {
65
- if (!this.isValidUuid(token)) {
66
- return null;
67
- }
68
- const authToken = this.tokenStore.get(token);
69
- if (!authToken || authToken.type !== protocol) {
70
- return null;
71
- }
72
- // Check expiration if set
73
- if (authToken.expiresAt && authToken.expiresAt < new Date()) {
74
- this.tokenStore.delete(token);
75
- return null;
76
- }
77
- return authToken;
48
+ async validateToken(tokenString, protocol) {
49
+ return this.provider.validateToken(tokenString, protocol);
78
50
  }
79
51
  /**
80
- * Generic protocol token revocation (internal helper)
81
- * @param token - UUID token string
52
+ * Check if token has permission for an action
53
+ * @param token - Auth token (or null for anonymous)
54
+ * @param resource - Resource being accessed (e.g., "npm:package:foo")
55
+ * @param action - Action being performed (read, write, push, pull, delete)
56
+ * @returns true if authorized
82
57
  */
83
- async revokeProtocolToken(token) {
84
- this.tokenStore.delete(token);
58
+ async authorize(token, resource, action) {
59
+ return this.provider.authorize(token, resource, action);
85
60
  }
86
61
  // ========================================================================
87
62
  // NPM AUTHENTICATION
@@ -96,7 +71,7 @@ export class AuthManager {
96
71
  if (!this.config.npmTokens.enabled) {
97
72
  throw new Error('NPM tokens are not enabled');
98
73
  }
99
- return this.createProtocolToken(userId, 'npm', readonly);
74
+ return this.provider.createToken(userId, 'npm', { readonly });
100
75
  }
101
76
  /**
102
77
  * Validate an NPM token
@@ -104,14 +79,14 @@ export class AuthManager {
104
79
  * @returns Auth token object or null
105
80
  */
106
81
  async validateNpmToken(token) {
107
- return this.validateProtocolToken(token, 'npm');
82
+ return this.provider.validateToken(token, 'npm');
108
83
  }
109
84
  /**
110
85
  * Revoke an NPM token
111
86
  * @param token - NPM UUID token
112
87
  */
113
88
  async revokeNpmToken(token) {
114
- return this.revokeProtocolToken(token);
89
+ return this.provider.revokeToken(token);
115
90
  }
116
91
  /**
117
92
  * List all tokens for a user
@@ -119,17 +94,10 @@ export class AuthManager {
119
94
  * @returns List of token info (without actual token values)
120
95
  */
121
96
  async listUserTokens(userId) {
122
- const tokens = [];
123
- for (const [token, authToken] of this.tokenStore.entries()) {
124
- if (authToken.userId === userId) {
125
- tokens.push({
126
- key: this.hashToken(token),
127
- readonly: authToken.readonly || false,
128
- created: authToken.metadata?.created || 'unknown',
129
- });
130
- }
97
+ if (this.provider.listUserTokens) {
98
+ return this.provider.listUserTokens(userId);
131
99
  }
132
- return tokens;
100
+ return [];
133
101
  }
134
102
  // ========================================================================
135
103
  // OCI AUTHENTICATION (JWT)
@@ -139,31 +107,13 @@ export class AuthManager {
139
107
  * @param userId - User ID
140
108
  * @param scopes - Permission scopes
141
109
  * @param expiresIn - Expiration time in seconds
142
- * @returns JWT token string (HMAC-SHA256 signed)
110
+ * @returns JWT token string
143
111
  */
144
112
  async createOciToken(userId, scopes, expiresIn = 3600) {
145
- if (!this.config.ociTokens.enabled) {
113
+ if (!this.config.ociTokens?.enabled) {
146
114
  throw new Error('OCI tokens are not enabled');
147
115
  }
148
- const now = Math.floor(Date.now() / 1000);
149
- const payload = {
150
- iss: this.config.ociTokens.realm,
151
- sub: userId,
152
- aud: this.config.ociTokens.service,
153
- exp: now + expiresIn,
154
- nbf: now,
155
- iat: now,
156
- access: this.scopesToOciAccess(scopes),
157
- };
158
- // Create JWT with HMAC-SHA256 signature
159
- const header = { alg: 'HS256', typ: 'JWT' };
160
- const headerB64 = Buffer.from(JSON.stringify(header)).toString('base64url');
161
- const payloadB64 = Buffer.from(JSON.stringify(payload)).toString('base64url');
162
- const signature = crypto
163
- .createHmac('sha256', this.config.jwtSecret)
164
- .update(`${headerB64}.${payloadB64}`)
165
- .digest('base64url');
166
- return `${headerB64}.${payloadB64}.${signature}`;
116
+ return this.provider.createToken(userId, 'oci', { scopes, expiresIn });
167
117
  }
168
118
  /**
169
119
  * Validate an OCI JWT token
@@ -171,68 +121,7 @@ export class AuthManager {
171
121
  * @returns Auth token object or null
172
122
  */
173
123
  async validateOciToken(jwt) {
174
- try {
175
- const parts = jwt.split('.');
176
- if (parts.length !== 3) {
177
- return null;
178
- }
179
- const [headerB64, payloadB64, signatureB64] = parts;
180
- // Verify signature
181
- const expectedSignature = crypto
182
- .createHmac('sha256', this.config.jwtSecret)
183
- .update(`${headerB64}.${payloadB64}`)
184
- .digest('base64url');
185
- if (signatureB64 !== expectedSignature) {
186
- return null;
187
- }
188
- // Decode and parse payload
189
- const payload = JSON.parse(Buffer.from(payloadB64, 'base64url').toString('utf-8'));
190
- // Check expiration
191
- const now = Math.floor(Date.now() / 1000);
192
- if (payload.exp && payload.exp < now) {
193
- return null;
194
- }
195
- // Check not-before time
196
- if (payload.nbf && payload.nbf > now) {
197
- return null;
198
- }
199
- // Convert to unified token format
200
- const scopes = this.ociAccessToScopes(payload.access || []);
201
- return {
202
- type: 'oci',
203
- userId: payload.sub,
204
- scopes,
205
- expiresAt: payload.exp ? new Date(payload.exp * 1000) : undefined,
206
- metadata: {
207
- iss: payload.iss,
208
- aud: payload.aud,
209
- },
210
- };
211
- }
212
- catch (error) {
213
- return null;
214
- }
215
- }
216
- // ========================================================================
217
- // UNIFIED AUTHENTICATION
218
- // ========================================================================
219
- /**
220
- * Authenticate user credentials
221
- * @param credentials - Username and password
222
- * @returns User ID or null
223
- */
224
- async authenticate(credentials) {
225
- // Mock authentication - in production, verify against database
226
- const storedPassword = this.userCredentials.get(credentials.username);
227
- if (!storedPassword) {
228
- // Auto-register for testing (remove in production)
229
- this.userCredentials.set(credentials.username, credentials.password);
230
- return credentials.username;
231
- }
232
- if (storedPassword === credentials.password) {
233
- return credentials.username;
234
- }
235
- return null;
124
+ return this.provider.validateToken(jwt, 'oci');
236
125
  }
237
126
  // ========================================================================
238
127
  // MAVEN AUTHENTICATION
@@ -244,7 +133,7 @@ export class AuthManager {
244
133
  * @returns Maven UUID token
245
134
  */
246
135
  async createMavenToken(userId, readonly = false) {
247
- return this.createProtocolToken(userId, 'maven', readonly);
136
+ return this.provider.createToken(userId, 'maven', { readonly });
248
137
  }
249
138
  /**
250
139
  * Validate a Maven token
@@ -252,14 +141,14 @@ export class AuthManager {
252
141
  * @returns Auth token object or null
253
142
  */
254
143
  async validateMavenToken(token) {
255
- return this.validateProtocolToken(token, 'maven');
144
+ return this.provider.validateToken(token, 'maven');
256
145
  }
257
146
  /**
258
147
  * Revoke a Maven token
259
148
  * @param token - Maven UUID token
260
149
  */
261
150
  async revokeMavenToken(token) {
262
- return this.revokeProtocolToken(token);
151
+ return this.provider.revokeToken(token);
263
152
  }
264
153
  // ========================================================================
265
154
  // COMPOSER TOKEN MANAGEMENT
@@ -271,7 +160,7 @@ export class AuthManager {
271
160
  * @returns Composer UUID token
272
161
  */
273
162
  async createComposerToken(userId, readonly = false) {
274
- return this.createProtocolToken(userId, 'composer', readonly);
163
+ return this.provider.createToken(userId, 'composer', { readonly });
275
164
  }
276
165
  /**
277
166
  * Validate a Composer token
@@ -279,14 +168,14 @@ export class AuthManager {
279
168
  * @returns Auth token object or null
280
169
  */
281
170
  async validateComposerToken(token) {
282
- return this.validateProtocolToken(token, 'composer');
171
+ return this.provider.validateToken(token, 'composer');
283
172
  }
284
173
  /**
285
174
  * Revoke a Composer token
286
175
  * @param token - Composer UUID token
287
176
  */
288
177
  async revokeComposerToken(token) {
289
- return this.revokeProtocolToken(token);
178
+ return this.provider.revokeToken(token);
290
179
  }
291
180
  // ========================================================================
292
181
  // CARGO TOKEN MANAGEMENT
@@ -298,7 +187,7 @@ export class AuthManager {
298
187
  * @returns Cargo UUID token
299
188
  */
300
189
  async createCargoToken(userId, readonly = false) {
301
- return this.createProtocolToken(userId, 'cargo', readonly);
190
+ return this.provider.createToken(userId, 'cargo', { readonly });
302
191
  }
303
192
  /**
304
193
  * Validate a Cargo token
@@ -306,14 +195,14 @@ export class AuthManager {
306
195
  * @returns Auth token object or null
307
196
  */
308
197
  async validateCargoToken(token) {
309
- return this.validateProtocolToken(token, 'cargo');
198
+ return this.provider.validateToken(token, 'cargo');
310
199
  }
311
200
  /**
312
201
  * Revoke a Cargo token
313
202
  * @param token - Cargo UUID token
314
203
  */
315
204
  async revokeCargoToken(token) {
316
- return this.revokeProtocolToken(token);
205
+ return this.provider.revokeToken(token);
317
206
  }
318
207
  // ========================================================================
319
208
  // PYPI AUTHENTICATION
@@ -325,7 +214,7 @@ export class AuthManager {
325
214
  * @returns PyPI UUID token
326
215
  */
327
216
  async createPypiToken(userId, readonly = false) {
328
- return this.createProtocolToken(userId, 'pypi', readonly);
217
+ return this.provider.createToken(userId, 'pypi', { readonly });
329
218
  }
330
219
  /**
331
220
  * Validate a PyPI token
@@ -333,14 +222,14 @@ export class AuthManager {
333
222
  * @returns Auth token object or null
334
223
  */
335
224
  async validatePypiToken(token) {
336
- return this.validateProtocolToken(token, 'pypi');
225
+ return this.provider.validateToken(token, 'pypi');
337
226
  }
338
227
  /**
339
228
  * Revoke a PyPI token
340
229
  * @param token - PyPI UUID token
341
230
  */
342
231
  async revokePypiToken(token) {
343
- return this.revokeProtocolToken(token);
232
+ return this.provider.revokeToken(token);
344
233
  }
345
234
  // ========================================================================
346
235
  // RUBYGEMS AUTHENTICATION
@@ -352,7 +241,7 @@ export class AuthManager {
352
241
  * @returns RubyGems UUID token
353
242
  */
354
243
  async createRubyGemsToken(userId, readonly = false) {
355
- return this.createProtocolToken(userId, 'rubygems', readonly);
244
+ return this.provider.createToken(userId, 'rubygems', { readonly });
356
245
  }
357
246
  /**
358
247
  * Validate a RubyGems token
@@ -360,177 +249,14 @@ export class AuthManager {
360
249
  * @returns Auth token object or null
361
250
  */
362
251
  async validateRubyGemsToken(token) {
363
- return this.validateProtocolToken(token, 'rubygems');
252
+ return this.provider.validateToken(token, 'rubygems');
364
253
  }
365
254
  /**
366
255
  * Revoke a RubyGems token
367
256
  * @param token - RubyGems UUID token
368
257
  */
369
258
  async revokeRubyGemsToken(token) {
370
- return this.revokeProtocolToken(token);
371
- }
372
- // ========================================================================
373
- // UNIFIED AUTHENTICATION
374
- // ========================================================================
375
- /**
376
- * Validate any token (NPM, Maven, OCI, PyPI, RubyGems, Composer, Cargo)
377
- * Optimized: O(1) lookup when protocol hint provided
378
- * @param tokenString - Token string (UUID or JWT)
379
- * @param protocol - Expected protocol type (optional, improves performance)
380
- * @returns Auth token object or null
381
- */
382
- async validateToken(tokenString, protocol) {
383
- // OCI uses JWT (contains dots), not UUID - check first if OCI is expected
384
- if (protocol === 'oci' || tokenString.includes('.')) {
385
- const ociToken = await this.validateOciToken(tokenString);
386
- if (ociToken && (!protocol || protocol === 'oci')) {
387
- return ociToken;
388
- }
389
- // If protocol was explicitly OCI but validation failed, return null
390
- if (protocol === 'oci') {
391
- return null;
392
- }
393
- }
394
- // UUID-based tokens: single O(1) Map lookup
395
- if (this.isValidUuid(tokenString)) {
396
- const authToken = this.tokenStore.get(tokenString);
397
- if (authToken) {
398
- // If protocol specified, verify it matches
399
- if (protocol && authToken.type !== protocol) {
400
- return null;
401
- }
402
- // Check expiration
403
- if (authToken.expiresAt && authToken.expiresAt < new Date()) {
404
- this.tokenStore.delete(tokenString);
405
- return null;
406
- }
407
- return authToken;
408
- }
409
- }
410
- return null;
411
- }
412
- /**
413
- * Check if token has permission for an action
414
- * @param token - Auth token
415
- * @param resource - Resource being accessed (e.g., "package:foo" or "repository:bar")
416
- * @param action - Action being performed (read, write, push, pull, delete)
417
- * @returns true if authorized
418
- */
419
- async authorize(token, resource, action) {
420
- if (!token) {
421
- return false;
422
- }
423
- // Check readonly flag
424
- if (token.readonly && ['write', 'push', 'delete'].includes(action)) {
425
- return false;
426
- }
427
- // Check scopes
428
- for (const scope of token.scopes) {
429
- if (this.matchesScope(scope, resource, action)) {
430
- return true;
431
- }
432
- }
433
- return false;
434
- }
435
- // ========================================================================
436
- // HELPER METHODS
437
- // ========================================================================
438
- /**
439
- * Check if a scope matches a resource and action
440
- * Scope format: "{protocol}:{type}:{name}:{action}"
441
- * Examples:
442
- * - "npm:*:*" - All NPM access
443
- * - "npm:package:foo:*" - All actions on package foo
444
- * - "npm:package:foo:read" - Read-only on package foo
445
- * - "oci:repository:*:pull" - Pull from any OCI repo
446
- */
447
- matchesScope(scope, resource, action) {
448
- const scopeParts = scope.split(':');
449
- const resourceParts = resource.split(':');
450
- // Scope must have at least protocol:type:name:action
451
- if (scopeParts.length < 4) {
452
- return false;
453
- }
454
- const [scopeProtocol, scopeType, scopeName, scopeAction] = scopeParts;
455
- const [resourceProtocol, resourceType, resourceName] = resourceParts;
456
- // Check protocol
457
- if (scopeProtocol !== '*' && scopeProtocol !== resourceProtocol) {
458
- return false;
459
- }
460
- // Check type
461
- if (scopeType !== '*' && scopeType !== resourceType) {
462
- return false;
463
- }
464
- // Check name
465
- if (scopeName !== '*' && scopeName !== resourceName) {
466
- return false;
467
- }
468
- // Check action
469
- if (scopeAction !== '*' && scopeAction !== action) {
470
- // Map action aliases
471
- const actionAliases = {
472
- read: ['pull', 'get'],
473
- write: ['push', 'put', 'post'],
474
- };
475
- const aliases = actionAliases[scopeAction] || [];
476
- if (!aliases.includes(action)) {
477
- return false;
478
- }
479
- }
480
- return true;
481
- }
482
- /**
483
- * Convert unified scopes to OCI access array
484
- */
485
- scopesToOciAccess(scopes) {
486
- const access = [];
487
- for (const scope of scopes) {
488
- const parts = scope.split(':');
489
- if (parts.length >= 4 && parts[0] === 'oci') {
490
- access.push({
491
- type: parts[1],
492
- name: parts[2],
493
- actions: [parts[3]],
494
- });
495
- }
496
- }
497
- return access;
498
- }
499
- /**
500
- * Convert OCI access array to unified scopes
501
- */
502
- ociAccessToScopes(access) {
503
- const scopes = [];
504
- for (const item of access) {
505
- for (const action of item.actions) {
506
- scopes.push(`oci:${item.type}:${item.name}:${action}`);
507
- }
508
- }
509
- return scopes;
510
- }
511
- /**
512
- * Generate UUID for NPM tokens
513
- */
514
- generateUuid() {
515
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
516
- const r = (Math.random() * 16) | 0;
517
- const v = c === 'x' ? r : (r & 0x3) | 0x8;
518
- return v.toString(16);
519
- });
520
- }
521
- /**
522
- * Check if string is a valid UUID
523
- */
524
- isValidUuid(str) {
525
- 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;
526
- return uuidRegex.test(str);
527
- }
528
- /**
529
- * Hash a token for identification (SHA-512 mock)
530
- */
531
- hashToken(token) {
532
- // In production, use actual SHA-512
533
- return `sha512-${token.substring(0, 16)}...`;
259
+ return this.provider.revokeToken(token);
534
260
  }
535
261
  }
536
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5hdXRobWFuYWdlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2NvcmUvY2xhc3Nlcy5hdXRobWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEtBQUssTUFBTSxNQUFNLFFBQVEsQ0FBQztBQUVqQzs7O0dBR0c7QUFDSCxNQUFNLE9BQU8sV0FBVztJQUlGO0lBSFosVUFBVSxHQUE0QixJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQ2hELGVBQWUsR0FBd0IsSUFBSSxHQUFHLEVBQUUsQ0FBQyxDQUFDLG1DQUFtQztJQUU3RixZQUFvQixNQUFtQjtRQUFuQixXQUFNLEdBQU4sTUFBTSxDQUFhO0lBQUcsQ0FBQztJQUUzQzs7T0FFRztJQUNJLEtBQUssQ0FBQyxJQUFJO1FBQ2YsNkNBQTZDO1FBQzdDLG1EQUFtRDtJQUNyRCxDQUFDO0lBRUQsMkVBQTJFO0lBQzNFLHlEQUF5RDtJQUN6RCwyRUFBMkU7SUFFM0U7Ozs7Ozs7T0FPRztJQUNLLEtBQUssQ0FBQyxlQUFlLENBQzNCLE1BQWMsRUFDZCxRQUEyQixFQUMzQixNQUFnQixFQUNoQixXQUFvQixLQUFLO1FBRXpCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUNsQyxNQUFNLFNBQVMsR0FBZTtZQUM1QixJQUFJLEVBQUUsUUFBUTtZQUNkLE1BQU07WUFDTixNQUFNO1lBQ04sUUFBUTtZQUNSLFFBQVEsRUFBRTtnQkFDUixPQUFPLEVBQUUsSUFBSSxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUU7YUFDbEM7U0FDRixDQUFDO1FBRUYsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQ3RDLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNLLEtBQUssQ0FBQyxtQkFBbUIsQ0FDL0IsTUFBYyxFQUNkLFFBQTJCLEVBQzNCLFFBQWlCO1FB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
262
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5hdXRobWFuYWdlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2NvcmUvY2xhc3Nlcy5hdXRobWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUV2RTs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSCxNQUFNLE9BQU8sV0FBVztJQUlaO0lBSEYsUUFBUSxDQUFnQjtJQUVoQyxZQUNVLE1BQW1CLEVBQzNCLFFBQXdCO1FBRGhCLFdBQU0sR0FBTixNQUFNLENBQWE7UUFHM0IsNERBQTREO1FBQzVELElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxJQUFJLElBQUksbUJBQW1CLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDOUQsQ0FBQztJQUVEOztPQUVHO0lBQ0ksS0FBSyxDQUFDLElBQUk7UUFDZixJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDdkIsTUFBTSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQzdCLENBQUM7SUFDSCxDQUFDO0lBRUQsMkVBQTJFO0lBQzNFLGlEQUFpRDtJQUNqRCwyRUFBMkU7SUFFM0U7Ozs7T0FJRztJQUNJLEtBQUssQ0FBQyxZQUFZLENBQUMsV0FBeUI7UUFDakQsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUNqRCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSSxLQUFLLENBQUMsYUFBYSxDQUN4QixXQUFtQixFQUNuQixRQUE0QjtRQUU1QixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLFdBQVcsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUM1RCxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0ksS0FBSyxDQUFDLFNBQVMsQ0FDcEIsS0FBd0IsRUFDeEIsUUFBZ0IsRUFDaEIsTUFBYztRQUVkLE9BQU8sSUFB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