@push.rocks/smartproxy 3.26.0 → 3.28.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.
@@ -1,19 +1,109 @@
1
- import * as http from 'http';
2
- import * as acme from 'acme-client';
3
- export class Port80Handler {
4
- constructor() {
1
+ import * as plugins from './plugins.js';
2
+ /**
3
+ * Events emitted by the ACME Certificate Manager
4
+ */
5
+ export var CertManagerEvents;
6
+ (function (CertManagerEvents) {
7
+ CertManagerEvents["CERTIFICATE_ISSUED"] = "certificate-issued";
8
+ CertManagerEvents["CERTIFICATE_RENEWED"] = "certificate-renewed";
9
+ CertManagerEvents["CERTIFICATE_FAILED"] = "certificate-failed";
10
+ CertManagerEvents["CERTIFICATE_EXPIRING"] = "certificate-expiring";
11
+ CertManagerEvents["MANAGER_STARTED"] = "manager-started";
12
+ CertManagerEvents["MANAGER_STOPPED"] = "manager-stopped";
13
+ })(CertManagerEvents || (CertManagerEvents = {}));
14
+ /**
15
+ * Improved ACME Certificate Manager with event emission and external certificate management
16
+ */
17
+ export class AcmeCertManager extends plugins.EventEmitter {
18
+ /**
19
+ * Creates a new ACME Certificate Manager
20
+ * @param options Configuration options
21
+ */
22
+ constructor(options = {}) {
23
+ super();
24
+ this.server = null;
5
25
  this.acmeClient = null;
6
26
  this.accountKey = null;
27
+ this.renewalTimer = null;
28
+ this.isShuttingDown = false;
7
29
  this.domainCertificates = new Map();
8
- // Create and start an HTTP server on port 80.
9
- this.server = http.createServer((req, res) => this.handleRequest(req, res));
10
- this.server.listen(80, () => {
11
- console.log('Port80Handler is listening on port 80');
30
+ // Default options
31
+ this.options = {
32
+ port: options.port ?? 80,
33
+ contactEmail: options.contactEmail ?? 'admin@example.com',
34
+ useProduction: options.useProduction ?? false, // Safer default: staging
35
+ renewThresholdDays: options.renewThresholdDays ?? 30,
36
+ httpsRedirectPort: options.httpsRedirectPort ?? 443,
37
+ renewCheckIntervalHours: options.renewCheckIntervalHours ?? 24,
38
+ };
39
+ }
40
+ /**
41
+ * Starts the HTTP server for ACME challenges
42
+ */
43
+ async start() {
44
+ if (this.server) {
45
+ throw new Error('Server is already running');
46
+ }
47
+ if (this.isShuttingDown) {
48
+ throw new Error('Server is shutting down');
49
+ }
50
+ return new Promise((resolve, reject) => {
51
+ try {
52
+ this.server = plugins.http.createServer((req, res) => this.handleRequest(req, res));
53
+ this.server.on('error', (error) => {
54
+ if (error.code === 'EACCES') {
55
+ reject(new Error(`Permission denied to bind to port ${this.options.port}. Try running with elevated privileges or use a port > 1024.`));
56
+ }
57
+ else if (error.code === 'EADDRINUSE') {
58
+ reject(new Error(`Port ${this.options.port} is already in use.`));
59
+ }
60
+ else {
61
+ reject(error);
62
+ }
63
+ });
64
+ this.server.listen(this.options.port, () => {
65
+ console.log(`AcmeCertManager is listening on port ${this.options.port}`);
66
+ this.startRenewalTimer();
67
+ this.emit(CertManagerEvents.MANAGER_STARTED, this.options.port);
68
+ resolve();
69
+ });
70
+ }
71
+ catch (error) {
72
+ reject(error);
73
+ }
12
74
  });
13
75
  }
14
76
  /**
15
- * Adds a domain to be managed.
16
- * @param domain The domain to add.
77
+ * Stops the HTTP server and renewal timer
78
+ */
79
+ async stop() {
80
+ if (!this.server) {
81
+ return;
82
+ }
83
+ this.isShuttingDown = true;
84
+ // Stop the renewal timer
85
+ if (this.renewalTimer) {
86
+ clearInterval(this.renewalTimer);
87
+ this.renewalTimer = null;
88
+ }
89
+ return new Promise((resolve) => {
90
+ if (this.server) {
91
+ this.server.close(() => {
92
+ this.server = null;
93
+ this.isShuttingDown = false;
94
+ this.emit(CertManagerEvents.MANAGER_STOPPED);
95
+ resolve();
96
+ });
97
+ }
98
+ else {
99
+ this.isShuttingDown = false;
100
+ resolve();
101
+ }
102
+ });
103
+ }
104
+ /**
105
+ * Adds a domain to be managed for certificates
106
+ * @param domain The domain to add
17
107
  */
18
108
  addDomain(domain) {
19
109
  if (!this.domainCertificates.has(domain)) {
@@ -22,8 +112,8 @@ export class Port80Handler {
22
112
  }
23
113
  }
24
114
  /**
25
- * Removes a domain from management.
26
- * @param domain The domain to remove.
115
+ * Removes a domain from management
116
+ * @param domain The domain to remove
27
117
  */
28
118
  removeDomain(domain) {
29
119
  if (this.domainCertificates.delete(domain)) {
@@ -31,32 +121,91 @@ export class Port80Handler {
31
121
  }
32
122
  }
33
123
  /**
34
- * Lazy initialization of the ACME client.
35
- * Uses Let’s Encrypt’s production directory (for testing you might switch to staging).
124
+ * Sets a certificate for a domain directly (for externally obtained certificates)
125
+ * @param domain The domain for the certificate
126
+ * @param certificate The certificate (PEM format)
127
+ * @param privateKey The private key (PEM format)
128
+ * @param expiryDate Optional expiry date
129
+ */
130
+ setCertificate(domain, certificate, privateKey, expiryDate) {
131
+ let domainInfo = this.domainCertificates.get(domain);
132
+ if (!domainInfo) {
133
+ domainInfo = { certObtained: false, obtainingInProgress: false };
134
+ this.domainCertificates.set(domain, domainInfo);
135
+ }
136
+ domainInfo.certificate = certificate;
137
+ domainInfo.privateKey = privateKey;
138
+ domainInfo.certObtained = true;
139
+ domainInfo.obtainingInProgress = false;
140
+ if (expiryDate) {
141
+ domainInfo.expiryDate = expiryDate;
142
+ }
143
+ else {
144
+ // Try to extract expiry date from certificate
145
+ try {
146
+ // This is a simplistic approach - in a real implementation, use a proper
147
+ // certificate parsing library like node-forge or x509
148
+ const matches = certificate.match(/Not After\s*:\s*(.*?)(?:\n|$)/i);
149
+ if (matches && matches[1]) {
150
+ domainInfo.expiryDate = new Date(matches[1]);
151
+ }
152
+ }
153
+ catch (error) {
154
+ console.warn(`Failed to extract expiry date from certificate for ${domain}`);
155
+ }
156
+ }
157
+ console.log(`Certificate set for ${domain}`);
158
+ // Emit certificate event
159
+ this.emitCertificateEvent(CertManagerEvents.CERTIFICATE_ISSUED, {
160
+ domain,
161
+ certificate,
162
+ privateKey,
163
+ expiryDate: domainInfo.expiryDate || new Date(Date.now() + 90 * 24 * 60 * 60 * 1000) // 90 days default
164
+ });
165
+ }
166
+ /**
167
+ * Gets the certificate for a domain if it exists
168
+ * @param domain The domain to get the certificate for
169
+ */
170
+ getCertificate(domain) {
171
+ const domainInfo = this.domainCertificates.get(domain);
172
+ if (!domainInfo || !domainInfo.certObtained || !domainInfo.certificate || !domainInfo.privateKey) {
173
+ return null;
174
+ }
175
+ return {
176
+ domain,
177
+ certificate: domainInfo.certificate,
178
+ privateKey: domainInfo.privateKey,
179
+ expiryDate: domainInfo.expiryDate || new Date(Date.now() + 90 * 24 * 60 * 60 * 1000) // 90 days default
180
+ };
181
+ }
182
+ /**
183
+ * Lazy initialization of the ACME client
184
+ * @returns An ACME client instance
36
185
  */
37
186
  async getAcmeClient() {
38
187
  if (this.acmeClient) {
39
188
  return this.acmeClient;
40
189
  }
41
- // Generate a new account key and convert Buffer to string.
42
- this.accountKey = (await acme.forge.createPrivateKey()).toString();
43
- this.acmeClient = new acme.Client({
44
- directoryUrl: acme.directory.letsencrypt.production, // Use production for a real certificate
45
- // For testing, you could use:
46
- // directoryUrl: acme.directory.letsencrypt.staging,
190
+ // Generate a new account key
191
+ this.accountKey = (await plugins.acme.forge.createPrivateKey()).toString();
192
+ this.acmeClient = new plugins.acme.Client({
193
+ directoryUrl: this.options.useProduction
194
+ ? plugins.acme.directory.letsencrypt.production
195
+ : plugins.acme.directory.letsencrypt.staging,
47
196
  accountKey: this.accountKey,
48
197
  });
49
- // Create a new account. Make sure to update the contact email.
198
+ // Create a new account
50
199
  await this.acmeClient.createAccount({
51
200
  termsOfServiceAgreed: true,
52
- contact: ['mailto:admin@example.com'],
201
+ contact: [`mailto:${this.options.contactEmail}`],
53
202
  });
54
203
  return this.acmeClient;
55
204
  }
56
205
  /**
57
- * Handles incoming HTTP requests on port 80.
58
- * If the request is for an ACME challenge, it responds with the key authorization.
59
- * If the domain has a certificate, it redirects to HTTPS; otherwise, it initiates certificate issuance.
206
+ * Handles incoming HTTP requests
207
+ * @param req The HTTP request
208
+ * @param res The HTTP response
60
209
  */
61
210
  handleRequest(req, res) {
62
211
  const hostHeader = req.headers.host;
@@ -67,7 +216,7 @@ export class Port80Handler {
67
216
  }
68
217
  // Extract domain (ignoring any port in the Host header)
69
218
  const domain = hostHeader.split(':')[0];
70
- // If the request is for an ACME HTTP-01 challenge, handle it.
219
+ // If the request is for an ACME HTTP-01 challenge, handle it
71
220
  if (req.url && req.url.startsWith('/.well-known/acme-challenge/')) {
72
221
  this.handleAcmeChallenge(req, res, domain);
73
222
  return;
@@ -78,18 +227,20 @@ export class Port80Handler {
78
227
  return;
79
228
  }
80
229
  const domainInfo = this.domainCertificates.get(domain);
81
- // If certificate exists, redirect to HTTPS on port 443.
230
+ // If certificate exists, redirect to HTTPS
82
231
  if (domainInfo.certObtained) {
83
- const redirectUrl = `https://${domain}:443${req.url}`;
232
+ const httpsPort = this.options.httpsRedirectPort;
233
+ const portSuffix = httpsPort === 443 ? '' : `:${httpsPort}`;
234
+ const redirectUrl = `https://${domain}${portSuffix}${req.url || '/'}`;
84
235
  res.statusCode = 301;
85
236
  res.setHeader('Location', redirectUrl);
86
237
  res.end(`Redirecting to ${redirectUrl}`);
87
238
  }
88
239
  else {
89
- // Trigger certificate issuance if not already running.
240
+ // Trigger certificate issuance if not already running
90
241
  if (!domainInfo.obtainingInProgress) {
91
- domainInfo.obtainingInProgress = true;
92
242
  this.obtainCertificate(domain).catch(err => {
243
+ this.emit(CertManagerEvents.CERTIFICATE_FAILED, { domain, error: err.message });
93
244
  console.error(`Error obtaining certificate for ${domain}:`, err);
94
245
  });
95
246
  }
@@ -98,7 +249,10 @@ export class Port80Handler {
98
249
  }
99
250
  }
100
251
  /**
101
- * Serves the ACME HTTP-01 challenge response.
252
+ * Serves the ACME HTTP-01 challenge response
253
+ * @param req The HTTP request
254
+ * @param res The HTTP response
255
+ * @param domain The domain for the challenge
102
256
  */
103
257
  handleAcmeChallenge(req, res, domain) {
104
258
  const domainInfo = this.domainCertificates.get(domain);
@@ -107,7 +261,7 @@ export class Port80Handler {
107
261
  res.end('Domain not configured');
108
262
  return;
109
263
  }
110
- // The token is the last part of the URL.
264
+ // The token is the last part of the URL
111
265
  const urlParts = req.url?.split('/');
112
266
  const token = urlParts ? urlParts[urlParts.length - 1] : '';
113
267
  if (domainInfo.challengeToken === token && domainInfo.challengeKeyAuthorization) {
@@ -122,65 +276,180 @@ export class Port80Handler {
122
276
  }
123
277
  }
124
278
  /**
125
- * Uses acme-client to perform a full ACME HTTP-01 challenge to obtain a certificate.
126
- * On success, it stores the certificate and key in memory and clears challenge data.
279
+ * Obtains a certificate for a domain using ACME HTTP-01 challenge
280
+ * @param domain The domain to obtain a certificate for
281
+ * @param isRenewal Whether this is a renewal attempt
127
282
  */
128
- async obtainCertificate(domain) {
283
+ async obtainCertificate(domain, isRenewal = false) {
284
+ // Get the domain info
285
+ const domainInfo = this.domainCertificates.get(domain);
286
+ if (!domainInfo) {
287
+ throw new Error(`Domain not found: ${domain}`);
288
+ }
289
+ // Prevent concurrent certificate issuance
290
+ if (domainInfo.obtainingInProgress) {
291
+ console.log(`Certificate issuance already in progress for ${domain}`);
292
+ return;
293
+ }
294
+ domainInfo.obtainingInProgress = true;
295
+ domainInfo.lastRenewalAttempt = new Date();
129
296
  try {
130
297
  const client = await this.getAcmeClient();
131
- // Create a new order for the domain.
298
+ // Create a new order for the domain
132
299
  const order = await client.createOrder({
133
300
  identifiers: [{ type: 'dns', value: domain }],
134
301
  });
135
- // Get the authorizations for the order.
302
+ // Get the authorizations for the order
136
303
  const authorizations = await client.getAuthorizations(order);
137
304
  for (const authz of authorizations) {
138
305
  const challenge = authz.challenges.find(ch => ch.type === 'http-01');
139
306
  if (!challenge) {
140
307
  throw new Error('HTTP-01 challenge not found');
141
308
  }
142
- // Get the key authorization for the challenge.
309
+ // Get the key authorization for the challenge
143
310
  const keyAuthorization = await client.getChallengeKeyAuthorization(challenge);
144
- const domainInfo = this.domainCertificates.get(domain);
311
+ // Store the challenge data
145
312
  domainInfo.challengeToken = challenge.token;
146
313
  domainInfo.challengeKeyAuthorization = keyAuthorization;
147
- // Notify the ACME server that the challenge is ready.
148
- // The acme-client examples show that verifyChallenge takes three arguments:
149
- // (authorization, challenge, keyAuthorization). However, the official TypeScript
150
- // types appear to be out-of-sync. As a workaround, we cast client to 'any'.
151
- await client.verifyChallenge(authz, challenge, keyAuthorization);
152
- await client.completeChallenge(challenge);
153
- // Wait until the challenge is validated.
154
- await client.waitForValidStatus(challenge);
155
- console.log(`HTTP-01 challenge completed for ${domain}`);
314
+ // ACME client type definition workaround - use compatible approach
315
+ // First check if challenge verification is needed
316
+ const authzUrl = authz.url;
317
+ try {
318
+ // Check if authzUrl exists and perform verification
319
+ if (authzUrl) {
320
+ await client.verifyChallenge(authz, challenge);
321
+ }
322
+ // Complete the challenge
323
+ await client.completeChallenge(challenge);
324
+ // Wait for validation
325
+ await client.waitForValidStatus(challenge);
326
+ console.log(`HTTP-01 challenge completed for ${domain}`);
327
+ }
328
+ catch (error) {
329
+ console.error(`Challenge error for ${domain}:`, error);
330
+ throw error;
331
+ }
156
332
  }
157
- // Generate a CSR and a new private key for the domain.
158
- // Convert the resulting Buffers to strings.
159
- const [csrBuffer, privateKeyBuffer] = await acme.forge.createCsr({
333
+ // Generate a CSR and private key
334
+ const [csrBuffer, privateKeyBuffer] = await plugins.acme.forge.createCsr({
160
335
  commonName: domain,
161
336
  });
162
337
  const csr = csrBuffer.toString();
163
338
  const privateKey = privateKeyBuffer.toString();
164
- // Finalize the order and obtain the certificate.
339
+ // Finalize the order with our CSR
165
340
  await client.finalizeOrder(order, csr);
341
+ // Get the certificate with the full chain
166
342
  const certificate = await client.getCertificate(order);
167
- const domainInfo = this.domainCertificates.get(domain);
343
+ // Store the certificate and key
168
344
  domainInfo.certificate = certificate;
169
345
  domainInfo.privateKey = privateKey;
170
346
  domainInfo.certObtained = true;
171
- domainInfo.obtainingInProgress = false;
347
+ // Clear challenge data
172
348
  delete domainInfo.challengeToken;
173
349
  delete domainInfo.challengeKeyAuthorization;
174
- console.log(`Certificate obtained for ${domain}`);
175
- // In a production system, persist the certificate and key and reload your TLS server.
350
+ // Extract expiry date from certificate
351
+ try {
352
+ const matches = certificate.match(/Not After\s*:\s*(.*?)(?:\n|$)/i);
353
+ if (matches && matches[1]) {
354
+ domainInfo.expiryDate = new Date(matches[1]);
355
+ console.log(`Certificate for ${domain} will expire on ${domainInfo.expiryDate.toISOString()}`);
356
+ }
357
+ }
358
+ catch (error) {
359
+ console.warn(`Failed to extract expiry date from certificate for ${domain}`);
360
+ }
361
+ console.log(`Certificate ${isRenewal ? 'renewed' : 'obtained'} for ${domain}`);
362
+ // Emit the appropriate event
363
+ const eventType = isRenewal
364
+ ? CertManagerEvents.CERTIFICATE_RENEWED
365
+ : CertManagerEvents.CERTIFICATE_ISSUED;
366
+ this.emitCertificateEvent(eventType, {
367
+ domain,
368
+ certificate,
369
+ privateKey,
370
+ expiryDate: domainInfo.expiryDate || new Date(Date.now() + 90 * 24 * 60 * 60 * 1000) // 90 days default
371
+ });
176
372
  }
177
373
  catch (error) {
178
- console.error(`Error during certificate issuance for ${domain}:`, error);
179
- const domainInfo = this.domainCertificates.get(domain);
180
- if (domainInfo) {
181
- domainInfo.obtainingInProgress = false;
374
+ // Check for rate limit errors
375
+ if (error.message && (error.message.includes('rateLimited') ||
376
+ error.message.includes('too many certificates') ||
377
+ error.message.includes('rate limit'))) {
378
+ console.error(`Rate limit reached for ${domain}. Waiting before retry.`);
379
+ }
380
+ else {
381
+ console.error(`Error during certificate issuance for ${domain}:`, error);
382
+ }
383
+ // Emit failure event
384
+ this.emit(CertManagerEvents.CERTIFICATE_FAILED, {
385
+ domain,
386
+ error: error.message || 'Unknown error',
387
+ isRenewal
388
+ });
389
+ }
390
+ finally {
391
+ // Reset flag whether successful or not
392
+ domainInfo.obtainingInProgress = false;
393
+ }
394
+ }
395
+ /**
396
+ * Starts the certificate renewal timer
397
+ */
398
+ startRenewalTimer() {
399
+ if (this.renewalTimer) {
400
+ clearInterval(this.renewalTimer);
401
+ }
402
+ // Convert hours to milliseconds
403
+ const checkInterval = this.options.renewCheckIntervalHours * 60 * 60 * 1000;
404
+ this.renewalTimer = setInterval(() => this.checkForRenewals(), checkInterval);
405
+ // Prevent the timer from keeping the process alive
406
+ if (this.renewalTimer.unref) {
407
+ this.renewalTimer.unref();
408
+ }
409
+ console.log(`Certificate renewal check scheduled every ${this.options.renewCheckIntervalHours} hours`);
410
+ }
411
+ /**
412
+ * Checks for certificates that need renewal
413
+ */
414
+ checkForRenewals() {
415
+ if (this.isShuttingDown) {
416
+ return;
417
+ }
418
+ console.log('Checking for certificates that need renewal...');
419
+ const now = new Date();
420
+ const renewThresholdMs = this.options.renewThresholdDays * 24 * 60 * 60 * 1000;
421
+ for (const [domain, domainInfo] of this.domainCertificates.entries()) {
422
+ // Skip domains without certificates or already in renewal
423
+ if (!domainInfo.certObtained || domainInfo.obtainingInProgress) {
424
+ continue;
425
+ }
426
+ // Skip domains without expiry dates
427
+ if (!domainInfo.expiryDate) {
428
+ continue;
429
+ }
430
+ const timeUntilExpiry = domainInfo.expiryDate.getTime() - now.getTime();
431
+ // Check if certificate is near expiry
432
+ if (timeUntilExpiry <= renewThresholdMs) {
433
+ console.log(`Certificate for ${domain} expires soon, renewing...`);
434
+ this.emit(CertManagerEvents.CERTIFICATE_EXPIRING, {
435
+ domain,
436
+ expiryDate: domainInfo.expiryDate,
437
+ daysRemaining: Math.ceil(timeUntilExpiry / (24 * 60 * 60 * 1000))
438
+ });
439
+ // Start renewal process
440
+ this.obtainCertificate(domain, true).catch(err => {
441
+ console.error(`Error renewing certificate for ${domain}:`, err);
442
+ });
182
443
  }
183
444
  }
184
445
  }
446
+ /**
447
+ * Emits a certificate event with the certificate data
448
+ * @param eventType The event type to emit
449
+ * @param data The certificate data
450
+ */
451
+ emitCertificateEvent(eventType, data) {
452
+ this.emit(eventType, data);
453
+ }
185
454
  }
186
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5wb3J0ODBoYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5wb3J0ODBoYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBQzdCLE9BQU8sS0FBSyxJQUFJLE1BQU0sYUFBYSxDQUFDO0FBV3BDLE1BQU0sT0FBTyxhQUFhO0lBTXhCO1FBSFEsZUFBVSxHQUF1QixJQUFJLENBQUM7UUFDdEMsZUFBVSxHQUFrQixJQUFJLENBQUM7UUFHdkMsSUFBSSxDQUFDLGtCQUFrQixHQUFHLElBQUksR0FBRyxFQUE4QixDQUFDO1FBRWhFLDhDQUE4QztRQUM5QyxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQzVFLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxHQUFHLEVBQUU7WUFDMUIsT0FBTyxDQUFDLEdBQUcsQ0FBQyx1Q0FBdUMsQ0FBQyxDQUFDO1FBQ3ZELENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOzs7T0FHRztJQUNJLFNBQVMsQ0FBQyxNQUFjO1FBQzdCLElBQUksQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7WUFDekMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLG1CQUFtQixFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7WUFDekYsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUN6QyxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNJ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
455
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5wb3J0ODBoYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5wb3J0ODBoYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBc0N4Qzs7R0FFRztBQUNILE1BQU0sQ0FBTixJQUFZLGlCQU9YO0FBUEQsV0FBWSxpQkFBaUI7SUFDM0IsOERBQXlDLENBQUE7SUFDekMsZ0VBQTJDLENBQUE7SUFDM0MsOERBQXlDLENBQUE7SUFDekMsa0VBQTZDLENBQUE7SUFDN0Msd0RBQW1DLENBQUE7SUFDbkMsd0RBQW1DLENBQUE7QUFDckMsQ0FBQyxFQVBXLGlCQUFpQixLQUFqQixpQkFBaUIsUUFPNUI7QUFFRDs7R0FFRztBQUNILE1BQU0sT0FBTyxlQUFnQixTQUFRLE9BQU8sQ0FBQyxZQUFZO0lBU3ZEOzs7T0FHRztJQUNILFlBQVksVUFBbUMsRUFBRTtRQUMvQyxLQUFLLEVBQUUsQ0FBQztRQVpGLFdBQU0sR0FBK0IsSUFBSSxDQUFDO1FBQzFDLGVBQVUsR0FBK0IsSUFBSSxDQUFDO1FBQzlDLGVBQVUsR0FBa0IsSUFBSSxDQUFDO1FBQ2pDLGlCQUFZLEdBQTBCLElBQUksQ0FBQztRQUMzQyxtQkFBYyxHQUFZLEtBQUssQ0FBQztRQVN0QyxJQUFJLENBQUMsa0JBQWtCLEdBQUcsSUFBSSxHQUFHLEVBQThCLENBQUM7UUFFaEUsa0JBQWtCO1FBQ2xCLElBQUksQ0FBQyxPQUFPLEdBQUc7WUFDYixJQUFJLEVBQUUsT0FBTyxDQUFDLElBQUksSUFBSSxFQUFFO1lBQ3hCLFlBQVksRUFBRSxPQUFPLENBQUMsWUFBWSxJQUFJLG1CQUFtQjtZQUN6RCxhQUFhLEVBQUUsT0FBTyxDQUFDLGFBQWEsSUFBSSxLQUFLLEVBQUUseUJBQXlCO1lBQ3hFLGtCQUFrQixFQUFFLE9BQU8sQ0FBQyxrQkFBa0IsSUFBSSxFQUFFO1lBQ3BELGlCQUFpQixFQUFF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