@push.rocks/smartproxy 18.0.2 → 18.2.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 (53) hide show
  1. package/dist_ts/00_commitinfo_data.js +1 -1
  2. package/dist_ts/certificate/certificate-manager.d.ts +150 -0
  3. package/dist_ts/certificate/certificate-manager.js +505 -0
  4. package/dist_ts/certificate/events/simplified-events.d.ts +56 -0
  5. package/dist_ts/certificate/events/simplified-events.js +13 -0
  6. package/dist_ts/certificate/models/certificate-errors.d.ts +69 -0
  7. package/dist_ts/certificate/models/certificate-errors.js +141 -0
  8. package/dist_ts/certificate/models/certificate-strategy.d.ts +60 -0
  9. package/dist_ts/certificate/models/certificate-strategy.js +73 -0
  10. package/dist_ts/certificate/simplified-certificate-manager.d.ts +150 -0
  11. package/dist_ts/certificate/simplified-certificate-manager.js +501 -0
  12. package/dist_ts/http/index.d.ts +1 -9
  13. package/dist_ts/http/index.js +5 -11
  14. package/dist_ts/plugins.d.ts +3 -1
  15. package/dist_ts/plugins.js +4 -2
  16. package/dist_ts/proxies/network-proxy/network-proxy.js +3 -1
  17. package/dist_ts/proxies/network-proxy/simplified-certificate-bridge.d.ts +48 -0
  18. package/dist_ts/proxies/network-proxy/simplified-certificate-bridge.js +76 -0
  19. package/dist_ts/proxies/network-proxy/websocket-handler.js +41 -4
  20. package/dist_ts/proxies/smart-proxy/cert-store.d.ts +10 -0
  21. package/dist_ts/proxies/smart-proxy/cert-store.js +70 -0
  22. package/dist_ts/proxies/smart-proxy/certificate-manager.d.ts +116 -0
  23. package/dist_ts/proxies/smart-proxy/certificate-manager.js +401 -0
  24. package/dist_ts/proxies/smart-proxy/legacy-smart-proxy.d.ts +168 -0
  25. package/dist_ts/proxies/smart-proxy/legacy-smart-proxy.js +642 -0
  26. package/dist_ts/proxies/smart-proxy/models/route-types.d.ts +26 -0
  27. package/dist_ts/proxies/smart-proxy/models/route-types.js +1 -1
  28. package/dist_ts/proxies/smart-proxy/models/simplified-smartproxy-config.d.ts +65 -0
  29. package/dist_ts/proxies/smart-proxy/models/simplified-smartproxy-config.js +31 -0
  30. package/dist_ts/proxies/smart-proxy/models/smartproxy-options.d.ts +102 -0
  31. package/dist_ts/proxies/smart-proxy/models/smartproxy-options.js +73 -0
  32. package/dist_ts/proxies/smart-proxy/network-proxy-bridge.d.ts +10 -44
  33. package/dist_ts/proxies/smart-proxy/network-proxy-bridge.js +66 -202
  34. package/dist_ts/proxies/smart-proxy/route-connection-handler.d.ts +4 -0
  35. package/dist_ts/proxies/smart-proxy/route-connection-handler.js +62 -2
  36. package/dist_ts/proxies/smart-proxy/simplified-smart-proxy.d.ts +41 -0
  37. package/dist_ts/proxies/smart-proxy/simplified-smart-proxy.js +132 -0
  38. package/dist_ts/proxies/smart-proxy/smart-proxy.d.ts +18 -13
  39. package/dist_ts/proxies/smart-proxy/smart-proxy.js +79 -196
  40. package/package.json +7 -5
  41. package/readme.md +224 -10
  42. package/readme.plan.md +1405 -617
  43. package/ts/00_commitinfo_data.ts +1 -1
  44. package/ts/http/index.ts +5 -12
  45. package/ts/plugins.ts +4 -1
  46. package/ts/proxies/network-proxy/network-proxy.ts +3 -0
  47. package/ts/proxies/network-proxy/websocket-handler.ts +38 -3
  48. package/ts/proxies/smart-proxy/cert-store.ts +86 -0
  49. package/ts/proxies/smart-proxy/certificate-manager.ts +506 -0
  50. package/ts/proxies/smart-proxy/models/route-types.ts +33 -3
  51. package/ts/proxies/smart-proxy/network-proxy-bridge.ts +86 -239
  52. package/ts/proxies/smart-proxy/route-connection-handler.ts +74 -1
  53. package/ts/proxies/smart-proxy/smart-proxy.ts +105 -222
@@ -0,0 +1,505 @@
1
+ /**
2
+ * Unified certificate manager for SmartProxy
3
+ */
4
+ import * as plugins from '../plugins.js';
5
+ import * as path from 'path';
6
+ import * as fs from 'fs/promises';
7
+ import { CertificateError, CertificateErrors } from './models/certificate-errors.js';
8
+ import { CertificateEvent } from './events/certificate-events.js';
9
+ /**
10
+ * Unified certificate manager
11
+ */
12
+ export class CertificateManager extends plugins.EventEmitter {
13
+ constructor(config) {
14
+ super();
15
+ this.certificateCache = new Map();
16
+ this.pendingRequests = new Map();
17
+ // Validate configuration
18
+ if (!config.certProvider) {
19
+ throw CertificateErrors.noCertProvider();
20
+ }
21
+ if (!config.acmeEmail) {
22
+ throw CertificateErrors.missingAcmeEmail();
23
+ }
24
+ // Set defaults
25
+ this.config = {
26
+ ...config,
27
+ storageDir: config.storageDir || './certs',
28
+ renewBeforeDays: config.renewBeforeDays || 30,
29
+ defaultCertPath: config.defaultCertPath || path.join(process.cwd(), 'assets/certs/cert.pem'),
30
+ defaultKeyPath: config.defaultKeyPath || path.join(process.cwd(), 'assets/certs/key.pem')
31
+ };
32
+ // Ensure storage directory exists
33
+ this.ensureStorageDir();
34
+ }
35
+ /**
36
+ * Initialize the certificate manager
37
+ */
38
+ async start() {
39
+ // Initialize ACME client
40
+ await this.initializeAcmeClient();
41
+ // Load stored certificates
42
+ await this.loadStoredCertificates();
43
+ // Start renewal timer
44
+ this.startRenewalTimer();
45
+ }
46
+ /**
47
+ * Stop the certificate manager
48
+ */
49
+ async stop() {
50
+ if (this.renewalTimer) {
51
+ clearInterval(this.renewalTimer);
52
+ this.renewalTimer = undefined;
53
+ }
54
+ }
55
+ /**
56
+ * Get a certificate for a domain (main entry point)
57
+ */
58
+ async getCertificate(domain) {
59
+ // Check cache first
60
+ const cached = this.certificateCache.get(domain);
61
+ if (cached && this.isCertificateValid(cached)) {
62
+ return cached;
63
+ }
64
+ // Check for pending request to avoid duplicates
65
+ const pending = this.pendingRequests.get(domain);
66
+ if (pending) {
67
+ return pending;
68
+ }
69
+ // Start new certificate request
70
+ const request = this.requestCertificate(domain);
71
+ this.pendingRequests.set(domain, request);
72
+ try {
73
+ const cert = await request;
74
+ this.pendingRequests.delete(domain);
75
+ return cert;
76
+ }
77
+ catch (error) {
78
+ this.pendingRequests.delete(domain);
79
+ throw error;
80
+ }
81
+ }
82
+ /**
83
+ * Request a new certificate
84
+ */
85
+ async requestCertificate(domain) {
86
+ let strategyType = 'static';
87
+ try {
88
+ // Get strategy from provider
89
+ let strategy;
90
+ try {
91
+ strategy = await this.config.certProvider(domain);
92
+ }
93
+ catch (providerError) {
94
+ throw CertificateErrors.invalidCertProvider(providerError);
95
+ }
96
+ // Track strategy type for error reporting
97
+ strategyType = strategy.type === 'skip' ? 'static' : strategy.type;
98
+ let certificate;
99
+ switch (strategy.type) {
100
+ case 'acme-http':
101
+ certificate = await this.requestAcmeHttpCertificate(domain);
102
+ break;
103
+ case 'acme-dns':
104
+ certificate = await this.requestAcmeDnsCertificate(domain);
105
+ break;
106
+ case 'static':
107
+ certificate = {
108
+ domain,
109
+ certificate: strategy.cert,
110
+ privateKey: strategy.key,
111
+ expiresAt: strategy.expiresAt || new Date(Date.now() + 90 * 24 * 60 * 60 * 1000),
112
+ source: 'static'
113
+ };
114
+ break;
115
+ case 'skip':
116
+ throw CertificateErrors.certificateNotFound(domain);
117
+ default:
118
+ throw CertificateErrors.invalidCertProvider(new Error('Unknown strategy type'));
119
+ }
120
+ // Cache and store
121
+ this.certificateCache.set(domain, certificate);
122
+ await this.storeCertificate(certificate);
123
+ // Emit success event
124
+ this.emit(CertificateEvent.OBTAINED, {
125
+ domain,
126
+ type: 'new',
127
+ expiresAt: certificate.expiresAt,
128
+ source: certificate.source,
129
+ certificate: certificate.certificate,
130
+ privateKey: certificate.privateKey
131
+ });
132
+ return certificate;
133
+ }
134
+ catch (error) {
135
+ const certError = error instanceof CertificateError
136
+ ? error
137
+ : new CertificateError({
138
+ code: 'UNKNOWN_ERROR',
139
+ message: error.message || 'Unknown error',
140
+ domain,
141
+ cause: error
142
+ });
143
+ this.emit(CertificateEvent.FAILED, {
144
+ domain,
145
+ error: certError,
146
+ strategy: strategyType
147
+ });
148
+ throw certError;
149
+ }
150
+ }
151
+ /**
152
+ * Request certificate via ACME HTTP-01
153
+ */
154
+ async requestAcmeHttpCertificate(domain) {
155
+ if (domain.includes('*')) {
156
+ throw CertificateErrors.wildcardNotSupported(domain);
157
+ }
158
+ try {
159
+ // Create ACME order
160
+ const order = await this.acmeClient.createOrder({
161
+ identifiers: [{ type: 'dns', value: domain }]
162
+ });
163
+ // Get authorization
164
+ const authorization = await this.acmeClient.getAuthorization(order.authorizations[0]);
165
+ const challenge = authorization.challenges.find(c => c.type === 'http-01');
166
+ if (!challenge) {
167
+ throw new Error('No HTTP-01 challenge available');
168
+ }
169
+ // Prepare challenge response
170
+ const keyAuthorization = await this.acmeClient.getChallengeKeyAuthorization(challenge);
171
+ // Set up HTTP responder (this would integrate with Port80Handler)
172
+ await this.setupHttpChallenge(challenge.token, keyAuthorization);
173
+ // Notify ACME server
174
+ await this.acmeClient.completeChallenge(challenge);
175
+ await this.acmeClient.waitForValidation(challenge);
176
+ // Generate CSR
177
+ const keypair = await this.generateKeypair();
178
+ const csr = await this.generateCsr(domain, keypair);
179
+ // Finalize order
180
+ await this.acmeClient.finalizeOrder(order, csr);
181
+ const cert = await this.acmeClient.getCertificate(order);
182
+ // Clean up challenge
183
+ await this.cleanupHttpChallenge(challenge.token);
184
+ return {
185
+ domain,
186
+ certificate: cert,
187
+ privateKey: keypair.privateKey,
188
+ expiresAt: this.extractExpiryDate(cert),
189
+ source: 'acme-http'
190
+ };
191
+ }
192
+ catch (error) {
193
+ throw CertificateErrors.acmeHttpChallengeFailed(domain, error);
194
+ }
195
+ }
196
+ /**
197
+ * Request certificate via ACME DNS-01
198
+ */
199
+ async requestAcmeDnsCertificate(domain) {
200
+ try {
201
+ // Create ACME order
202
+ const order = await this.acmeClient.createOrder({
203
+ identifiers: [{ type: 'dns', value: domain }]
204
+ });
205
+ // Get authorization
206
+ const authorization = await this.acmeClient.getAuthorization(order.authorizations[0]);
207
+ const challenge = authorization.challenges.find(c => c.type === 'dns-01');
208
+ if (!challenge) {
209
+ throw new Error('No DNS-01 challenge available');
210
+ }
211
+ // Get DNS record value
212
+ const keyAuthorization = await this.acmeClient.getChallengeKeyAuthorization(challenge);
213
+ const dnsRecord = this.acmeClient.keyAuthorizationToDns01(keyAuthorization);
214
+ // Note: Actual DNS record creation would be handled externally
215
+ console.log(`Please create DNS TXT record: _acme-challenge.${domain} = ${dnsRecord}`);
216
+ // In a real implementation, we'd wait for DNS propagation
217
+ // For now, this is a placeholder
218
+ await new Promise(resolve => setTimeout(resolve, 60000)); // Wait 60 seconds
219
+ // Notify ACME server
220
+ await this.acmeClient.completeChallenge(challenge);
221
+ await this.acmeClient.waitForValidation(challenge);
222
+ // Generate CSR
223
+ const keypair = await this.generateKeypair();
224
+ const csr = await this.generateCsr(domain, keypair);
225
+ // Finalize order
226
+ await this.acmeClient.finalizeOrder(order, csr);
227
+ const cert = await this.acmeClient.getCertificate(order);
228
+ return {
229
+ domain,
230
+ certificate: cert,
231
+ privateKey: keypair.privateKey,
232
+ expiresAt: this.extractExpiryDate(cert),
233
+ source: 'acme-dns'
234
+ };
235
+ }
236
+ catch (error) {
237
+ throw CertificateErrors.acmeDnsChallengeFailed(domain, error);
238
+ }
239
+ }
240
+ /**
241
+ * Renew a certificate
242
+ */
243
+ async renewCertificate(domain) {
244
+ const existing = this.certificateCache.get(domain);
245
+ if (!existing) {
246
+ throw CertificateErrors.certificateNotFound(domain);
247
+ }
248
+ try {
249
+ // Request new certificate
250
+ const renewed = await this.requestCertificate(domain);
251
+ // Emit renewal event
252
+ this.emit(CertificateEvent.OBTAINED, {
253
+ domain,
254
+ type: 'renewed',
255
+ expiresAt: renewed.expiresAt,
256
+ source: renewed.source,
257
+ certificate: renewed.certificate,
258
+ privateKey: renewed.privateKey
259
+ });
260
+ return renewed;
261
+ }
262
+ catch (error) {
263
+ throw error;
264
+ }
265
+ }
266
+ /**
267
+ * Check certificates for renewal
268
+ */
269
+ async checkForRenewals() {
270
+ for (const [domain, cert] of this.certificateCache.entries()) {
271
+ if (this.shouldRenew(cert)) {
272
+ try {
273
+ await this.renewCertificate(domain);
274
+ }
275
+ catch (error) {
276
+ console.error(`Failed to renew certificate for ${domain}:`, error);
277
+ }
278
+ }
279
+ else if (this.isExpiringSoon(cert)) {
280
+ this.emit(CertificateEvent.EXPIRING, {
281
+ domain,
282
+ expiresAt: cert.expiresAt,
283
+ daysRemaining: this.getDaysRemaining(cert)
284
+ });
285
+ }
286
+ }
287
+ }
288
+ /**
289
+ * Initialize ACME client
290
+ */
291
+ async initializeAcmeClient() {
292
+ // ACME client initialization placeholder
293
+ // In a real implementation, this would use an ACME library
294
+ console.log(`Initializing ACME client for ${this.config.acmeServer} environment`);
295
+ }
296
+ /**
297
+ * Load stored certificates from disk
298
+ */
299
+ async loadStoredCertificates() {
300
+ try {
301
+ const files = await fs.readdir(this.config.storageDir);
302
+ const certFiles = files.filter(f => f.endsWith('.json'));
303
+ for (const file of certFiles) {
304
+ try {
305
+ const content = await fs.readFile(path.join(this.config.storageDir, file), 'utf-8');
306
+ const cert = JSON.parse(content);
307
+ cert.expiresAt = new Date(cert.expiresAt);
308
+ if (this.isCertificateValid(cert)) {
309
+ this.certificateCache.set(cert.domain, cert);
310
+ }
311
+ }
312
+ catch (error) {
313
+ console.error(`Failed to load certificate ${file}:`, error);
314
+ }
315
+ }
316
+ }
317
+ catch (error) {
318
+ console.error('Failed to load certificates:', error);
319
+ }
320
+ }
321
+ /**
322
+ * Store certificate to disk
323
+ */
324
+ async storeCertificate(cert) {
325
+ const filename = `${cert.domain}.json`;
326
+ const filepath = path.join(this.config.storageDir, filename);
327
+ try {
328
+ await fs.writeFile(filepath, JSON.stringify(cert, null, 2));
329
+ // Also save individual cert and key files
330
+ await fs.writeFile(path.join(this.config.storageDir, `${cert.domain}.crt`), cert.certificate);
331
+ await fs.writeFile(path.join(this.config.storageDir, `${cert.domain}.key`), cert.privateKey);
332
+ // Set proper permissions on key file
333
+ await fs.chmod(path.join(this.config.storageDir, `${cert.domain}.key`), 0o600);
334
+ }
335
+ catch (error) {
336
+ throw CertificateErrors.storageError('write', filepath, error);
337
+ }
338
+ }
339
+ /**
340
+ * Ensure storage directory exists
341
+ */
342
+ async ensureStorageDir() {
343
+ try {
344
+ await fs.mkdir(this.config.storageDir, { recursive: true });
345
+ }
346
+ catch (error) {
347
+ console.error('Failed to create storage directory:', error);
348
+ }
349
+ }
350
+ /**
351
+ * Get or create ACME account key
352
+ */
353
+ async getOrCreateAccountKey() {
354
+ const keyPath = path.join(this.config.storageDir, 'account.key');
355
+ try {
356
+ return await fs.readFile(keyPath, 'utf-8');
357
+ }
358
+ catch {
359
+ // Generate new key - placeholder
360
+ const dummyKey = '-----BEGIN PRIVATE KEY-----\nDUMMY_KEY_FOR_TESTING\n-----END PRIVATE KEY-----';
361
+ await fs.writeFile(keyPath, dummyKey);
362
+ await fs.chmod(keyPath, 0o600);
363
+ return dummyKey;
364
+ }
365
+ }
366
+ /**
367
+ * Generate keypair for certificate
368
+ */
369
+ async generateKeypair() {
370
+ // Keypair generation placeholder
371
+ return {
372
+ privateKey: '-----BEGIN PRIVATE KEY-----\nDUMMY_PRIVATE_KEY\n-----END PRIVATE KEY-----',
373
+ publicKey: '-----BEGIN PUBLIC KEY-----\nDUMMY_PUBLIC_KEY\n-----END PUBLIC KEY-----'
374
+ };
375
+ }
376
+ /**
377
+ * Generate CSR for domain
378
+ */
379
+ async generateCsr(domain, keypair) {
380
+ // CSR generation placeholder
381
+ return `-----BEGIN CERTIFICATE REQUEST-----\nDUMMY_CSR_FOR_${domain}\n-----END CERTIFICATE REQUEST-----`;
382
+ }
383
+ /**
384
+ * Extract expiry date from certificate
385
+ */
386
+ extractExpiryDate(certPem) {
387
+ // Certificate expiry extraction placeholder
388
+ // In a real implementation, this would parse the certificate
389
+ return new Date(Date.now() + 90 * 24 * 60 * 60 * 1000); // 90 days from now
390
+ }
391
+ /**
392
+ * Check if certificate is valid
393
+ */
394
+ isCertificateValid(cert) {
395
+ return cert.expiresAt > new Date();
396
+ }
397
+ /**
398
+ * Check if certificate should be renewed
399
+ */
400
+ shouldRenew(cert) {
401
+ const daysRemaining = this.getDaysRemaining(cert);
402
+ return daysRemaining <= this.config.renewBeforeDays;
403
+ }
404
+ /**
405
+ * Check if certificate is expiring soon
406
+ */
407
+ isExpiringSoon(cert) {
408
+ const daysRemaining = this.getDaysRemaining(cert);
409
+ return daysRemaining <= this.config.renewBeforeDays + 7; // Warn 7 days before renewal
410
+ }
411
+ /**
412
+ * Get days remaining until expiry
413
+ */
414
+ getDaysRemaining(cert) {
415
+ const now = new Date();
416
+ const diff = cert.expiresAt.getTime() - now.getTime();
417
+ return Math.floor(diff / (1000 * 60 * 60 * 24));
418
+ }
419
+ /**
420
+ * Start renewal timer
421
+ */
422
+ startRenewalTimer() {
423
+ // Check every 6 hours
424
+ this.renewalTimer = setInterval(() => {
425
+ this.checkForRenewals().catch(error => {
426
+ console.error('Renewal check failed:', error);
427
+ });
428
+ }, 6 * 60 * 60 * 1000);
429
+ // Also check immediately
430
+ this.checkForRenewals().catch(error => {
431
+ console.error('Initial renewal check failed:', error);
432
+ });
433
+ }
434
+ /**
435
+ * Get default certificate for SNI fallback
436
+ */
437
+ async getDefaultCertificate() {
438
+ try {
439
+ const [cert, key] = await Promise.all([
440
+ fs.readFile(this.config.defaultCertPath, 'utf-8'),
441
+ fs.readFile(this.config.defaultKeyPath, 'utf-8')
442
+ ]);
443
+ return { cert, key };
444
+ }
445
+ catch (error) {
446
+ throw new CertificateError({
447
+ code: 'DEFAULT_CERT_ERROR',
448
+ message: 'Failed to load default certificate',
449
+ solution: 'Ensure default certificate files exist at configured paths',
450
+ cause: error
451
+ });
452
+ }
453
+ }
454
+ /**
455
+ * Set up HTTP challenge responder
456
+ */
457
+ async setupHttpChallenge(token, keyAuthorization) {
458
+ // This would integrate with Port80Handler
459
+ // For now, it's a placeholder
460
+ console.log(`HTTP Challenge: /.well-known/acme-challenge/${token} = ${keyAuthorization}`);
461
+ }
462
+ /**
463
+ * Clean up HTTP challenge
464
+ */
465
+ async cleanupHttpChallenge(token) {
466
+ // This would integrate with Port80Handler
467
+ // For now, it's a placeholder
468
+ console.log(`Cleanup HTTP Challenge: ${token}`);
469
+ }
470
+ /**
471
+ * Type assertion for event emitter
472
+ */
473
+ on(event, listener) {
474
+ return super.on(event, listener);
475
+ }
476
+ off(event, listener) {
477
+ return super.off(event, listener);
478
+ }
479
+ emit(event, data) {
480
+ return super.emit(event, data);
481
+ }
482
+ /**
483
+ * Update routes (placeholder for future implementation)
484
+ */
485
+ async updateRoutes(routes) {
486
+ // Process routes to extract certificate requirements
487
+ for (const route of routes) {
488
+ if (route.action.type === 'forward' &&
489
+ route.action.tls?.mode === 'terminate' &&
490
+ route.action.tls?.certificate === 'auto' &&
491
+ route.match.domains) {
492
+ const domains = Array.isArray(route.match.domains)
493
+ ? route.match.domains
494
+ : [route.match.domains];
495
+ for (const domain of domains) {
496
+ // Trigger certificate retrieval for auto domains
497
+ this.getCertificate(domain).catch(err => {
498
+ console.error(`Failed to get certificate for ${domain}:`, err);
499
+ });
500
+ }
501
+ }
502
+ }
503
+ }
504
+ }
505
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VydGlmaWNhdGUtbWFuYWdlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2NlcnRpZmljYXRlL2NlcnRpZmljYXRlLW1hbmFnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUM3QixPQUFPLEtBQUssRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUVsQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNyRixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQStCbEU7O0dBRUc7QUFDSCxNQUFNLE9BQU8sa0JBQW1CLFNBQVEsT0FBTyxDQUFDLFlBQVk7SUFPMUQsWUFBWSxNQUFnQztRQUMxQyxLQUFLLEVBQUUsQ0FBQztRQU5GLHFCQUFnQixHQUFHLElBQUksR0FBRyxFQUE2QixDQUFDO1FBR3hELG9CQUFlLEdBQUcsSUFBSSxHQUFHLEVBQXNDLENBQUM7UUFLdEUseUJBQXlCO1FBQ3pCLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDekIsTUFBTSxpQkFBaUIsQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUMzQyxDQUFDO1FBRUQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUN0QixNQUFNLGlCQUFpQixDQUFDLGdCQUFnQixFQUFFLENBQUM7UUFDN0MsQ0FBQztRQUVELGVBQWU7UUFDZixJQUFJLENBQUMsTUFBTSxHQUFHO1lBQ1osR0FBRyxNQUFNO1lBQ1QsVUFBVSxFQUFFLE1BQU0sQ0FBQyxVQUFVLElBQUksU0FBUztZQUMxQyxlQUFlLEVBQUUsTUFBTSxDQUFDLGVBQWUsSUFBSSxFQUFFO1lBQzdDLGVBQWUsRUFBRSxNQUFNLENBQUMsZUFBZSxJQUFJLElBQUksQ0FB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
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Simplified certificate event system
3
+ */
4
+ import type { CertificateError } from '../models/certificate-errors.js';
5
+ /**
6
+ * Certificate event types - only the essentials
7
+ */
8
+ export declare enum CertificateEvent {
9
+ OBTAINED = "certificate:obtained",
10
+ FAILED = "certificate:failed",
11
+ EXPIRING = "certificate:expiring"
12
+ }
13
+ /**
14
+ * Certificate obtained event data
15
+ */
16
+ export interface CertificateObtainedEvent {
17
+ domain: string;
18
+ type: 'new' | 'renewed';
19
+ expiresAt: Date;
20
+ source: 'acme-http' | 'acme-dns' | 'static';
21
+ certificate: string;
22
+ privateKey: string;
23
+ }
24
+ /**
25
+ * Certificate failed event data
26
+ */
27
+ export interface CertificateFailedEvent {
28
+ domain: string;
29
+ error: CertificateError;
30
+ attemptNumber?: number;
31
+ willRetry?: boolean;
32
+ }
33
+ /**
34
+ * Certificate expiring event data
35
+ */
36
+ export interface CertificateExpiringEvent {
37
+ domain: string;
38
+ expiresAt: Date;
39
+ daysRemaining: number;
40
+ }
41
+ /**
42
+ * Combined event map for TypeScript typing
43
+ */
44
+ export interface CertificateEventMap {
45
+ [CertificateEvent.OBTAINED]: CertificateObtainedEvent;
46
+ [CertificateEvent.FAILED]: CertificateFailedEvent;
47
+ [CertificateEvent.EXPIRING]: CertificateExpiringEvent;
48
+ }
49
+ /**
50
+ * Type-safe event emitter interface
51
+ */
52
+ export interface ICertificateEventEmitter {
53
+ on<K extends keyof CertificateEventMap>(event: K, listener: (data: CertificateEventMap[K]) => void): this;
54
+ off<K extends keyof CertificateEventMap>(event: K, listener: (data: CertificateEventMap[K]) => void): this;
55
+ emit<K extends keyof CertificateEventMap>(event: K, data: CertificateEventMap[K]): boolean;
56
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Simplified certificate event system
3
+ */
4
+ /**
5
+ * Certificate event types - only the essentials
6
+ */
7
+ export var CertificateEvent;
8
+ (function (CertificateEvent) {
9
+ CertificateEvent["OBTAINED"] = "certificate:obtained";
10
+ CertificateEvent["FAILED"] = "certificate:failed";
11
+ CertificateEvent["EXPIRING"] = "certificate:expiring";
12
+ })(CertificateEvent || (CertificateEvent = {}));
13
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2ltcGxpZmllZC1ldmVudHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9jZXJ0aWZpY2F0ZS9ldmVudHMvc2ltcGxpZmllZC1ldmVudHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFJSDs7R0FFRztBQUNILE1BQU0sQ0FBTixJQUFZLGdCQUlYO0FBSkQsV0FBWSxnQkFBZ0I7SUFDMUIscURBQWlDLENBQUE7SUFDakMsaURBQTZCLENBQUE7SUFDN0IscURBQWlDLENBQUE7QUFDbkMsQ0FBQyxFQUpXLGdCQUFnQixLQUFoQixnQkFBZ0IsUUFJM0IifQ==
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Structured error types for certificate management
3
+ */
4
+ export interface CertificateErrorDetails {
5
+ code: string;
6
+ message: string;
7
+ solution?: string;
8
+ domain?: string;
9
+ challengeType?: 'http' | 'dns';
10
+ details?: Record<string, any>;
11
+ cause?: Error;
12
+ }
13
+ /**
14
+ * Certificate-specific error class with structured information
15
+ */
16
+ export declare class CertificateError extends Error {
17
+ readonly code: string;
18
+ readonly solution?: string;
19
+ readonly domain?: string;
20
+ readonly challengeType?: 'http' | 'dns';
21
+ readonly details?: Record<string, any>;
22
+ readonly cause?: Error;
23
+ constructor(details: CertificateErrorDetails);
24
+ /**
25
+ * Convert error to JSON for logging
26
+ */
27
+ toJSON(): Record<string, any>;
28
+ }
29
+ /**
30
+ * Common certificate error codes
31
+ */
32
+ export declare const CertificateErrorCodes: {
33
+ readonly NO_CERT_PROVIDER: "NO_CERT_PROVIDER";
34
+ readonly INVALID_CERT_PROVIDER: "INVALID_CERT_PROVIDER";
35
+ readonly MISSING_ACME_EMAIL: "MISSING_ACME_EMAIL";
36
+ readonly ACME_HTTP_CHALLENGE_FAILED: "ACME_HTTP_CHALLENGE_FAILED";
37
+ readonly ACME_DNS_CHALLENGE_FAILED: "ACME_DNS_CHALLENGE_FAILED";
38
+ readonly ACME_RATE_LIMITED: "ACME_RATE_LIMITED";
39
+ readonly ACME_ACCOUNT_ERROR: "ACME_ACCOUNT_ERROR";
40
+ readonly ACME_VALIDATION_ERROR: "ACME_VALIDATION_ERROR";
41
+ readonly CERTIFICATE_EXPIRED: "CERTIFICATE_EXPIRED";
42
+ readonly CERTIFICATE_INVALID: "CERTIFICATE_INVALID";
43
+ readonly CERTIFICATE_NOT_FOUND: "CERTIFICATE_NOT_FOUND";
44
+ readonly CERTIFICATE_PARSE_ERROR: "CERTIFICATE_PARSE_ERROR";
45
+ readonly STORAGE_READ_ERROR: "STORAGE_READ_ERROR";
46
+ readonly STORAGE_WRITE_ERROR: "STORAGE_WRITE_ERROR";
47
+ readonly STORAGE_PERMISSION_ERROR: "STORAGE_PERMISSION_ERROR";
48
+ readonly NETWORK_TIMEOUT: "NETWORK_TIMEOUT";
49
+ readonly NETWORK_UNREACHABLE: "NETWORK_UNREACHABLE";
50
+ readonly DNS_RESOLUTION_FAILED: "DNS_RESOLUTION_FAILED";
51
+ readonly INVALID_DOMAIN: "INVALID_DOMAIN";
52
+ readonly WILDCARD_NOT_SUPPORTED: "WILDCARD_NOT_SUPPORTED";
53
+ readonly DOMAIN_NOT_CONFIGURED: "DOMAIN_NOT_CONFIGURED";
54
+ };
55
+ /**
56
+ * Helper functions for creating common certificate errors
57
+ */
58
+ export declare const CertificateErrors: {
59
+ noCertProvider: () => CertificateError;
60
+ invalidCertProvider: (error: Error) => CertificateError;
61
+ missingAcmeEmail: () => CertificateError;
62
+ acmeHttpChallengeFailed: (domain: string, details?: any) => CertificateError;
63
+ acmeDnsChallengeFailed: (domain: string, details?: any) => CertificateError;
64
+ acmeRateLimited: (domain: string, resetTime?: Date) => CertificateError;
65
+ certificateExpired: (domain: string, expiredAt: Date) => CertificateError;
66
+ certificateNotFound: (domain: string) => CertificateError;
67
+ wildcardNotSupported: (domain: string) => CertificateError;
68
+ storageError: (operation: "read" | "write", path: string, error: Error) => CertificateError;
69
+ };