@oxidezap/baileyrs 0.0.32 → 0.1.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/README.md +77 -24
  2. package/lib/Bridge/adapt.d.ts +1 -1
  3. package/lib/Bridge/history-sync-wire.d.ts +1 -1
  4. package/lib/Bridge/history-sync-wire.js +2 -2
  5. package/lib/Bridge/schema.d.ts +1 -1
  6. package/lib/Bridge/schema.js +10 -10
  7. package/lib/Bridge/types.d.ts +1 -1
  8. package/lib/Compatibility/group-metadata.d.ts +1 -1
  9. package/lib/Compatibility/legacy-store/codecs/basic.js +1 -1
  10. package/lib/Compatibility/legacy-store/codecs/signal.js +17 -5
  11. package/lib/Compatibility/legacy-store/device.js +1 -1
  12. package/lib/Compatibility/legacy-store/multi-file.js +1 -1
  13. package/lib/Compatibility/legacy-store/native-projection.d.ts +1 -1
  14. package/lib/Compatibility/legacy-store/types.d.ts +1 -1
  15. package/lib/Compatibility/media-type.d.ts +1 -1
  16. package/lib/Compatibility/message-relay.d.ts +1 -1
  17. package/lib/Compatibility/proto-runtime.js +119 -45
  18. package/lib/Compatibility/socket-results.d.ts +1 -1
  19. package/lib/Compatibility/stanza-responses.d.ts +1 -1
  20. package/lib/Compatibility/usync/adapter.d.ts +1 -1
  21. package/lib/Compatibility/websocket-client.d.ts +24 -3
  22. package/lib/Compatibility/websocket-client.js +47 -18
  23. package/lib/Socket/bridge-client-owner.d.ts +89 -0
  24. package/lib/Socket/bridge-client-owner.js +135 -0
  25. package/lib/Socket/communities.d.ts +2 -2
  26. package/lib/Socket/contacts.d.ts +1 -1
  27. package/lib/Socket/events.d.ts +32 -1
  28. package/lib/Socket/events.js +140 -37
  29. package/lib/Socket/index.d.ts +32 -6
  30. package/lib/Socket/index.js +433 -132
  31. package/lib/Socket/messages.d.ts +4 -1
  32. package/lib/Socket/messages.js +6 -4
  33. package/lib/Socket/newsletter.d.ts +3 -3
  34. package/lib/Socket/terminal-close-reporter.d.ts +79 -0
  35. package/lib/Socket/terminal-close-reporter.js +108 -0
  36. package/lib/Socket/terminal-close.d.ts +39 -0
  37. package/lib/Socket/terminal-close.js +51 -0
  38. package/lib/Socket/transport.d.ts +1 -1
  39. package/lib/Socket/types.d.ts +1 -1
  40. package/lib/Types/Auth.d.ts +1 -1
  41. package/lib/Types/Message.d.ts +1 -1
  42. package/lib/Types/Socket.d.ts +2 -2
  43. package/lib/Utils/crypto.d.ts +2 -2
  44. package/lib/Utils/crypto.js +1 -1
  45. package/lib/Utils/event-buffer.js +31 -0
  46. package/lib/Utils/logger.d.ts +2 -2
  47. package/lib/Utils/logger.js +122 -25
  48. package/lib/Utils/messages.d.ts +12 -1
  49. package/lib/Utils/messages.js +39 -15
  50. package/lib/Utils/process-history-message.js +6 -10
  51. package/lib/Utils/process-message.js +1 -1
  52. package/lib/WAProto/runtime.js +5 -2
  53. package/package.json +3 -3
@@ -505,10 +505,14 @@ export const generateWAMessageContent = async (message, options) => {
505
505
  };
506
506
  export const generateWAMessageFromContent = (jid, message, options) => {
507
507
  const innerMessage = normalizeMessageContent(message);
508
- const key = getContentType(innerMessage);
509
508
  const timestamp = unixTimestampSeconds(options.timestamp);
510
509
  const { quoted, userJid } = options;
510
+ // Only the quote and ephemeral branches read the content key, and a plain
511
+ // send takes neither, so resolve it on demand instead of on every send.
512
+ let key;
511
513
  if (quoted && !isJidNewsletter(jid)) {
514
+ const contentKey = getContentType(innerMessage);
515
+ key = contentKey;
512
516
  const participant = quoted.key.fromMe
513
517
  ? userJid // TODO: Add support for LIDs
514
518
  : quoted.participant || quoted.key.participant || quoted.key.remoteJid;
@@ -520,7 +524,7 @@ export const generateWAMessageFromContent = (jid, message, options) => {
520
524
  if (typeof quotedContent === 'object' && quotedContent && 'contextInfo' in quotedContent) {
521
525
  delete quotedContent.contextInfo;
522
526
  }
523
- const contextInfo = ('contextInfo' in innerMessage[key] && innerMessage[key]?.contextInfo) || {};
527
+ const contextInfo = ('contextInfo' in innerMessage[contentKey] && innerMessage[contentKey]?.contextInfo) || {};
524
528
  contextInfo.participant = jidNormalizedUser(participant);
525
529
  contextInfo.stanzaId = quoted.key.id;
526
530
  contextInfo.quotedMessage = quotedMsg;
@@ -529,26 +533,27 @@ export const generateWAMessageFromContent = (jid, message, options) => {
529
533
  if (jid !== quoted.key.remoteJid) {
530
534
  contextInfo.remoteJid = quoted.key.remoteJid;
531
535
  }
532
- if (contextInfo && innerMessage[key]) {
536
+ if (contextInfo && innerMessage[contentKey]) {
533
537
  /* @ts-ignore */
534
- innerMessage[key].contextInfo = contextInfo;
538
+ innerMessage[contentKey].contextInfo = contextInfo;
535
539
  }
536
540
  }
537
541
  if (
538
542
  // if we want to send a disappearing message
539
543
  !!options?.ephemeralExpiration &&
540
- // and it's not a protocol message -- delete, toggle disappear message
541
- key !== 'protocolMessage' &&
542
- // already not converted to disappearing message
543
- key !== 'ephemeralMessage' &&
544
544
  // newsletters don't support ephemeral messages
545
545
  !isJidNewsletter(jid)) {
546
- /* @ts-ignore */
547
- innerMessage[key].contextInfo = {
548
- ...innerMessage[key].contextInfo,
549
- expiration: options.ephemeralExpiration || WA_DEFAULT_EPHEMERAL
550
- //ephemeralSettingTimestamp: options.ephemeralOptions.eph_setting_ts?.toString()
551
- };
546
+ const contentKey = key ?? getContentType(innerMessage);
547
+ // skip protocol messages -- delete, toggle disappear message -- and
548
+ // content already converted to a disappearing message
549
+ if (contentKey !== 'protocolMessage' && contentKey !== 'ephemeralMessage') {
550
+ /* @ts-ignore */
551
+ innerMessage[contentKey].contextInfo = {
552
+ ...innerMessage[contentKey].contextInfo,
553
+ expiration: options.ephemeralExpiration || WA_DEFAULT_EPHEMERAL
554
+ //ephemeralSettingTimestamp: options.ephemeralOptions.eph_setting_ts?.toString()
555
+ };
556
+ }
552
557
  }
553
558
  // `create` copies into a fresh instance; content built by
554
559
  // `generateWAMessageContent` already is one, and the branches above mutate
@@ -720,6 +725,22 @@ export const _registerActiveBridgeClient = (client, logger) => {
720
725
  activeBridgeClient = client;
721
726
  activeBridgeLogger = logger;
722
727
  };
728
+ /**
729
+ * Drop the module-level pointer when `sock.end()` frees the client it points
730
+ * at. Without this the global keeps a strong reference to a freed
731
+ * `WasmWhatsAppClient`, so the next standalone `downloadContentFromMessage()`
732
+ * call reaches into a null wasm pointer and fails with an opaque
733
+ * wasm-bindgen error instead of the actionable "no bridge client" Boom.
734
+ *
735
+ * Identity-checked on purpose: a multi-account host that ends socket A after
736
+ * creating socket B must not clear B's registration.
737
+ */
738
+ export const _unregisterActiveBridgeClient = (client) => {
739
+ if (activeBridgeClient !== client)
740
+ return;
741
+ activeBridgeClient = undefined;
742
+ activeBridgeLogger = undefined;
743
+ };
723
744
  const noopLogger = {
724
745
  level: 'silent',
725
746
  child: () => noopLogger,
@@ -746,9 +767,12 @@ export const downloadContentFromMessage = async (mediaContent, type, opts = {})
746
767
  throw new Boom('downloadContentFromMessage: no bridge client available. ' +
747
768
  'Pass `opts.client = sock.waClient`, or call after `makeWASocket()` has initialized.', { statusCode: 500 });
748
769
  }
770
+ // `url` is seeded because the media guard downstream keys off its presence,
771
+ // and content addressed only by `directPath` (history-sync notifications
772
+ // carry no `url` field at all) would otherwise be rejected as non-media.
749
773
  const fakeMessage = {
750
774
  key: {},
751
- message: { [`${type}Message`]: mediaContent }
775
+ message: { [`${type}Message`]: { url: null, ...mediaContent } }
752
776
  };
753
777
  return downloadMediaMessage(fakeMessage, 'stream', opts, {
754
778
  logger: opts.logger ?? activeBridgeLogger ?? noopLogger,
@@ -10,9 +10,7 @@
10
10
  * are limited to swapping upstream imports for baileyrs equivalents and
11
11
  * keeping the WAProto namespace as our re-export.
12
12
  */
13
- import { pipeline } from 'node:stream/promises';
14
- import { promisify } from 'node:util';
15
- import { createInflate, inflate } from 'node:zlib';
13
+ import { inflateZlib } from '@oxidezap/whatsapp-rust-bridge';
16
14
  import { proto } from '../WAProto/runtime.js';
17
15
  import { WAProto } from '../Types/index.js';
18
16
  import { isHostedLidUser, isHostedPnUser, isLidUser, isPnUser } from '../WABinary/jid-utils.js';
@@ -21,7 +19,6 @@ import { toNumber } from './generics.js';
21
19
  import { downloadContentFromMessage, normalizeMessageContent } from './messages.js';
22
20
  import { createSparseArray } from './sparse-array.js';
23
21
  const STUB = WAProto.WebMessageInfo.StubType;
24
- const inflatePromise = promisify(inflate);
25
22
  const extractPnFromMessages = (messages) => {
26
23
  for (let index = 0; index < messages.length; index++) {
27
24
  const msgItem = messages[index];
@@ -190,16 +187,15 @@ export const processHistoryMessage = (item, logger) => {
190
187
  /** Download, decrypt and inflate an external history-sync blob. */
191
188
  export const downloadHistory = async (msg, options) => {
192
189
  const stream = await downloadContentFromMessage(msg, 'md-msg-hist', { options });
193
- const inflater = createInflate();
194
- const chunks = [];
195
- inflater.on('data', (chunk) => chunks.push(chunk));
196
- await pipeline(stream, inflater);
197
- return proto.HistorySync.decode(Buffer.concat(chunks));
190
+ const compressed = [];
191
+ for await (const chunk of stream)
192
+ compressed.push(chunk);
193
+ return proto.HistorySync.decode(inflateZlib(Buffer.concat(compressed)));
198
194
  };
199
195
  /** Resolve inline or external history-sync content and normalize its public payload. */
200
196
  export const downloadAndProcessHistorySyncNotification = async (msg, options, logger) => {
201
197
  const historyMsg = msg.initialHistBootstrapInlinePayload
202
- ? proto.HistorySync.decode(await inflatePromise(msg.initialHistBootstrapInlinePayload))
198
+ ? proto.HistorySync.decode(inflateZlib(msg.initialHistBootstrapInlinePayload))
203
199
  : await downloadHistory(msg, options);
204
200
  return processHistoryMessage(historyMsg, logger);
205
201
  };
@@ -1,6 +1,6 @@
1
1
  import { WAMessageStubType } from '../Types/index.js';
2
2
  import { proto } from '../WAProto/runtime.js';
3
- import { decryptEventResponsePayload, decryptPollVotePayload } from 'whatsapp-rust-bridge';
3
+ import { decryptEventResponsePayload, decryptPollVotePayload } from '@oxidezap/whatsapp-rust-bridge';
4
4
  import { areJidsSameUser, isHostedLidUser, isHostedPnUser, isJidBroadcast, isJidStatusBroadcast, jidDecode, jidEncode, jidNormalizedUser } from '../WABinary/index.js';
5
5
  import { Boom } from './boom.js';
6
6
  import { getContentType, normalizeMessageContent } from './messages.js';
@@ -4,13 +4,16 @@
4
4
  * compatibility layer below translates constructor/object semantics while the
5
5
  * bridge remains the single protobuf codec shipped by this package.
6
6
  */
7
- import { proto as bridgeProto } from 'whatsapp-rust-bridge/proto-types';
7
+ import { proto as bridgeProto } from '@oxidezap/whatsapp-rust-bridge/proto-types';
8
8
  import { createProtoCompatibilityFacade } from '../Compatibility/proto-runtime.js';
9
9
  const facade = createProtoCompatibilityFacade(bridgeProto);
10
10
  // Re-exporting the original namespace alias preserves its generated type
11
11
  // namespace for internal `proto.IMessage` references. The facade already
12
12
  // captured every neutral codec before these top-level values are replaced.
13
- Object.assign(bridgeProto, facade.proto);
13
+ //
14
+ // Descriptors, not values: the facade's entries are lazy getters, and
15
+ // Object.assign would read — and therefore build — every one of them.
16
+ Object.defineProperties(bridgeProto, Object.getOwnPropertyDescriptors(facade.proto));
14
17
  export { bridgeProto as proto };
15
18
  /** Internal audit signal; intentionally absent from the public package root. */
16
19
  export const unsupportedProtoCodecs = facade.unsupportedCodecs;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@oxidezap/baileyrs",
3
3
  "type": "module",
4
- "version": "0.0.32",
4
+ "version": "0.1.0",
5
5
  "description": "A Rust-powered WhatsApp Web library for JavaScript, with a Baileys-compatible API",
6
6
  "keywords": [
7
7
  "whatsapp",
@@ -75,10 +75,10 @@
75
75
  },
76
76
  "dependencies": {
77
77
  "@hapi/boom": "^9.1.4",
78
+ "@oxidezap/whatsapp-rust-bridge": "0.6.5",
78
79
  "long": "^5.3.2",
79
80
  "pino": "^10.3.1",
80
- "protobufjs": "^7.6.5",
81
- "whatsapp-rust-bridge": "0.6.0-alpha.42"
81
+ "protobufjs": "^7.6.5"
82
82
  },
83
83
  "devDependencies": {
84
84
  "@bufbuild/protobuf": "^2.13.0",