@kangwifi-pro/waliwa 1.0.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/LICENSE +21 -0
- package/README.md +600 -0
- package/dist/advanced/features.d.ts +211 -0
- package/dist/advanced/features.d.ts.map +1 -0
- package/dist/advanced/features.js +671 -0
- package/dist/advanced/features.js.map +1 -0
- package/dist/auth/auth-state.d.ts +89 -0
- package/dist/auth/auth-state.d.ts.map +1 -0
- package/dist/auth/auth-state.js +330 -0
- package/dist/auth/auth-state.js.map +1 -0
- package/dist/auth/pairing-code.d.ts +78 -0
- package/dist/auth/pairing-code.d.ts.map +1 -0
- package/dist/auth/pairing-code.js +191 -0
- package/dist/auth/pairing-code.js.map +1 -0
- package/dist/auth/qr-code.d.ts +60 -0
- package/dist/auth/qr-code.d.ts.map +1 -0
- package/dist/auth/qr-code.js +151 -0
- package/dist/auth/qr-code.js.map +1 -0
- package/dist/calls/handler.d.ts +61 -0
- package/dist/calls/handler.d.ts.map +1 -0
- package/dist/calls/handler.js +117 -0
- package/dist/calls/handler.js.map +1 -0
- package/dist/core/binary.d.ts +74 -0
- package/dist/core/binary.d.ts.map +1 -0
- package/dist/core/binary.js +448 -0
- package/dist/core/binary.js.map +1 -0
- package/dist/core/crypto.d.ts +60 -0
- package/dist/core/crypto.d.ts.map +1 -0
- package/dist/core/crypto.js +170 -0
- package/dist/core/crypto.js.map +1 -0
- package/dist/core/noise.d.ts +106 -0
- package/dist/core/noise.d.ts.map +1 -0
- package/dist/core/noise.js +307 -0
- package/dist/core/noise.js.map +1 -0
- package/dist/events/emitter.d.ts +44 -0
- package/dist/events/emitter.d.ts.map +1 -0
- package/dist/events/emitter.js +79 -0
- package/dist/events/emitter.js.map +1 -0
- package/dist/features/index.d.ts +342 -0
- package/dist/features/index.d.ts.map +1 -0
- package/dist/features/index.js +755 -0
- package/dist/features/index.js.map +1 -0
- package/dist/fixes/index.d.ts +333 -0
- package/dist/fixes/index.d.ts.map +1 -0
- package/dist/fixes/index.js +762 -0
- package/dist/fixes/index.js.map +1 -0
- package/dist/groups/management.d.ts +86 -0
- package/dist/groups/management.d.ts.map +1 -0
- package/dist/groups/management.js +443 -0
- package/dist/groups/management.js.map +1 -0
- package/dist/index.d.ts +65 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +236 -0
- package/dist/index.js.map +1 -0
- package/dist/messages/media.d.ts +93 -0
- package/dist/messages/media.d.ts.map +1 -0
- package/dist/messages/media.js +252 -0
- package/dist/messages/media.js.map +1 -0
- package/dist/messages/message-encoder.d.ts +70 -0
- package/dist/messages/message-encoder.d.ts.map +1 -0
- package/dist/messages/message-encoder.js +453 -0
- package/dist/messages/message-encoder.js.map +1 -0
- package/dist/messages/send.d.ts +101 -0
- package/dist/messages/send.d.ts.map +1 -0
- package/dist/messages/send.js +409 -0
- package/dist/messages/send.js.map +1 -0
- package/dist/recovery/index.d.ts +125 -0
- package/dist/recovery/index.d.ts.map +1 -0
- package/dist/recovery/index.js +584 -0
- package/dist/recovery/index.js.map +1 -0
- package/dist/skdm/index.d.ts +220 -0
- package/dist/skdm/index.d.ts.map +1 -0
- package/dist/skdm/index.js +600 -0
- package/dist/skdm/index.js.map +1 -0
- package/dist/socket/hybrid.d.ts +118 -0
- package/dist/socket/hybrid.d.ts.map +1 -0
- package/dist/socket/hybrid.js +352 -0
- package/dist/socket/hybrid.js.map +1 -0
- package/dist/socket/wa-socket.d.ts +300 -0
- package/dist/socket/wa-socket.d.ts.map +1 -0
- package/dist/socket/wa-socket.js +1094 -0
- package/dist/socket/wa-socket.js.map +1 -0
- package/dist/socket/ws-socket.d.ts +96 -0
- package/dist/socket/ws-socket.d.ts.map +1 -0
- package/dist/socket/ws-socket.js +302 -0
- package/dist/socket/ws-socket.js.map +1 -0
- package/dist/types/index.d.ts +444 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +7 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/jid.d.ts +46 -0
- package/dist/utils/jid.d.ts.map +1 -0
- package/dist/utils/jid.js +152 -0
- package/dist/utils/jid.js.map +1 -0
- package/dist/utils/logger.d.ts +45 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +79 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/retry.d.ts +43 -0
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/utils/retry.js +175 -0
- package/dist/utils/retry.js.map +1 -0
- package/docs/API.md +745 -0
- package/docs/ARCHITECTURE.md +307 -0
- package/docs/BAILEYS_FIXES.md +360 -0
- package/docs/FEATURES.md +532 -0
- package/docs/PROTOCOL.md +489 -0
- package/docs/RECOVERY.md +409 -0
- package/docs/SKDM.md +233 -0
- package/examples/ai-bot/index.ts +479 -0
- package/examples/ai-bot/package.json +17 -0
- package/examples/echo-bot/index.ts +171 -0
- package/examples/echo-bot/package.json +18 -0
- package/examples/group-bot/index.ts +557 -0
- package/examples/group-bot/package.json +17 -0
- package/examples/rest-gateway/index.ts +499 -0
- package/examples/rest-gateway/package.json +19 -0
- package/package.json +75 -0
- package/src/advanced/features.ts +817 -0
- package/src/auth/auth-state.ts +342 -0
- package/src/auth/pairing-code.ts +246 -0
- package/src/auth/qr-code.ts +191 -0
- package/src/calls/handler.ts +153 -0
- package/src/core/binary.ts +464 -0
- package/src/core/crypto.ts +189 -0
- package/src/core/noise.ts +406 -0
- package/src/events/emitter.ts +88 -0
- package/src/features/index.ts +921 -0
- package/src/fixes/index.ts +882 -0
- package/src/groups/management.ts +497 -0
- package/src/index.ts +274 -0
- package/src/messages/media.ts +372 -0
- package/src/messages/message-encoder.ts +520 -0
- package/src/messages/send.ts +521 -0
- package/src/recovery/index.ts +704 -0
- package/src/skdm/index.ts +693 -0
- package/src/socket/hybrid.ts +414 -0
- package/src/socket/wa-socket.ts +1347 -0
- package/src/socket/ws-socket.ts +355 -0
- package/src/types/index.ts +457 -0
- package/src/utils/jid.ts +156 -0
- package/src/utils/logger.ts +84 -0
- package/src/utils/retry.ts +205 -0
- package/tsconfig.json +30 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Waliwa - Logger utility (pino-based, RAM-efficient)
|
|
3
|
+
* Default level 'warn' untuk production hemat RAM.
|
|
4
|
+
*/
|
|
5
|
+
import type { WALogger } from '../types/index.js';
|
|
6
|
+
type LogLevel = 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace';
|
|
7
|
+
/**
|
|
8
|
+
* Lightweight logger - lebih ringan dari pino untuk RAM efficiency
|
|
9
|
+
* Tetap API-compatible dengan pino agar mudah di-swap
|
|
10
|
+
*/
|
|
11
|
+
export declare class DefaultLogger implements WALogger {
|
|
12
|
+
level: LogLevel;
|
|
13
|
+
private meta;
|
|
14
|
+
constructor(level?: LogLevel);
|
|
15
|
+
child(meta?: Record<string, any>): WALogger;
|
|
16
|
+
private shouldLog;
|
|
17
|
+
private format;
|
|
18
|
+
private log;
|
|
19
|
+
fatal(msg: string, ...args: any[]): void;
|
|
20
|
+
error(msg: string, ...args: any[]): void;
|
|
21
|
+
warn(msg: string, ...args: any[]): void;
|
|
22
|
+
info(msg: string, ...args: any[]): void;
|
|
23
|
+
debug(msg: string, ...args: any[]): void;
|
|
24
|
+
trace(msg: string, ...args: any[]): void;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Default logger instance (singleton, RAM-friendly)
|
|
28
|
+
*/
|
|
29
|
+
export declare const defaultLogger: DefaultLogger;
|
|
30
|
+
/**
|
|
31
|
+
* Silent logger - untuk testing atau production mode tanpa logs
|
|
32
|
+
*/
|
|
33
|
+
export declare class SilentLogger implements WALogger {
|
|
34
|
+
level: LogLevel;
|
|
35
|
+
child(): WALogger;
|
|
36
|
+
fatal(): void;
|
|
37
|
+
error(): void;
|
|
38
|
+
warn(): void;
|
|
39
|
+
info(): void;
|
|
40
|
+
debug(): void;
|
|
41
|
+
trace(): void;
|
|
42
|
+
}
|
|
43
|
+
export declare const silentLogger: SilentLogger;
|
|
44
|
+
export {};
|
|
45
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAElD,KAAK,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAKxE;;;GAGG;AACH,qBAAa,aAAc,YAAW,QAAQ;IAC5C,KAAK,EAAE,QAAQ,CAAU;IACzB,OAAO,CAAC,IAAI,CAA2B;gBAE3B,KAAK,GAAE,QAAiB;IAIpC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,QAAQ;IAM3C,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,MAAM;IAUd,OAAO,CAAC,GAAG;IAYX,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IACxC,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IACxC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IACvC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IACvC,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IACxC,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;CACzC;AAED;;GAEG;AACH,eAAO,MAAM,aAAa,eAAwE,CAAC;AAEnG;;GAEG;AACH,qBAAa,YAAa,YAAW,QAAQ;IAC3C,KAAK,EAAE,QAAQ,CAAmB;IAClC,KAAK,IAAI,QAAQ;IACjB,KAAK,IAAI,IAAI;IACb,KAAK,IAAI,IAAI;IACb,IAAI,IAAI,IAAI;IACZ,IAAI,IAAI,IAAI;IACZ,KAAK,IAAI,IAAI;IACb,KAAK,IAAI,IAAI;CACd;AAED,eAAO,MAAM,YAAY,cAAqB,CAAC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Waliwa - Logger utility (pino-based, RAM-efficient)
|
|
4
|
+
* Default level 'warn' untuk production hemat RAM.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.silentLogger = exports.SilentLogger = exports.defaultLogger = exports.DefaultLogger = void 0;
|
|
8
|
+
const LEVEL_PRIORITY = {
|
|
9
|
+
fatal: 60, error: 50, warn: 40, info: 30, debug: 20, trace: 10
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Lightweight logger - lebih ringan dari pino untuk RAM efficiency
|
|
13
|
+
* Tetap API-compatible dengan pino agar mudah di-swap
|
|
14
|
+
*/
|
|
15
|
+
class DefaultLogger {
|
|
16
|
+
level = 'warn';
|
|
17
|
+
meta = {};
|
|
18
|
+
constructor(level = 'warn') {
|
|
19
|
+
this.level = level;
|
|
20
|
+
}
|
|
21
|
+
child(meta) {
|
|
22
|
+
const child = new DefaultLogger(this.level);
|
|
23
|
+
child.meta = { ...this.meta, ...(meta || {}) };
|
|
24
|
+
return child;
|
|
25
|
+
}
|
|
26
|
+
shouldLog(level) {
|
|
27
|
+
return LEVEL_PRIORITY[level] >= LEVEL_PRIORITY[this.level];
|
|
28
|
+
}
|
|
29
|
+
format(level, msg, args) {
|
|
30
|
+
const ts = new Date().toISOString();
|
|
31
|
+
const metaStr = Object.keys(this.meta).length
|
|
32
|
+
? ' ' + JSON.stringify(this.meta)
|
|
33
|
+
: '';
|
|
34
|
+
const argsStr = args.length ? ' ' + args.map(a => typeof a === 'object' ? JSON.stringify(a) : String(a)).join(' ')
|
|
35
|
+
: '';
|
|
36
|
+
return `[${ts}] ${level.toUpperCase()}${metaStr} ${msg}${argsStr}`;
|
|
37
|
+
}
|
|
38
|
+
log(level, msg, args) {
|
|
39
|
+
if (!this.shouldLog(level))
|
|
40
|
+
return;
|
|
41
|
+
const formatted = this.format(level, msg, args);
|
|
42
|
+
if (level === 'fatal' || level === 'error') {
|
|
43
|
+
console.error(formatted);
|
|
44
|
+
}
|
|
45
|
+
else if (level === 'warn') {
|
|
46
|
+
console.warn(formatted);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
console.log(formatted);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
fatal(msg, ...args) { this.log('fatal', msg, args); }
|
|
53
|
+
error(msg, ...args) { this.log('error', msg, args); }
|
|
54
|
+
warn(msg, ...args) { this.log('warn', msg, args); }
|
|
55
|
+
info(msg, ...args) { this.log('info', msg, args); }
|
|
56
|
+
debug(msg, ...args) { this.log('debug', msg, args); }
|
|
57
|
+
trace(msg, ...args) { this.log('trace', msg, args); }
|
|
58
|
+
}
|
|
59
|
+
exports.DefaultLogger = DefaultLogger;
|
|
60
|
+
/**
|
|
61
|
+
* Default logger instance (singleton, RAM-friendly)
|
|
62
|
+
*/
|
|
63
|
+
exports.defaultLogger = new DefaultLogger(process.env.WALIWA_LOG_LEVEL || 'warn');
|
|
64
|
+
/**
|
|
65
|
+
* Silent logger - untuk testing atau production mode tanpa logs
|
|
66
|
+
*/
|
|
67
|
+
class SilentLogger {
|
|
68
|
+
level = 'silent';
|
|
69
|
+
child() { return this; }
|
|
70
|
+
fatal() { }
|
|
71
|
+
error() { }
|
|
72
|
+
warn() { }
|
|
73
|
+
info() { }
|
|
74
|
+
debug() { }
|
|
75
|
+
trace() { }
|
|
76
|
+
}
|
|
77
|
+
exports.SilentLogger = SilentLogger;
|
|
78
|
+
exports.silentLogger = new SilentLogger();
|
|
79
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Waliwa - Retry & throttle utilities
|
|
3
|
+
* Implementasi efficient untuk retry exponential backoff dan rate limiting
|
|
4
|
+
*/
|
|
5
|
+
export interface RetryOptions {
|
|
6
|
+
retries?: number;
|
|
7
|
+
minTimeout?: number;
|
|
8
|
+
maxTimeout?: number;
|
|
9
|
+
factor?: number;
|
|
10
|
+
randomize?: boolean;
|
|
11
|
+
onFailedAttempt?: (error: Error, attempt: number) => void;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Exponential backoff retry dengan jitter
|
|
15
|
+
*/
|
|
16
|
+
export declare function retry<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T>;
|
|
17
|
+
export declare function sleep(ms: number): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Token bucket rate limiter - RAM-efficient (single object per limiter)
|
|
20
|
+
*/
|
|
21
|
+
export declare class RateLimiter {
|
|
22
|
+
private tokens;
|
|
23
|
+
private lastRefill;
|
|
24
|
+
private readonly maxTokens;
|
|
25
|
+
private readonly refillRate;
|
|
26
|
+
private readonly queue;
|
|
27
|
+
private processing;
|
|
28
|
+
constructor(maxTokensPerSecond: number);
|
|
29
|
+
private refill;
|
|
30
|
+
acquire(): Promise<void>;
|
|
31
|
+
private processQueue;
|
|
32
|
+
/** Destroy limiter dan reject semua queued requests */
|
|
33
|
+
destroy(): void;
|
|
34
|
+
}
|
|
35
|
+
export declare function debounce<T extends (...args: any[]) => void>(fn: T, wait: number): (...args: Parameters<T>) => void;
|
|
36
|
+
export declare function throttle<T extends (...args: any[]) => void>(fn: T, wait: number): (...args: Parameters<T>) => void;
|
|
37
|
+
export declare class PromiseQueue {
|
|
38
|
+
private queue;
|
|
39
|
+
private running;
|
|
40
|
+
add<T>(fn: () => Promise<T>): Promise<T>;
|
|
41
|
+
private process;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/utils/retry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3D;AAED;;GAEG;AACH,wBAAsB,KAAK,CAAC,CAAC,EAC3B,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,CAAC,CAAC,CAoCZ;AAED,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAID;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoE;IAC1F,OAAO,CAAC,UAAU,CAAkB;gBAExB,kBAAkB,EAAE,MAAM;IAOtC,OAAO,CAAC,MAAM;IAOR,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAa9B,OAAO,CAAC,YAAY;IAmBpB,uDAAuD;IACvD,OAAO,IAAI,IAAI;CAMhB;AAID,wBAAgB,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,EACzD,EAAE,EAAE,CAAC,EACL,IAAI,EAAE,MAAM,GACX,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI,CAMlC;AAID,wBAAgB,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,EACzD,EAAE,EAAE,CAAC,EACL,IAAI,EAAE,MAAM,GACX,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI,CAqBlC;AAID,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAkC;IAC/C,OAAO,CAAC,OAAO,CAAkB;IAE3B,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;YAchC,OAAO;CAStB"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Waliwa - Retry & throttle utilities
|
|
4
|
+
* Implementasi efficient untuk retry exponential backoff dan rate limiting
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.PromiseQueue = exports.RateLimiter = void 0;
|
|
8
|
+
exports.retry = retry;
|
|
9
|
+
exports.sleep = sleep;
|
|
10
|
+
exports.debounce = debounce;
|
|
11
|
+
exports.throttle = throttle;
|
|
12
|
+
const crypto_js_1 = require("../core/crypto.js");
|
|
13
|
+
/**
|
|
14
|
+
* Exponential backoff retry dengan jitter
|
|
15
|
+
*/
|
|
16
|
+
async function retry(fn, options = {}) {
|
|
17
|
+
const { retries = 5, minTimeout = 500, maxTimeout = 30000, factor = 2, randomize = true, onFailedAttempt } = options;
|
|
18
|
+
let attempt = 0;
|
|
19
|
+
let lastError;
|
|
20
|
+
while (attempt <= retries) {
|
|
21
|
+
try {
|
|
22
|
+
return await fn();
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
lastError = err;
|
|
26
|
+
attempt++;
|
|
27
|
+
if (attempt > retries) {
|
|
28
|
+
throw lastError;
|
|
29
|
+
}
|
|
30
|
+
if (onFailedAttempt) {
|
|
31
|
+
onFailedAttempt(lastError, attempt);
|
|
32
|
+
}
|
|
33
|
+
// Exponential backoff dengan jitter
|
|
34
|
+
let delay = minTimeout * Math.pow(factor, attempt - 1);
|
|
35
|
+
if (randomize) {
|
|
36
|
+
const jitter = ((0, crypto_js_1.getRandomBytes)(1)[0] / 255) * 0.3;
|
|
37
|
+
delay = delay * (1 + jitter);
|
|
38
|
+
}
|
|
39
|
+
delay = Math.min(delay, maxTimeout);
|
|
40
|
+
await sleep(delay);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
throw lastError;
|
|
44
|
+
}
|
|
45
|
+
function sleep(ms) {
|
|
46
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
47
|
+
}
|
|
48
|
+
// ============== Throttle / Rate Limiter ==============
|
|
49
|
+
/**
|
|
50
|
+
* Token bucket rate limiter - RAM-efficient (single object per limiter)
|
|
51
|
+
*/
|
|
52
|
+
class RateLimiter {
|
|
53
|
+
tokens;
|
|
54
|
+
lastRefill;
|
|
55
|
+
maxTokens;
|
|
56
|
+
refillRate; // tokens per ms
|
|
57
|
+
queue = [];
|
|
58
|
+
processing = false;
|
|
59
|
+
constructor(maxTokensPerSecond) {
|
|
60
|
+
this.maxTokens = maxTokensPerSecond;
|
|
61
|
+
this.tokens = maxTokensPerSecond;
|
|
62
|
+
this.refillRate = maxTokensPerSecond / 1000;
|
|
63
|
+
this.lastRefill = Date.now();
|
|
64
|
+
}
|
|
65
|
+
refill() {
|
|
66
|
+
const now = Date.now();
|
|
67
|
+
const elapsed = now - this.lastRefill;
|
|
68
|
+
this.tokens = Math.min(this.maxTokens, this.tokens + elapsed * this.refillRate);
|
|
69
|
+
this.lastRefill = now;
|
|
70
|
+
}
|
|
71
|
+
async acquire() {
|
|
72
|
+
this.refill();
|
|
73
|
+
if (this.tokens >= 1) {
|
|
74
|
+
this.tokens -= 1;
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
// Queue
|
|
78
|
+
return new Promise((resolve, reject) => {
|
|
79
|
+
this.queue.push({ resolve, reject });
|
|
80
|
+
this.processQueue();
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
processQueue() {
|
|
84
|
+
if (this.processing)
|
|
85
|
+
return;
|
|
86
|
+
this.processing = true;
|
|
87
|
+
const tick = () => {
|
|
88
|
+
this.refill();
|
|
89
|
+
while (this.queue.length > 0 && this.tokens >= 1) {
|
|
90
|
+
this.tokens -= 1;
|
|
91
|
+
const item = this.queue.shift();
|
|
92
|
+
item.resolve();
|
|
93
|
+
}
|
|
94
|
+
if (this.queue.length > 0) {
|
|
95
|
+
setTimeout(tick, 50);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
this.processing = false;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
tick();
|
|
102
|
+
}
|
|
103
|
+
/** Destroy limiter dan reject semua queued requests */
|
|
104
|
+
destroy() {
|
|
105
|
+
while (this.queue.length > 0) {
|
|
106
|
+
const item = this.queue.shift();
|
|
107
|
+
item.reject(new Error('Rate limiter destroyed'));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
exports.RateLimiter = RateLimiter;
|
|
112
|
+
// ============== Debounce ==============
|
|
113
|
+
function debounce(fn, wait) {
|
|
114
|
+
let timeout = null;
|
|
115
|
+
return (...args) => {
|
|
116
|
+
if (timeout)
|
|
117
|
+
clearTimeout(timeout);
|
|
118
|
+
timeout = setTimeout(() => fn(...args), wait);
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
// ============== Throttle (leading edge) ==============
|
|
122
|
+
function throttle(fn, wait) {
|
|
123
|
+
let lastCall = 0;
|
|
124
|
+
let timeout = null;
|
|
125
|
+
return (...args) => {
|
|
126
|
+
const now = Date.now();
|
|
127
|
+
const remaining = wait - (now - lastCall);
|
|
128
|
+
if (remaining <= 0) {
|
|
129
|
+
if (timeout) {
|
|
130
|
+
clearTimeout(timeout);
|
|
131
|
+
timeout = null;
|
|
132
|
+
}
|
|
133
|
+
lastCall = now;
|
|
134
|
+
fn(...args);
|
|
135
|
+
}
|
|
136
|
+
else if (!timeout) {
|
|
137
|
+
timeout = setTimeout(() => {
|
|
138
|
+
lastCall = Date.now();
|
|
139
|
+
timeout = null;
|
|
140
|
+
fn(...args);
|
|
141
|
+
}, remaining);
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
// ============== Promise Queue (sequential execution) ==============
|
|
146
|
+
class PromiseQueue {
|
|
147
|
+
queue = [];
|
|
148
|
+
running = false;
|
|
149
|
+
async add(fn) {
|
|
150
|
+
return new Promise((resolve, reject) => {
|
|
151
|
+
this.queue.push(async () => {
|
|
152
|
+
try {
|
|
153
|
+
const result = await fn();
|
|
154
|
+
resolve(result);
|
|
155
|
+
}
|
|
156
|
+
catch (err) {
|
|
157
|
+
reject(err);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
this.process();
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
async process() {
|
|
164
|
+
if (this.running)
|
|
165
|
+
return;
|
|
166
|
+
this.running = true;
|
|
167
|
+
while (this.queue.length > 0) {
|
|
168
|
+
const task = this.queue.shift();
|
|
169
|
+
await task();
|
|
170
|
+
}
|
|
171
|
+
this.running = false;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
exports.PromiseQueue = PromiseQueue;
|
|
175
|
+
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/utils/retry.ts"],"names":[],"mappings":"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"}
|