zapo-js 1.2.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/WaClient.d.ts +84 -49
- package/dist/client/WaClient.js +70 -50
- package/dist/client/WaClientFactory.d.ts +7 -0
- package/dist/client/WaClientFactory.js +1 -0
- package/dist/client/plugins/define.d.ts +23 -0
- package/dist/client/plugins/define.js +22 -0
- package/dist/client/plugins/index.d.ts +4 -0
- package/dist/client/plugins/index.js +9 -0
- package/dist/client/plugins/install.d.ts +18 -0
- package/dist/client/plugins/install.js +83 -0
- package/dist/client/plugins/types.d.ts +76 -0
- package/dist/client/plugins/types.js +6 -0
- package/dist/client/types.d.ts +6 -0
- package/dist/esm/client/WaClient.js +70 -49
- package/dist/esm/client/WaClientFactory.js +1 -0
- package/dist/esm/client/plugins/define.js +19 -0
- package/dist/esm/client/plugins/index.js +3 -0
- package/dist/esm/client/plugins/install.js +80 -0
- package/dist/esm/client/plugins/types.js +3 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/infra/log/ConsoleLogger.js +3 -9
- package/dist/esm/infra/log/PinoLogger.js +24 -12
- package/dist/esm/infra/log/types.js +8 -1
- package/dist/esm/transport/index.js +2 -0
- package/dist/esm/util/index.js +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +7 -2
- package/dist/infra/log/ConsoleLogger.d.ts +4 -2
- package/dist/infra/log/ConsoleLogger.js +5 -11
- package/dist/infra/log/PinoLogger.d.ts +4 -2
- package/dist/infra/log/PinoLogger.js +24 -12
- package/dist/infra/log/types.d.ts +8 -1
- package/dist/infra/log/types.js +9 -1
- package/dist/transport/index.d.ts +3 -0
- package/dist/transport/index.js +11 -1
- package/dist/util/index.d.ts +1 -1
- package/dist/util/index.js +4 -1
- package/package.json +1 -1
|
@@ -3,6 +3,7 @@ import { createIgnoreKeyFilter, validateIgnoreKey } from './messaging/ignore-key
|
|
|
3
3
|
import { runHistorySyncNotification } from './persistence/history-sync.js';
|
|
4
4
|
import { persistIncomingMailboxEntities } from './persistence/mailbox.js';
|
|
5
5
|
import { WriteBehindPersistence } from './persistence/WriteBehindPersistence.js';
|
|
6
|
+
import { installWaClientPlugins } from './plugins/install.js';
|
|
6
7
|
import { buildWaClientDependencies, resolveWaClientBase } from './WaClientFactory.js';
|
|
7
8
|
import { ConsoleLogger } from '../infra/log/ConsoleLogger.js';
|
|
8
9
|
import { proto } from '../proto.js';
|
|
@@ -19,55 +20,8 @@ const SYNC_RELATED_PROTOCOL_TYPES = new Set([
|
|
|
19
20
|
proto.Message.ProtocolMessage.Type.PEER_DATA_OPERATION_REQUEST_MESSAGE,
|
|
20
21
|
proto.Message.ProtocolMessage.Type.PEER_DATA_OPERATION_REQUEST_RESPONSE_MESSAGE
|
|
21
22
|
]);
|
|
22
|
-
/**
|
|
23
|
-
|
|
24
|
-
* coordinators (accessible via getters such as {@link message}, {@link group},
|
|
25
|
-
* {@link newsletter}, etc.) and re-emits every {@link WaClientEventMap} event.
|
|
26
|
-
*
|
|
27
|
-
* Lifecycle: construct with {@link WaClientOptions}, call {@link connect} to
|
|
28
|
-
* open the socket, react to `connection`/`auth_qr`/`auth_pairing_code` events,
|
|
29
|
-
* then use the coordinator getters to drive the session. Call {@link disconnect}
|
|
30
|
-
* to shut down cleanly or {@link logout} to remove the companion device.
|
|
31
|
-
*
|
|
32
|
-
* @example
|
|
33
|
-
* ```ts
|
|
34
|
-
* import { createPinoLogger, createStore, WaClient } from '..'
|
|
35
|
-
* import { createSqliteStore } from '@zapo-js/store-sqlite'
|
|
36
|
-
*
|
|
37
|
-
* const store = createStore({
|
|
38
|
-
* backends: { sqlite: createSqliteStore({ path: '.auth/state.sqlite' }) },
|
|
39
|
-
* providers: {
|
|
40
|
-
* auth: 'sqlite',
|
|
41
|
-
* signal: 'sqlite',
|
|
42
|
-
* preKey: 'sqlite',
|
|
43
|
-
* session: 'sqlite',
|
|
44
|
-
* identity: 'sqlite',
|
|
45
|
-
* senderKey: 'sqlite',
|
|
46
|
-
* appState: 'sqlite',
|
|
47
|
-
* privacyToken: 'sqlite',
|
|
48
|
-
* messages: 'sqlite',
|
|
49
|
-
* threads: 'sqlite',
|
|
50
|
-
* contacts: 'sqlite'
|
|
51
|
-
* }
|
|
52
|
-
* })
|
|
53
|
-
*
|
|
54
|
-
* const client = new WaClient(
|
|
55
|
-
* { store, sessionId: 'default' },
|
|
56
|
-
* await createPinoLogger({ level: 'info', pretty: true })
|
|
57
|
-
* )
|
|
58
|
-
*
|
|
59
|
-
* client.on('auth_qr', ({ qr, ttlMs }) => console.log('scan:', qr, ttlMs))
|
|
60
|
-
* client.on('connection', (event) => console.log('connection', event))
|
|
61
|
-
* client.on('message', async (event) => {
|
|
62
|
-
* if (event.message?.conversation === 'ping') {
|
|
63
|
-
* await client.message.send(event.chatJid!, 'pong')
|
|
64
|
-
* }
|
|
65
|
-
* })
|
|
66
|
-
*
|
|
67
|
-
* await client.connect()
|
|
68
|
-
* ```
|
|
69
|
-
*/
|
|
70
|
-
export class WaClient extends EventEmitter {
|
|
23
|
+
/** @internal Implementation backing the exported {@link WaClient}. */
|
|
24
|
+
class WaClientImpl extends EventEmitter {
|
|
71
25
|
/**
|
|
72
26
|
* @param options Client configuration (store, transport, addons, history...).
|
|
73
27
|
* @param logger Optional structured logger. Defaults to a `ConsoleLogger('info')`.
|
|
@@ -78,6 +32,7 @@ export class WaClient extends EventEmitter {
|
|
|
78
32
|
this.acceptingIncomingEvents = true;
|
|
79
33
|
this.activeIncomingHandlers = 0;
|
|
80
34
|
this.incomingHandlersDrainedWaiters = [];
|
|
35
|
+
this.disposePlugins = null;
|
|
81
36
|
const base = resolveWaClientBase(options, logger);
|
|
82
37
|
this.options = base.options;
|
|
83
38
|
this.logger = base.logger;
|
|
@@ -115,6 +70,13 @@ export class WaClient extends EventEmitter {
|
|
|
115
70
|
this.deps = dependencies;
|
|
116
71
|
this.appStateSync = dependencies.appStateSync;
|
|
117
72
|
this.mediaTransfer = dependencies.mediaTransfer;
|
|
73
|
+
this.disposePlugins = installWaClientPlugins(this, {
|
|
74
|
+
options: this.options,
|
|
75
|
+
logger: this.logger,
|
|
76
|
+
stores: this.stores,
|
|
77
|
+
deps: this.deps,
|
|
78
|
+
queryWithContext: this.queryWithContext.bind(this)
|
|
79
|
+
}, this.options.plugins ?? []);
|
|
118
80
|
this.bindNodeTransportEvents();
|
|
119
81
|
this.on('connection', (event) => {
|
|
120
82
|
if (event.status !== 'close')
|
|
@@ -381,6 +343,11 @@ export class WaClient extends EventEmitter {
|
|
|
381
343
|
remaining: writeBehindFlush.remaining
|
|
382
344
|
});
|
|
383
345
|
}
|
|
346
|
+
if (this.disposePlugins) {
|
|
347
|
+
const dispose = this.disposePlugins;
|
|
348
|
+
this.disposePlugins = null;
|
|
349
|
+
await dispose();
|
|
350
|
+
}
|
|
384
351
|
await this.deps.connectionManager.disconnect();
|
|
385
352
|
this.emit('connection', {
|
|
386
353
|
status: 'close',
|
|
@@ -603,3 +570,57 @@ export class WaClient extends EventEmitter {
|
|
|
603
570
|
this.emit('debug_client_error', { error });
|
|
604
571
|
}
|
|
605
572
|
}
|
|
573
|
+
/**
|
|
574
|
+
* Top-level WhatsApp client. Owns the transport, auth, signal, and per-feature
|
|
575
|
+
* coordinators (accessible via getters such as {@link message}, {@link group},
|
|
576
|
+
* {@link newsletter}, etc.) and re-emits every {@link WaClientEventMap} event.
|
|
577
|
+
*
|
|
578
|
+
* Lifecycle: construct with {@link WaClientOptions}, call {@link connect} to
|
|
579
|
+
* open the socket, react to `connection`/`auth_qr`/`auth_pairing_code` events,
|
|
580
|
+
* then use the coordinator getters to drive the session. Call {@link disconnect}
|
|
581
|
+
* to shut down cleanly or {@link logout} to remove the companion device.
|
|
582
|
+
*
|
|
583
|
+
* Pass `plugins` to expose plugin getters and events on the returned client,
|
|
584
|
+
* typed from the values you pass: e.g. `plugins: [voipPlugin()]` adds
|
|
585
|
+
* `client.voip` and the `voip_*` events, and only then. See
|
|
586
|
+
* {@link WaClientConstructor}.
|
|
587
|
+
*
|
|
588
|
+
* @example
|
|
589
|
+
* ```ts
|
|
590
|
+
* import { createPinoLogger, createStore, WaClient } from '..'
|
|
591
|
+
* import { createSqliteStore } from '@zapo-js/store-sqlite'
|
|
592
|
+
*
|
|
593
|
+
* const store = createStore({
|
|
594
|
+
* backends: { sqlite: createSqliteStore({ path: '.auth/state.sqlite' }) },
|
|
595
|
+
* providers: {
|
|
596
|
+
* auth: 'sqlite',
|
|
597
|
+
* signal: 'sqlite',
|
|
598
|
+
* preKey: 'sqlite',
|
|
599
|
+
* session: 'sqlite',
|
|
600
|
+
* identity: 'sqlite',
|
|
601
|
+
* senderKey: 'sqlite',
|
|
602
|
+
* appState: 'sqlite',
|
|
603
|
+
* privacyToken: 'sqlite',
|
|
604
|
+
* messages: 'sqlite',
|
|
605
|
+
* threads: 'sqlite',
|
|
606
|
+
* contacts: 'sqlite'
|
|
607
|
+
* }
|
|
608
|
+
* })
|
|
609
|
+
*
|
|
610
|
+
* const client = new WaClient(
|
|
611
|
+
* { store, sessionId: 'default' },
|
|
612
|
+
* await createPinoLogger({ level: 'info', pretty: true })
|
|
613
|
+
* )
|
|
614
|
+
*
|
|
615
|
+
* client.on('auth_qr', ({ qr, ttlMs }) => console.log('scan:', qr, ttlMs))
|
|
616
|
+
* client.on('connection', (event) => console.log('connection', event))
|
|
617
|
+
* client.on('message', async (event) => {
|
|
618
|
+
* if (event.message?.conversation === 'ping') {
|
|
619
|
+
* await client.message.send(event.chatJid!, 'pong')
|
|
620
|
+
* }
|
|
621
|
+
* })
|
|
622
|
+
*
|
|
623
|
+
* await client.connect()
|
|
624
|
+
* ```
|
|
625
|
+
*/
|
|
626
|
+
export const WaClient = WaClientImpl;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export function defineWaClientPlugin(input) {
|
|
2
|
+
if ('exposeAs' in input && input.exposeAs !== undefined) {
|
|
3
|
+
const exposeInput = input;
|
|
4
|
+
return {
|
|
5
|
+
id: exposeInput.id,
|
|
6
|
+
exposeAs: exposeInput.exposeAs,
|
|
7
|
+
setup: exposeInput.setup,
|
|
8
|
+
dispose: exposeInput.dispose
|
|
9
|
+
? (instance, ctx) => exposeInput.dispose(instance, ctx)
|
|
10
|
+
: undefined
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
const behaviorInput = input;
|
|
14
|
+
return {
|
|
15
|
+
id: behaviorInput.id,
|
|
16
|
+
setup: behaviorInput.setup,
|
|
17
|
+
dispose: behaviorInput.dispose ? (_instance, ctx) => behaviorInput.dispose(ctx) : undefined
|
|
18
|
+
};
|
|
19
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { isWaClientExposePluginDefinition } from '../plugins/types.js';
|
|
2
|
+
import { toError } from '../../util/primitives.js';
|
|
3
|
+
/**
|
|
4
|
+
* Installs {@link WaClientOptions.plugins} on `client`. Returns a dispose
|
|
5
|
+
* function invoked by {@link WaClient.disconnect}.
|
|
6
|
+
*/
|
|
7
|
+
export function installWaClientPlugins(client, input, plugins) {
|
|
8
|
+
const seenIds = new Set();
|
|
9
|
+
const seenExposeAs = new Set();
|
|
10
|
+
const disposeCallbacks = [];
|
|
11
|
+
const registerDispose = (fn) => {
|
|
12
|
+
disposeCallbacks[disposeCallbacks.length] = fn;
|
|
13
|
+
};
|
|
14
|
+
const baseCtx = {
|
|
15
|
+
client,
|
|
16
|
+
options: input.options,
|
|
17
|
+
logger: input.logger,
|
|
18
|
+
stores: input.stores,
|
|
19
|
+
deps: input.deps,
|
|
20
|
+
emit: client.emit.bind(client),
|
|
21
|
+
on: client.on.bind(client),
|
|
22
|
+
off: client.off.bind(client),
|
|
23
|
+
once: client.once.bind(client),
|
|
24
|
+
queryWithContext: input.queryWithContext,
|
|
25
|
+
registerIncomingHandler: (registration) => input.deps.lowLevelCoordinator.registerIncomingHandler(registration),
|
|
26
|
+
registerIncomingStanzaFilter: (filter) => input.deps.lowLevelCoordinator.registerIncomingStanzaFilter(filter),
|
|
27
|
+
registerDispose
|
|
28
|
+
};
|
|
29
|
+
for (let index = 0; index < plugins.length; index += 1) {
|
|
30
|
+
const plugin = plugins[index];
|
|
31
|
+
if (seenIds.has(plugin.id)) {
|
|
32
|
+
throw new Error(`duplicate wa client plugin id: ${plugin.id}`);
|
|
33
|
+
}
|
|
34
|
+
seenIds.add(plugin.id);
|
|
35
|
+
const pluginCtx = {
|
|
36
|
+
...baseCtx,
|
|
37
|
+
logger: input.logger.child({ plugin: plugin.id })
|
|
38
|
+
};
|
|
39
|
+
if (isWaClientExposePluginDefinition(plugin)) {
|
|
40
|
+
if (seenExposeAs.has(plugin.exposeAs)) {
|
|
41
|
+
throw new Error(`duplicate wa client plugin exposeAs: ${plugin.exposeAs}`);
|
|
42
|
+
}
|
|
43
|
+
seenExposeAs.add(plugin.exposeAs);
|
|
44
|
+
if (plugin.exposeAs in client) {
|
|
45
|
+
throw new Error(`wa client plugin exposeAs "${plugin.exposeAs}" collides with a reserved client member`);
|
|
46
|
+
}
|
|
47
|
+
const instance = plugin.setup(pluginCtx);
|
|
48
|
+
Object.defineProperty(client, plugin.exposeAs, {
|
|
49
|
+
get: () => instance,
|
|
50
|
+
enumerable: true,
|
|
51
|
+
configurable: false
|
|
52
|
+
});
|
|
53
|
+
if (plugin.dispose) {
|
|
54
|
+
const dispose = plugin.dispose;
|
|
55
|
+
registerDispose(() => dispose(instance, pluginCtx));
|
|
56
|
+
}
|
|
57
|
+
pluginCtx.logger.debug('wa client plugin installed', { exposeAs: plugin.exposeAs });
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
plugin.setup(pluginCtx);
|
|
61
|
+
if (plugin.dispose) {
|
|
62
|
+
const dispose = plugin.dispose;
|
|
63
|
+
registerDispose(() => dispose(undefined, pluginCtx));
|
|
64
|
+
}
|
|
65
|
+
pluginCtx.logger.debug('wa client plugin installed');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return async () => {
|
|
69
|
+
for (let index = disposeCallbacks.length - 1; index >= 0; index -= 1) {
|
|
70
|
+
try {
|
|
71
|
+
await disposeCallbacks[index]();
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
input.logger.warn('wa client plugin dispose failed', {
|
|
75
|
+
message: toError(error).message
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}
|
package/dist/esm/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
export { WaClient } from './client/index.js';
|
|
2
|
+
export { defineWaClientPlugin } from './client/plugins/index.js';
|
|
2
3
|
export { downloadMediaMessage } from './client/media.js';
|
|
3
4
|
export { parseUsyncResultEnvelope } from './transport/node/builders/usync.js';
|
|
4
5
|
export { getContentType, resolveMessageTarget } from './message/encode/content.js';
|
|
5
6
|
export { resolveMediaPayload } from './message/encode/media-payload.js';
|
|
7
|
+
export { unpadPkcs7, writeRandomPadMax16 } from './message/encode/padding.js';
|
|
6
8
|
export { fetchLatestWaWebVersion } from './transport/wa-web-version-fetcher.js';
|
|
7
9
|
export { ConsoleLogger } from './infra/log/ConsoleLogger.js';
|
|
8
10
|
export { PinoLogger, createPinoLogger } from './infra/log/PinoLogger.js';
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
trace: 10,
|
|
3
|
-
debug: 20,
|
|
4
|
-
info: 30,
|
|
5
|
-
warn: 40,
|
|
6
|
-
error: 50
|
|
7
|
-
};
|
|
1
|
+
import { LOG_LEVEL_PRIORITY } from '../log/types.js';
|
|
8
2
|
const CONSOLE_WRITERS = {
|
|
9
3
|
trace: (...args) => console.debug(...args),
|
|
10
4
|
debug: (...args) => console.debug(...args),
|
|
@@ -48,9 +42,9 @@ export class ConsoleLogger {
|
|
|
48
42
|
* Returns a derived logger with `bindings` merged into the parent's
|
|
49
43
|
* bindings. Per-call context still wins on key conflicts.
|
|
50
44
|
*/
|
|
51
|
-
child(bindings) {
|
|
45
|
+
child(bindings, options) {
|
|
52
46
|
const merged = this.bindings ? { ...this.bindings, ...bindings } : { ...bindings };
|
|
53
|
-
return new ConsoleLogger(this.level, merged);
|
|
47
|
+
return new ConsoleLogger(options?.level ?? this.level, merged);
|
|
54
48
|
}
|
|
55
49
|
write(level, message, context) {
|
|
56
50
|
if (LOG_LEVEL_PRIORITY[level] < this.minLevelPriority) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { LOG_LEVEL_PRIORITY } from '../log/types.js';
|
|
1
2
|
const PINO_MODULE = 'pino';
|
|
2
3
|
const PINO_PRETTY_MODULE = 'pino-pretty';
|
|
3
4
|
async function loadPinoFactory() {
|
|
@@ -57,11 +58,11 @@ export class PinoLogger {
|
|
|
57
58
|
* call's context. Delegates to the underlying pino `child()` when
|
|
58
59
|
* available; otherwise wraps with a parent + bindings merge.
|
|
59
60
|
*/
|
|
60
|
-
child(bindings) {
|
|
61
|
+
child(bindings, options) {
|
|
61
62
|
if (typeof this.logger.child === 'function') {
|
|
62
|
-
return new PinoLogger(this.logger.child(bindings), this.level);
|
|
63
|
+
return new PinoLogger(this.logger.child(bindings), options?.level ?? this.level);
|
|
63
64
|
}
|
|
64
|
-
return new BoundLogger(this, bindings);
|
|
65
|
+
return new BoundLogger(this, bindings, options?.level);
|
|
65
66
|
}
|
|
66
67
|
write(level, message, context) {
|
|
67
68
|
if (context === null || context === undefined) {
|
|
@@ -83,28 +84,39 @@ export class PinoLogger {
|
|
|
83
84
|
* underlying logger does not support `child()` natively.
|
|
84
85
|
*/
|
|
85
86
|
class BoundLogger {
|
|
86
|
-
constructor(parent, bindings) {
|
|
87
|
+
constructor(parent, bindings, level) {
|
|
87
88
|
this.parent = parent;
|
|
88
|
-
this.level = parent.level;
|
|
89
|
+
this.level = level ?? parent.level;
|
|
89
90
|
this.bindings = bindings;
|
|
91
|
+
this.minPriority = LOG_LEVEL_PRIORITY[this.level];
|
|
90
92
|
}
|
|
91
93
|
trace(message, context) {
|
|
92
|
-
|
|
94
|
+
if (LOG_LEVEL_PRIORITY.trace >= this.minPriority) {
|
|
95
|
+
this.parent.trace(message, this.merge(context));
|
|
96
|
+
}
|
|
93
97
|
}
|
|
94
98
|
debug(message, context) {
|
|
95
|
-
|
|
99
|
+
if (LOG_LEVEL_PRIORITY.debug >= this.minPriority) {
|
|
100
|
+
this.parent.debug(message, this.merge(context));
|
|
101
|
+
}
|
|
96
102
|
}
|
|
97
103
|
info(message, context) {
|
|
98
|
-
|
|
104
|
+
if (LOG_LEVEL_PRIORITY.info >= this.minPriority) {
|
|
105
|
+
this.parent.info(message, this.merge(context));
|
|
106
|
+
}
|
|
99
107
|
}
|
|
100
108
|
warn(message, context) {
|
|
101
|
-
|
|
109
|
+
if (LOG_LEVEL_PRIORITY.warn >= this.minPriority) {
|
|
110
|
+
this.parent.warn(message, this.merge(context));
|
|
111
|
+
}
|
|
102
112
|
}
|
|
103
113
|
error(message, context) {
|
|
104
|
-
|
|
114
|
+
if (LOG_LEVEL_PRIORITY.error >= this.minPriority) {
|
|
115
|
+
this.parent.error(message, this.merge(context));
|
|
116
|
+
}
|
|
105
117
|
}
|
|
106
|
-
child(bindings) {
|
|
107
|
-
return new BoundLogger(this.parent, { ...this.bindings, ...bindings });
|
|
118
|
+
child(bindings, options) {
|
|
119
|
+
return new BoundLogger(this.parent, { ...this.bindings, ...bindings }, options?.level ?? this.level);
|
|
108
120
|
}
|
|
109
121
|
merge(context) {
|
|
110
122
|
return context ? { ...this.bindings, ...context } : this.bindings;
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
export const LOG_LEVEL_PRIORITY = {
|
|
2
|
+
trace: 10,
|
|
3
|
+
debug: 20,
|
|
4
|
+
info: 30,
|
|
5
|
+
warn: 40,
|
|
6
|
+
error: 50
|
|
7
|
+
};
|
|
1
8
|
function noop() { }
|
|
2
9
|
export function createNoopLogger(level = 'trace') {
|
|
3
10
|
const logger = {
|
|
@@ -7,7 +14,7 @@ export function createNoopLogger(level = 'trace') {
|
|
|
7
14
|
info: noop,
|
|
8
15
|
warn: noop,
|
|
9
16
|
error: noop,
|
|
10
|
-
child: () => logger
|
|
17
|
+
child: (_bindings, options) => (options?.level ? createNoopLogger(options.level) : logger)
|
|
11
18
|
};
|
|
12
19
|
return logger;
|
|
13
20
|
}
|
|
@@ -12,3 +12,5 @@ export { WaNodeTransport } from './node/WaNodeTransport.js';
|
|
|
12
12
|
export { WaMobileTcpSocket, WaMobileTcpSocketCtor } from './node/WaMobileTcpSocket.js';
|
|
13
13
|
export { buildMobileLoginPayload } from './noise/WaMobileClientPayload.js';
|
|
14
14
|
export { assertIqResult, buildIqNode, parseIqError, queryWithContext } from './node/query.js';
|
|
15
|
+
export { buildAckNode, buildReceiptNode } from './node/builders/global.js';
|
|
16
|
+
export { findNodeChild, getFirstNodeChild, getNodeChildren, getNodeChildrenByTag, getNodeTextContent, hasNodeChild } from './node/helpers.js';
|
package/dist/esm/util/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { base64ToBytes, bytesToBase64, bytesToBase64UrlSafe, bytesToHex, decodeBase64Url, hexToBytes, TEXT_DECODER, toBytesView, uint8Equal, uint8TimingSafeEqual } from './bytes.js';
|
|
1
|
+
export { base64ToBytes, bytesToBase64, bytesToBase64UrlSafe, bytesToHex, concatBytes, decodeBase64Url, EMPTY_BYTES, hexToBytes, TEXT_DECODER, TEXT_ENCODER, toBytesView, uint8Equal, uint8TimingSafeEqual } from './bytes.js';
|
|
2
2
|
export { asBytes, asNumber, asOptionalBytes, asOptionalNumber, asOptionalString, asString, resolvePositive, toBoolOrUndef } from './coercion.js';
|
|
3
3
|
export { normalizeQueryLimit } from './collections.js';
|
|
4
4
|
export { toError, toSafeNumber } from './primitives.js';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export { WaClient } from './client';
|
|
2
|
+
export { defineWaClientPlugin } from './client/plugins';
|
|
3
|
+
export type { WaClientDependencies } from './client/WaClientFactory';
|
|
2
4
|
export type { WaClientEventMap, WaClientOptions, WaClientProxyOptions, WaDownloadMediaOptions, WaHistorySyncChunkEvent, WaHistorySyncOptions, WaWriteBehindOptions } from './client/types';
|
|
5
|
+
export type { WaClientPluginContext, WaClientPluginDefinition } from './client/plugins';
|
|
3
6
|
export type { WaMessageCoordinator } from './client/coordinators/WaMessageCoordinator';
|
|
4
7
|
export type { WaAccountTakeoverNoticeEvent, WaAppStateMutationEvent, WaAppStateMutationSource, WaBusinessEvent, WaBusinessEventAction, WaBusinessProfileResult, WaConnectionEvent, WaGroupEvent, WaGroupEventAction, WaGroupEventLinkedGroup, WaGroupEventMembershipRequest, WaGroupEventParticipant, WaGroupEventSubgroupSuggestion, WaIgnoreKey, WaIgnoreKeyContext, WaIgnoreKeyPredicate, WaIgnoreStanzaKind, WaIncomingAddonEvent, WaIncomingBaseEvent, WaIncomingBotChunkEvent, WaIncomingCallEvent, WaIncomingChatstateEvent, WaIncomingErrorStanzaEvent, WaIncomingFailureEvent, WaIncomingMessageEvent, WaIncomingMessageKey, WaIncomingNewsletterEvent, WaIncomingNewsletterMessageUpdateEvent, WaIncomingNodeHandler, WaIncomingNodeHandlerRegistration, WaIncomingNotificationEvent, WaIncomingPresenceEvent, WaIncomingProtocolMessageEvent, WaIncomingReceiptEvent, WaIncomingStanzaFilter, WaIncomingUnavailableMessageEvent, WaIncomingUnhandledStanzaEvent, WaMexLidChangeEvent, WaMexMessageCappingEvent, WaMexMessageCappingStatus, WaMexNotificationEvent, WaMexNotificationGraphQlError, WaMexNotificationOperationName, WaMexNotificationUnknownEvent, WaMexOwnUsernameSyncEvent, WaMexTextStatusUpdateEvent, WaMexTextStatusUpdateHintEvent, WaMexUsernameDeleteEvent, WaMexUsernameSetEvent, WaMexUsernameUpdateHintEvent, WaOfflineResumeEvent, WaPictureEvent, WaPictureEventAction, WaPrivacyTokenUpdateEvent, WaReceiptStatus, WaRegistrationCodeEvent, WaSendMessageOptions, WaUnavailableMessageKind, WaVerifiedNameResult, WaAddonKind, WaNewsletterEventAction, WaNewsletterMessageUpdate, WaNewsletterPollVoteEntry, WaNewsletterReactionEntry } from './client/types';
|
|
5
8
|
export type { WaAppStateMutationCoordinator, WaBroadcastListParticipant, WaSetBroadcastListInput, WaSetStatusPrivacyInput } from './client/coordinators/WaAppStateMutationCoordinator';
|
|
@@ -21,6 +24,7 @@ export type { WaSendStatusInput, WaStatusCoordinator } from './client/coordinato
|
|
|
21
24
|
export type { WaEncryptedMessageInput, WaMessageAckMetadata, WaMessageKey, WaMessagePublishOptions, WaMessagePublishResult, WaMessageRef, WaMessageTargetInput, WaSendEditKey, WaSendEventLocation, WaSendEventMessage, WaSendEventParent, WaSendEventResponseMessage, WaSendEventResponseType, WaSendKeepMessage, WaSendMediaMessage, WaSendMessageContent, WaSendPinMessage, WaSendPollMessage, WaSendPollOptionInput, WaSendPollParent, WaSendPollVoteMessage, WaSendReactionMessage, WaSendReceiptEventOptions, WaSendReceiptInput, WaSendReceiptOptions, WaSendRevokeMessage, WaSendStickerPackMessage, WaSendStickerPackStickerInput, WaSendStickerPackTrayIcon, WaSendTextMessage } from './message/types';
|
|
22
25
|
export { getContentType, resolveMessageTarget } from './message/encode/content';
|
|
23
26
|
export { resolveMediaPayload } from './message/encode/media-payload';
|
|
27
|
+
export { unpadPkcs7, writeRandomPadMax16 } from './message/encode/padding';
|
|
24
28
|
export type { WaResolvedMediaPayload } from './message/encode/media-payload';
|
|
25
29
|
export type { WaSendContextInfo } from './message/context-info';
|
|
26
30
|
export type { WaLinkPreviewFetcher, WaLinkPreviewOptions, WaLinkPreviewOverride, WaLinkPreviewResolved, WaLinkPreviewThumbnailBytes, WaLinkPreviewThumbnailInput, WaLinkPreviewThumbnailStream, WaLinkPreviewType } from './message/addons/link-preview/types';
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.proto = exports.WA_XMLNS = exports.WA_PRIVACY_VALUES = exports.WA_PRIVACY_TAGS = exports.WA_PRIVACY_SETTING_TO_CATEGORY = exports.WA_PRIVACY_DISALLOWED_LIST_CATEGORIES = exports.WA_PRIVACY_CATEGORY_TO_SETTING = exports.WA_PRIVACY_CATEGORIES = exports.WA_SUPPORTED_DIRTY_TYPES = exports.WA_STREAM_SIGNALING = exports.WA_SIGNALING = exports.WA_RETRYABLE_ACK_CODES = exports.WA_READY_STATES = exports.WA_PREVIEW_MEDIA_HKDF_INFO = exports.WA_PAIRING_KDF_INFO = exports.WA_NODE_TAGS = exports.WA_MEDIA_HKDF_INFO = exports.WA_MESSAGE_TYPES = exports.WA_MESSAGE_TAGS = exports.WA_LOGOUT_REASONS = exports.WA_IQ_TYPES = exports.WA_DISCONNECT_REASONS = exports.WA_DIRTY_TYPES = exports.WA_DIRTY_PROTOCOLS = exports.WA_DEFAULTS = void 0;
|
|
3
|
+
exports.WA_BROWSERS = exports.WA_APP_STATE_SYNC_DATA_TYPE = exports.WA_APP_STATE_KEY_TYPES = exports.WA_APP_STATE_KDF_INFO = exports.WA_APP_STATE_ERROR_CODES = exports.WA_APP_STATE_COLLECTION_STATES = exports.WA_APP_STATE_COLLECTIONS = exports.WA_ACCOUNT_SYNC_PROTOCOLS = exports.toUserJid = exports.splitJid = exports.signalAddressKey = exports.parseSignalAddressFromJid = exports.parsePhoneJid = exports.parseJidFull = exports.normalizeRecipientJid = exports.normalizeDeviceJid = exports.isUserJid = exports.isStatusBroadcastJid = exports.isNewsletterJid = exports.isLidJid = exports.isHostedServer = exports.isHostedDeviceJid = exports.isHostedDeviceId = exports.isGroupOrBroadcastJid = exports.isGroupJid = exports.isBroadcastJid = exports.isBotJid = exports.getWaMediaHkdfInfo = exports.getWaCompanionPlatformId = exports.getLoginIdentity = exports.canonicalizeSignalServer = exports.canonicalizeSignalJid = exports.buildDeviceJid = exports.delay = exports.WaAuthMemoryStore = exports.createStore = exports.createNoopLogger = exports.createPinoLogger = exports.PinoLogger = exports.ConsoleLogger = exports.fetchLatestWaWebVersion = exports.writeRandomPadMax16 = exports.unpadPkcs7 = exports.resolveMediaPayload = exports.resolveMessageTarget = exports.getContentType = exports.parseUsyncResultEnvelope = exports.downloadMediaMessage = exports.defineWaClientPlugin = exports.WaClient = void 0;
|
|
4
|
+
exports.proto = exports.WA_XMLNS = exports.WA_PRIVACY_VALUES = exports.WA_PRIVACY_TAGS = exports.WA_PRIVACY_SETTING_TO_CATEGORY = exports.WA_PRIVACY_DISALLOWED_LIST_CATEGORIES = exports.WA_PRIVACY_CATEGORY_TO_SETTING = exports.WA_PRIVACY_CATEGORIES = exports.WA_SUPPORTED_DIRTY_TYPES = exports.WA_STREAM_SIGNALING = exports.WA_SIGNALING = exports.WA_RETRYABLE_ACK_CODES = exports.WA_READY_STATES = exports.WA_PREVIEW_MEDIA_HKDF_INFO = exports.WA_PAIRING_KDF_INFO = exports.WA_NODE_TAGS = exports.WA_MEDIA_HKDF_INFO = exports.WA_MESSAGE_TYPES = exports.WA_MESSAGE_TAGS = exports.WA_LOGOUT_REASONS = exports.WA_IQ_TYPES = exports.WA_DISCONNECT_REASONS = exports.WA_DIRTY_TYPES = exports.WA_DIRTY_PROTOCOLS = exports.WA_DEFAULTS = exports.WA_COMPANION_PLATFORM_IDS = exports.WA_BUSINESS_HOURS_MODES = exports.WA_BUSINESS_HOURS_DAYS = void 0;
|
|
5
5
|
var _client_1 = require("./client");
|
|
6
6
|
Object.defineProperty(exports, "WaClient", { enumerable: true, get: function () { return _client_1.WaClient; } });
|
|
7
|
+
var plugins_1 = require("./client/plugins");
|
|
8
|
+
Object.defineProperty(exports, "defineWaClientPlugin", { enumerable: true, get: function () { return plugins_1.defineWaClientPlugin; } });
|
|
7
9
|
var media_1 = require("./client/media");
|
|
8
10
|
Object.defineProperty(exports, "downloadMediaMessage", { enumerable: true, get: function () { return media_1.downloadMediaMessage; } });
|
|
9
11
|
var usync_1 = require("./transport/node/builders/usync");
|
|
@@ -13,6 +15,9 @@ Object.defineProperty(exports, "getContentType", { enumerable: true, get: functi
|
|
|
13
15
|
Object.defineProperty(exports, "resolveMessageTarget", { enumerable: true, get: function () { return content_1.resolveMessageTarget; } });
|
|
14
16
|
var media_payload_1 = require("./message/encode/media-payload");
|
|
15
17
|
Object.defineProperty(exports, "resolveMediaPayload", { enumerable: true, get: function () { return media_payload_1.resolveMediaPayload; } });
|
|
18
|
+
var padding_1 = require("./message/encode/padding");
|
|
19
|
+
Object.defineProperty(exports, "unpadPkcs7", { enumerable: true, get: function () { return padding_1.unpadPkcs7; } });
|
|
20
|
+
Object.defineProperty(exports, "writeRandomPadMax16", { enumerable: true, get: function () { return padding_1.writeRandomPadMax16; } });
|
|
16
21
|
var wa_web_version_fetcher_1 = require("./transport/wa-web-version-fetcher");
|
|
17
22
|
Object.defineProperty(exports, "fetchLatestWaWebVersion", { enumerable: true, get: function () { return wa_web_version_fetcher_1.fetchLatestWaWebVersion; } });
|
|
18
23
|
var ConsoleLogger_1 = require("./infra/log/ConsoleLogger");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Logger, type LogLevel } from '../log/types';
|
|
2
2
|
/**
|
|
3
3
|
* Default zero-dependency {@link Logger} that writes structured records to
|
|
4
4
|
* the standard `console` sinks. Messages below the configured `level` are
|
|
@@ -24,6 +24,8 @@ export declare class ConsoleLogger implements Logger {
|
|
|
24
24
|
* Returns a derived logger with `bindings` merged into the parent's
|
|
25
25
|
* bindings. Per-call context still wins on key conflicts.
|
|
26
26
|
*/
|
|
27
|
-
child(bindings: Readonly<Record<string, unknown
|
|
27
|
+
child(bindings: Readonly<Record<string, unknown>>, options?: {
|
|
28
|
+
readonly level?: LogLevel;
|
|
29
|
+
}): Logger;
|
|
28
30
|
private write;
|
|
29
31
|
}
|
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ConsoleLogger = void 0;
|
|
4
|
-
const
|
|
5
|
-
trace: 10,
|
|
6
|
-
debug: 20,
|
|
7
|
-
info: 30,
|
|
8
|
-
warn: 40,
|
|
9
|
-
error: 50
|
|
10
|
-
};
|
|
4
|
+
const types_1 = require("../log/types");
|
|
11
5
|
const CONSOLE_WRITERS = {
|
|
12
6
|
trace: (...args) => console.debug(...args),
|
|
13
7
|
debug: (...args) => console.debug(...args),
|
|
@@ -24,7 +18,7 @@ class ConsoleLogger {
|
|
|
24
18
|
/** @param level Minimum level to emit. Defaults to `'info'`. */
|
|
25
19
|
constructor(level = 'info', bindings = null) {
|
|
26
20
|
this.level = level;
|
|
27
|
-
this.minLevelPriority = LOG_LEVEL_PRIORITY[level];
|
|
21
|
+
this.minLevelPriority = types_1.LOG_LEVEL_PRIORITY[level];
|
|
28
22
|
this.bindings = bindings;
|
|
29
23
|
}
|
|
30
24
|
/** Emits a `trace` record. */
|
|
@@ -51,12 +45,12 @@ class ConsoleLogger {
|
|
|
51
45
|
* Returns a derived logger with `bindings` merged into the parent's
|
|
52
46
|
* bindings. Per-call context still wins on key conflicts.
|
|
53
47
|
*/
|
|
54
|
-
child(bindings) {
|
|
48
|
+
child(bindings, options) {
|
|
55
49
|
const merged = this.bindings ? { ...this.bindings, ...bindings } : { ...bindings };
|
|
56
|
-
return new ConsoleLogger(this.level, merged);
|
|
50
|
+
return new ConsoleLogger(options?.level ?? this.level, merged);
|
|
57
51
|
}
|
|
58
52
|
write(level, message, context) {
|
|
59
|
-
if (LOG_LEVEL_PRIORITY[level] < this.minLevelPriority) {
|
|
53
|
+
if (types_1.LOG_LEVEL_PRIORITY[level] < this.minLevelPriority) {
|
|
60
54
|
return;
|
|
61
55
|
}
|
|
62
56
|
if (this.bindings) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Logger, type LogLevel } from '../log/types';
|
|
2
2
|
type PinoLikeLogger = {
|
|
3
3
|
level: string;
|
|
4
4
|
trace: (...args: unknown[]) => void;
|
|
@@ -72,7 +72,9 @@ export declare class PinoLogger implements Logger {
|
|
|
72
72
|
* call's context. Delegates to the underlying pino `child()` when
|
|
73
73
|
* available; otherwise wraps with a parent + bindings merge.
|
|
74
74
|
*/
|
|
75
|
-
child(bindings: Readonly<Record<string, unknown
|
|
75
|
+
child(bindings: Readonly<Record<string, unknown>>, options?: {
|
|
76
|
+
readonly level?: LogLevel;
|
|
77
|
+
}): Logger;
|
|
76
78
|
private write;
|
|
77
79
|
}
|
|
78
80
|
/**
|
|
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.PinoLogger = void 0;
|
|
37
37
|
exports.createPinoLogger = createPinoLogger;
|
|
38
|
+
const types_1 = require("../log/types");
|
|
38
39
|
const PINO_MODULE = 'pino';
|
|
39
40
|
const PINO_PRETTY_MODULE = 'pino-pretty';
|
|
40
41
|
async function loadPinoFactory() {
|
|
@@ -94,11 +95,11 @@ class PinoLogger {
|
|
|
94
95
|
* call's context. Delegates to the underlying pino `child()` when
|
|
95
96
|
* available; otherwise wraps with a parent + bindings merge.
|
|
96
97
|
*/
|
|
97
|
-
child(bindings) {
|
|
98
|
+
child(bindings, options) {
|
|
98
99
|
if (typeof this.logger.child === 'function') {
|
|
99
|
-
return new PinoLogger(this.logger.child(bindings), this.level);
|
|
100
|
+
return new PinoLogger(this.logger.child(bindings), options?.level ?? this.level);
|
|
100
101
|
}
|
|
101
|
-
return new BoundLogger(this, bindings);
|
|
102
|
+
return new BoundLogger(this, bindings, options?.level);
|
|
102
103
|
}
|
|
103
104
|
write(level, message, context) {
|
|
104
105
|
if (context === null || context === undefined) {
|
|
@@ -121,28 +122,39 @@ exports.PinoLogger = PinoLogger;
|
|
|
121
122
|
* underlying logger does not support `child()` natively.
|
|
122
123
|
*/
|
|
123
124
|
class BoundLogger {
|
|
124
|
-
constructor(parent, bindings) {
|
|
125
|
+
constructor(parent, bindings, level) {
|
|
125
126
|
this.parent = parent;
|
|
126
|
-
this.level = parent.level;
|
|
127
|
+
this.level = level ?? parent.level;
|
|
127
128
|
this.bindings = bindings;
|
|
129
|
+
this.minPriority = types_1.LOG_LEVEL_PRIORITY[this.level];
|
|
128
130
|
}
|
|
129
131
|
trace(message, context) {
|
|
130
|
-
|
|
132
|
+
if (types_1.LOG_LEVEL_PRIORITY.trace >= this.minPriority) {
|
|
133
|
+
this.parent.trace(message, this.merge(context));
|
|
134
|
+
}
|
|
131
135
|
}
|
|
132
136
|
debug(message, context) {
|
|
133
|
-
|
|
137
|
+
if (types_1.LOG_LEVEL_PRIORITY.debug >= this.minPriority) {
|
|
138
|
+
this.parent.debug(message, this.merge(context));
|
|
139
|
+
}
|
|
134
140
|
}
|
|
135
141
|
info(message, context) {
|
|
136
|
-
|
|
142
|
+
if (types_1.LOG_LEVEL_PRIORITY.info >= this.minPriority) {
|
|
143
|
+
this.parent.info(message, this.merge(context));
|
|
144
|
+
}
|
|
137
145
|
}
|
|
138
146
|
warn(message, context) {
|
|
139
|
-
|
|
147
|
+
if (types_1.LOG_LEVEL_PRIORITY.warn >= this.minPriority) {
|
|
148
|
+
this.parent.warn(message, this.merge(context));
|
|
149
|
+
}
|
|
140
150
|
}
|
|
141
151
|
error(message, context) {
|
|
142
|
-
|
|
152
|
+
if (types_1.LOG_LEVEL_PRIORITY.error >= this.minPriority) {
|
|
153
|
+
this.parent.error(message, this.merge(context));
|
|
154
|
+
}
|
|
143
155
|
}
|
|
144
|
-
child(bindings) {
|
|
145
|
-
return new BoundLogger(this.parent, { ...this.bindings, ...bindings });
|
|
156
|
+
child(bindings, options) {
|
|
157
|
+
return new BoundLogger(this.parent, { ...this.bindings, ...bindings }, options?.level ?? this.level);
|
|
146
158
|
}
|
|
147
159
|
merge(context) {
|
|
148
160
|
return context ? { ...this.bindings, ...context } : this.bindings;
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error';
|
|
2
|
+
export declare const LOG_LEVEL_PRIORITY: Readonly<Record<LogLevel, number>>;
|
|
3
|
+
export interface LoggerChildOptions {
|
|
4
|
+
/** Minimum level the derived logger emits; defaults to the parent's level. */
|
|
5
|
+
readonly level?: LogLevel;
|
|
6
|
+
}
|
|
2
7
|
export interface Logger {
|
|
3
8
|
readonly level: LogLevel;
|
|
4
9
|
trace(message: string, context?: Readonly<Record<string, unknown>>): void;
|
|
@@ -10,7 +15,9 @@ export interface Logger {
|
|
|
10
15
|
* Returns a derived logger that pre-binds `bindings` into every log
|
|
11
16
|
* call's context object. Bindings stack: `parent.child(a).child(b)`
|
|
12
17
|
* merges `{ ...a, ...b }`. Per-call context wins on key conflicts.
|
|
18
|
+
* Pass `options.level` to give the child its own minimum level
|
|
19
|
+
* (independent of the parent), e.g. to quiet a noisy subsystem.
|
|
13
20
|
*/
|
|
14
|
-
child(bindings: Readonly<Record<string, unknown
|
|
21
|
+
child(bindings: Readonly<Record<string, unknown>>, options?: LoggerChildOptions): Logger;
|
|
15
22
|
}
|
|
16
23
|
export declare function createNoopLogger(level?: LogLevel): Logger;
|