zapo-js 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/README.md +1 -1
  2. package/dist/appstate/crypto/WaAppStateCrypto.js +1 -1
  3. package/dist/appstate/parsers/encoding.js +1 -1
  4. package/dist/appstate/parsers/response-parser.js +1 -1
  5. package/dist/appstate/sync/WaAppStateSyncClient.js +2 -2
  6. package/dist/appstate-spec.js +1 -1
  7. package/dist/auth/credentials-flow.js +2 -2
  8. package/dist/auth/pairing/WaPairingFlow.js +2 -2
  9. package/dist/auth/pairing/pairing-code-crypto.js +1 -1
  10. package/dist/client/WaClient.js +2 -2
  11. package/dist/client/WaClientFactory.js +3 -1
  12. package/dist/client/coordinators/WaAppStateMutationCoordinator.js +2 -2
  13. package/dist/client/coordinators/WaBotCoordinator.js +1 -1
  14. package/dist/client/coordinators/WaMessageCoordinator.js +1 -1
  15. package/dist/client/coordinators/WaMessageDispatchCoordinator.js +3 -3
  16. package/dist/client/coordinators/WaRetryCoordinator.js +1 -1
  17. package/dist/client/coordinators/WaStatusCoordinator.js +1 -1
  18. package/dist/client/coordinators/WaStreamControlCoordinator.js +2 -3
  19. package/dist/client/events/appstate-mutation.js +1 -1
  20. package/dist/client/events/business.js +1 -1
  21. package/dist/client/media.js +2 -2
  22. package/dist/client/messaging/group-metadata.js +20 -9
  23. package/dist/client/messaging/key-protocol.js +1 -1
  24. package/dist/client/messaging/link-preview.js +1 -1
  25. package/dist/client/messaging/messages.js +2 -2
  26. package/dist/client/newsletter/content.js +1 -1
  27. package/dist/client/persistence/history-sync.js +1 -1
  28. package/dist/client/persistence/mailbox.js +1 -1
  29. package/dist/esm/client/WaClient.js +1 -1
  30. package/dist/esm/client/WaClientFactory.js +3 -1
  31. package/dist/esm/client/coordinators/WaStreamControlCoordinator.js +2 -3
  32. package/dist/esm/client/media.js +2 -2
  33. package/dist/esm/client/messaging/group-metadata.js +20 -9
  34. package/dist/esm/signal/api/SignalDeviceSyncApi.js +3 -1
  35. package/dist/esm/signal/registration/utils.js +3 -2
  36. package/dist/esm/store/locks/pre-key.lock.js +4 -1
  37. package/dist/index.js +4 -4
  38. package/dist/message/addons/link-preview/fetcher.js +1 -1
  39. package/dist/message/crypto/addon-crypto.js +2 -2
  40. package/dist/message/crypto/icdc.js +1 -1
  41. package/dist/message/crypto/reporting-token.js +2 -2
  42. package/dist/message/crypto/use-case-secret.js +1 -1
  43. package/dist/message/encode/content.js +1 -1
  44. package/dist/message/encode/padding.js +1 -1
  45. package/dist/message/kinds/bot.js +2 -2
  46. package/dist/message/kinds/newsletter.js +1 -1
  47. package/dist/message/primitives/incoming.js +1 -1
  48. package/dist/message/primitives/peer-data-operation.js +1 -1
  49. package/dist/protocol/bot.js +1 -1
  50. package/dist/retry/replay.js +1 -1
  51. package/dist/signal/api/SignalDeviceSyncApi.js +3 -1
  52. package/dist/signal/api/SignalDigestSyncApi.js +1 -1
  53. package/dist/signal/attestation/WaAdvSignature.js +1 -1
  54. package/dist/signal/group/SenderKeyChain.js +1 -1
  55. package/dist/signal/group/SenderKeyCodec.js +2 -2
  56. package/dist/signal/group/SenderKeyManager.js +2 -2
  57. package/dist/signal/group/encoding.js +1 -1
  58. package/dist/signal/registration/keygen.js +1 -1
  59. package/dist/signal/registration/utils.js +3 -2
  60. package/dist/signal/session/SignalProtocol.js +1 -1
  61. package/dist/signal/session/SignalRatchet.js +2 -2
  62. package/dist/signal/session/SignalSerializer.js +2 -2
  63. package/dist/signal/session/SignalSession.js +1 -1
  64. package/dist/signal/session/encoding.js +1 -1
  65. package/dist/store/locks/pre-key.lock.js +4 -1
  66. package/dist/transport/node/builders/global.js +1 -1
  67. package/dist/transport/node/helpers.js +1 -1
  68. package/dist/transport/node/mex/client.js +1 -1
  69. package/dist/transport/noise/WaClientPayload.js +2 -2
  70. package/dist/transport/noise/WaMobileClientPayload.js +1 -1
  71. package/dist/transport/noise/WaNoiseCert.js +2 -2
  72. package/dist/transport/noise/WaNoiseHandshake.js +1 -1
  73. package/dist/transport/noise/WaNoiseSession.js +2 -2
  74. package/dist/transport/noise/WaNoiseSocket.js +1 -1
  75. package/dist/types/appstate/crypto/WaAppStateCrypto.d.ts +1 -1
  76. package/dist/types/appstate/parsers/response-parser.d.ts +1 -1
  77. package/dist/types/appstate/sync/WaAppStateSyncClient.d.ts +1 -1
  78. package/dist/types/appstate/types.d.ts +1 -1
  79. package/dist/types/appstate/utils.d.ts +1 -1
  80. package/dist/types/appstate-spec.d.ts +1 -1
  81. package/dist/types/auth/types.d.ts +1 -1
  82. package/dist/types/client/coordinators/WaAppStateMutationCoordinator.d.ts +2 -2
  83. package/dist/types/client/coordinators/WaBotCoordinator.d.ts +1 -1
  84. package/dist/types/client/coordinators/WaBroadcastListCoordinator.d.ts +1 -1
  85. package/dist/types/client/coordinators/WaMessageCoordinator.d.ts +1 -1
  86. package/dist/types/client/coordinators/WaMessageDispatchCoordinator.d.ts +1 -1
  87. package/dist/types/client/coordinators/WaStatusCoordinator.d.ts +1 -1
  88. package/dist/types/client/messaging/key-protocol.d.ts +1 -1
  89. package/dist/types/client/newsletter/admin.d.ts +1 -1
  90. package/dist/types/client/newsletter/mex.d.ts +1 -1
  91. package/dist/types/client/newsletter/parse.d.ts +1 -1
  92. package/dist/types/client/newsletter/types.d.ts +1 -1
  93. package/dist/types/client/persistence/history-sync.d.ts +1 -1
  94. package/dist/types/client/types.d.ts +2 -2
  95. package/dist/types/index.d.ts +6 -6
  96. package/dist/types/message/addons/link-preview/builder.d.ts +1 -1
  97. package/dist/types/message/addons/link-preview/types.d.ts +1 -1
  98. package/dist/types/message/context-info.d.ts +1 -1
  99. package/dist/types/message/crypto/addon-crypto.d.ts +1 -1
  100. package/dist/types/message/crypto/icdc.d.ts +1 -1
  101. package/dist/types/message/crypto/reporting-token.d.ts +1 -1
  102. package/dist/types/message/crypto/use-case-secret.d.ts +1 -1
  103. package/dist/types/message/encode/content.d.ts +1 -1
  104. package/dist/types/message/encode/device-sent.d.ts +1 -1
  105. package/dist/types/message/encode/media-payload.d.ts +1 -1
  106. package/dist/types/message/kinds/bot.d.ts +1 -1
  107. package/dist/types/message/kinds/sticker-pack.d.ts +1 -1
  108. package/dist/types/message/primitives/incoming.d.ts +1 -1
  109. package/dist/types/message/primitives/peer-data-operation.d.ts +1 -1
  110. package/dist/types/message/types.d.ts +1 -1
  111. package/dist/types/protocol/bot.d.ts +1 -1
  112. package/dist/types/signal/group/SenderKeyManager.d.ts +1 -1
  113. package/dist/types/signal/session/encoding.d.ts +1 -1
  114. package/dist/types/signal/types.d.ts +1 -1
  115. package/dist/types/transport/node/mex/client.d.ts +1 -1
  116. package/dist/types/transport/noise/WaMobileClientPayload.d.ts +1 -1
  117. package/dist/types/transport/noise/types.d.ts +1 -1
  118. package/package.json +1 -1
package/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <p align="center">
2
- <img src=".github/assets/logo.png" alt="zapo" width="400" />
2
+ <img src="https://raw.githubusercontent.com/vinikjkkj/zapo/master/.github/assets/logo.png" alt="zapo" width="400" />
3
3
  </p>
4
4
 
5
5
  <p align="center">
@@ -5,7 +5,7 @@ const constants_1 = require("../constants");
5
5
  const hkdf_1 = require("../../crypto/core/hkdf");
6
6
  const primitives_1 = require("../../crypto/core/primitives");
7
7
  const random_1 = require("../../crypto/core/random");
8
- const _proto_1 = require("../../proto.js");
8
+ const _proto_1 = require("../../proto");
9
9
  const constants_2 = require("../../protocol/constants");
10
10
  const bytes_1 = require("../../util/bytes");
11
11
  const collections_1 = require("../../util/collections");
@@ -4,7 +4,7 @@ exports.encodeAppStateFingerprint = encodeAppStateFingerprint;
4
4
  exports.decodeAppStateFingerprint = decodeAppStateFingerprint;
5
5
  exports.decodeAppStateSyncKeys = decodeAppStateSyncKeys;
6
6
  exports.decodeAppStateCollections = decodeAppStateCollections;
7
- const _proto_1 = require("../../proto.js");
7
+ const _proto_1 = require("../../proto");
8
8
  const coercion_1 = require("../../util/coercion");
9
9
  const primitives_1 = require("../../util/primitives");
10
10
  /** Serializes an app-state sync key fingerprint to its protobuf bytes, or `null` when absent. */
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.parseSyncResponse = parseSyncResponse;
4
4
  exports.parseCollectionState = parseCollectionState;
5
5
  const utils_1 = require("../utils");
6
- const _proto_1 = require("../../proto.js");
6
+ const _proto_1 = require("../../proto");
7
7
  const constants_1 = require("../../protocol/constants");
8
8
  const helpers_1 = require("../../transport/node/helpers");
9
9
  const primitives_1 = require("../../util/primitives");
@@ -4,8 +4,8 @@ exports.WaAppStateSyncClient = void 0;
4
4
  const constants_1 = require("../constants");
5
5
  const WaAppStateCrypto_1 = require("../crypto/WaAppStateCrypto");
6
6
  const response_parser_1 = require("../parsers/response-parser");
7
- const _crypto_1 = require("../../crypto/index.js");
8
- const _proto_1 = require("../../proto.js");
7
+ const _crypto_1 = require("../../crypto");
8
+ const _proto_1 = require("../../proto");
9
9
  const constants_2 = require("../../protocol/constants");
10
10
  const jid_1 = require("../../protocol/jid");
11
11
  const query_1 = require("../../transport/node/query");
@@ -6,7 +6,7 @@ exports.resolveEnumObject = resolveEnumObject;
6
6
  exports.encodeEnumValue = encodeEnumValue;
7
7
  exports.decodeEnumValue = decodeEnumValue;
8
8
  exports.decodeIndexArgsFromSchema = decodeIndexArgsFromSchema;
9
- const _proto_1 = require("./proto.js");
9
+ const _proto_1 = require("./proto");
10
10
  const appstate_1 = require("../spec/appstate");
11
11
  var appstate_2 = require("../spec/appstate");
12
12
  Object.defineProperty(exports, "WA_APPSTATE_COLLECTIONS", { enumerable: true, get: function () { return appstate_2.WA_APPSTATE_COLLECTIONS; } });
@@ -3,11 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.loadOrCreateCredentials = loadOrCreateCredentials;
4
4
  exports.persistCredentials = persistCredentials;
5
5
  exports.buildCommsConfig = buildCommsConfig;
6
- const _crypto_1 = require("../crypto/index.js");
6
+ const _crypto_1 = require("../crypto");
7
7
  const keys_1 = require("../crypto/core/keys");
8
8
  const X25519_1 = require("../crypto/curves/X25519");
9
9
  const jid_1 = require("../protocol/jid");
10
- const _signal_1 = require("../signal/index.js");
10
+ const _signal_1 = require("../signal");
11
11
  const WaMobileTcpSocket_1 = require("../transport/node/WaMobileTcpSocket");
12
12
  const WaMobileClientPayload_1 = require("../transport/noise/WaMobileClientPayload");
13
13
  const proxy_1 = require("../transport/proxy");
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.WaPairingFlow = void 0;
4
4
  const pairing_code_crypto_1 = require("../pairing/pairing-code-crypto");
5
- const _crypto_1 = require("../../crypto/index.js");
6
- const _proto_1 = require("../../proto.js");
5
+ const _crypto_1 = require("../../crypto");
6
+ const _proto_1 = require("../../proto");
7
7
  const browser_1 = require("../../protocol/browser");
8
8
  const constants_1 = require("../../protocol/constants");
9
9
  const jid_1 = require("../../protocol/jid");
@@ -4,7 +4,7 @@ exports.PBKDF2_ITERATIONS = void 0;
4
4
  exports.normalizeCustomPairingCode = normalizeCustomPairingCode;
5
5
  exports.createCompanionHello = createCompanionHello;
6
6
  exports.completeCompanionFinish = completeCompanionFinish;
7
- const _crypto_1 = require("../../crypto/index.js");
7
+ const _crypto_1 = require("../../crypto");
8
8
  const X25519_1 = require("../../crypto/curves/X25519");
9
9
  const constants_1 = require("../../protocol/constants");
10
10
  const bytes_1 = require("../../util/bytes");
@@ -8,7 +8,7 @@ const mailbox_1 = require("./persistence/mailbox");
8
8
  const WriteBehindPersistence_1 = require("./persistence/WriteBehindPersistence");
9
9
  const WaClientFactory_1 = require("./WaClientFactory");
10
10
  const ConsoleLogger_1 = require("../infra/log/ConsoleLogger");
11
- const _proto_1 = require("../proto.js");
11
+ const _proto_1 = require("../proto");
12
12
  const constants_1 = require("../protocol/constants");
13
13
  const jid_1 = require("../protocol/jid");
14
14
  const stream_1 = require("../protocol/stream");
@@ -35,7 +35,7 @@ const SYNC_RELATED_PROTOCOL_TYPES = new Set([
35
35
  *
36
36
  * @example
37
37
  * ```ts
38
- * import { createPinoLogger, createStore, WaClient } from '../index.js'
38
+ * import { createPinoLogger, createStore, WaClient } from '..'
39
39
  * import { createSqliteStore } from '@zapo-js/store-sqlite'
40
40
  *
41
41
  * const store = createStore({
@@ -153,7 +153,8 @@ function createIncomingNodeRuntime(input) {
153
153
  emitRegistrationCode: (event) => emitEvent('mobile_registration_code', event),
154
154
  emitAccountTakeoverNotice: (event) => emitEvent('mobile_account_takeover_notice', event),
155
155
  emitGroupEvent: (event) => {
156
- emitEvent('group', event);
156
+ // Register the cache mutation before emitting so a handler that
157
+ // sends synchronously sees the fresh participants, not the stale ones.
157
158
  void messageDispatch.mutateGroupMetadataCacheFromGroupEvent(event).catch((error) => {
158
159
  logger.warn('failed to mutate group metadata cache from group event', {
159
160
  action: event.action,
@@ -162,6 +163,7 @@ function createIncomingNodeRuntime(input) {
162
163
  message: (0, primitives_1.toError)(error).message
163
164
  });
164
165
  });
166
+ emitEvent('group', event);
165
167
  },
166
168
  emitBusinessEvent: (event) => emitEvent('business', event),
167
169
  emitPictureEvent: (event) => emitEvent('picture', event),
@@ -2,9 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.WaAppStateMutationCoordinator = void 0;
4
4
  const utils_1 = require("../../appstate/utils");
5
- const _appstate_spec_1 = require("../../appstate-spec.js");
5
+ const _appstate_spec_1 = require("../../appstate-spec");
6
6
  const appstate_mutation_1 = require("../events/appstate-mutation");
7
- const _proto_1 = require("../../proto.js");
7
+ const _proto_1 = require("../../proto");
8
8
  const constants_1 = require("../../protocol/constants");
9
9
  const jid_1 = require("../../protocol/jid");
10
10
  const coercion_1 = require("../../util/coercion");
@@ -6,7 +6,7 @@ const context_info_1 = require("../../message/context-info");
6
6
  const addon_crypto_1 = require("../../message/crypto/addon-crypto");
7
7
  const content_1 = require("../../message/encode/content");
8
8
  const bot_1 = require("../../message/kinds/bot");
9
- const _proto_1 = require("../../proto.js");
9
+ const _proto_1 = require("../../proto");
10
10
  const bot_2 = require("../../protocol/bot");
11
11
  const constants_1 = require("../../protocol/constants");
12
12
  const jid_1 = require("../../protocol/jid");
@@ -7,7 +7,7 @@ const receipt_1 = require("../events/receipt");
7
7
  const addon_crypto_1 = require("../../message/crypto/addon-crypto");
8
8
  const content_1 = require("../../message/encode/content");
9
9
  const media_payload_1 = require("../../message/encode/media-payload");
10
- const _proto_1 = require("../../proto.js");
10
+ const _proto_1 = require("../../proto");
11
11
  const jid_1 = require("../../protocol/jid");
12
12
  const client_1 = require("../../transport/node/mex/client");
13
13
  const bytes_1 = require("../../util/bytes");
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.WaMessageDispatchCoordinator = void 0;
4
- const _crypto_1 = require("../../crypto/index.js");
4
+ const _crypto_1 = require("../../crypto");
5
5
  const primitives_1 = require("../../crypto/core/primitives");
6
6
  const PromiseDedup_1 = require("../../infra/perf/PromiseDedup");
7
- const _message_1 = require("../../message/index.js");
7
+ const _message_1 = require("../../message");
8
8
  const context_info_1 = require("../../message/context-info");
9
9
  const icdc_1 = require("../../message/crypto/icdc");
10
10
  const phash_1 = require("../../message/crypto/phash");
@@ -13,7 +13,7 @@ const content_1 = require("../../message/encode/content");
13
13
  const device_sent_1 = require("../../message/encode/device-sent");
14
14
  const padding_1 = require("../../message/encode/padding");
15
15
  const bot_1 = require("../../message/kinds/bot");
16
- const _proto_1 = require("../../proto.js");
16
+ const _proto_1 = require("../../proto");
17
17
  const constants_1 = require("../../protocol/constants");
18
18
  const jid_1 = require("../../protocol/jid");
19
19
  const binary_1 = require("../../transport/binary");
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.WaRetryCoordinator = void 0;
4
4
  const incoming_1 = require("../../message/primitives/incoming");
5
- const _proto_1 = require("../../proto.js");
5
+ const _proto_1 = require("../../proto");
6
6
  const constants_1 = require("../../protocol/constants");
7
7
  const jid_1 = require("../../protocol/jid");
8
8
  const constants_2 = require("../../retry/constants");
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createStatusCoordinator = createStatusCoordinator;
4
- const _proto_1 = require("../../proto.js");
4
+ const _proto_1 = require("../../proto");
5
5
  const defaults_1 = require("../../protocol/defaults");
6
6
  /** Builds a {@link WaStatusCoordinator} from its dependencies. */
7
7
  function createStatusCoordinator(options) {
@@ -53,11 +53,10 @@ function createStreamControlHandler(options) {
53
53
  const reason = constants_1.WA_DISCONNECT_REASONS.STREAM_ERROR_FORCE_LOGIN;
54
54
  stopCommsImmediately();
55
55
  await runStreamControlLifecycle(reason, async () => {
56
- logger.warn('received forced login stream error; starting login lifecycle', {
56
+ logger.warn('received forced login stream error; reconnecting, keeping credentials', {
57
57
  code
58
58
  });
59
- await disconnect(reason, true, code);
60
- await clearStoredCredentials();
59
+ await disconnect(reason, false, code);
61
60
  await restartBackendAfterStreamControl(reason);
62
61
  });
63
62
  };
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.parseAppStateMutationEvent = parseAppStateMutationEvent;
4
- const _appstate_spec_1 = require("../../appstate-spec.js");
4
+ const _appstate_spec_1 = require("../../appstate-spec");
5
5
  function parseAppStateMutationEvent(mutation) {
6
6
  const parts = parseIndexParts(mutation.index);
7
7
  if (!parts || parts.length === 0) {
@@ -4,7 +4,7 @@ exports.parseVerifiedNameNode = parseVerifiedNameNode;
4
4
  exports.parseBusinessProfileNode = parseBusinessProfileNode;
5
5
  exports.parseBusinessNotificationEvents = parseBusinessNotificationEvents;
6
6
  const incoming_1 = require("../events/incoming");
7
- const _proto_1 = require("../../proto.js");
7
+ const _proto_1 = require("../../proto");
8
8
  const constants_1 = require("../../protocol/constants");
9
9
  const nodes_1 = require("../../protocol/nodes");
10
10
  const helpers_1 = require("../../transport/node/helpers");
@@ -76,8 +76,8 @@ function parseWebpAnimation(data) {
76
76
  }
77
77
  return null;
78
78
  }
79
- const IMAGE_THUMB_MAX_EDGE = 320;
80
- const VIDEO_THUMB_MAX_EDGE = 48;
79
+ const IMAGE_THUMB_MAX_EDGE = 100;
80
+ const VIDEO_THUMB_MAX_EDGE = 100;
81
81
  const STICKER_THUMB_MAX_EDGE = 100;
82
82
  const EMPTY_PROCESSED = {};
83
83
  function isReadableStream(value) {
@@ -7,6 +7,7 @@ const primitives_1 = require("../../util/primitives");
7
7
  function createGroupMetadataCache(options) {
8
8
  const { groupMetadataStore, queryGroupMetadata, logger } = options;
9
9
  const dedup = new PromiseDedup_1.PromiseDedup();
10
+ const pendingMutations = new Map();
10
11
  const sanitizeParticipantUsers = (participants) => {
11
12
  const deduped = new Set();
12
13
  for (const participant of participants) {
@@ -109,14 +110,9 @@ function createGroupMetadataCache(options) {
109
110
  const extractParticipantUsersFromGroupEvent = (event) => {
110
111
  const candidates = [];
111
112
  for (const participant of event.participants ?? []) {
112
- if (participant.jid) {
113
- candidates.push(participant.jid);
114
- }
115
- if (participant.lidJid) {
116
- candidates.push(participant.lidJid);
117
- }
118
- if (participant.phoneJid) {
119
- candidates.push(participant.phoneJid);
113
+ const canonical = participant.jid ?? participant.lidJid ?? participant.phoneJid;
114
+ if (canonical) {
115
+ candidates.push(canonical);
120
116
  }
121
117
  }
122
118
  return sanitizeParticipantUsers(candidates);
@@ -133,6 +129,7 @@ function createGroupMetadataCache(options) {
133
129
  return participants;
134
130
  });
135
131
  const resolveParticipantUsers = (groupJid) => dedup.run(`resolve:${groupJid}`, async () => {
132
+ await pendingMutations.get(groupJid)?.catch(() => undefined);
136
133
  const cached = await groupMetadataStore.getGroupMetadata(groupJid);
137
134
  if (cached && cached.participants.length > 0) {
138
135
  return sanitizeParticipantUsers(cached.participants);
@@ -152,7 +149,7 @@ function createGroupMetadataCache(options) {
152
149
  const refreshed = await groupMetadataStore.getGroupMetadata(groupJid);
153
150
  return refreshed?.ephemeral ?? null;
154
151
  };
155
- const mutateFromGroupEvent = async (event) => {
152
+ const applyGroupEvent = async (event) => {
156
153
  const groupJid = resolveGroupJidForGroupCacheEvent(event);
157
154
  if (!groupJid) {
158
155
  return;
@@ -221,6 +218,20 @@ function createGroupMetadataCache(options) {
221
218
  await replaceParticipantUsersInCache(groupJid, cachedWithSanitized, authorUsers, participantUsers);
222
219
  }
223
220
  };
221
+ const mutateFromGroupEvent = (event) => {
222
+ const groupJid = resolveGroupJidForGroupCacheEvent(event);
223
+ if (!groupJid) {
224
+ return applyGroupEvent(event);
225
+ }
226
+ const prev = pendingMutations.get(groupJid) ?? Promise.resolve();
227
+ const next = prev.then(() => applyGroupEvent(event), () => applyGroupEvent(event));
228
+ pendingMutations.set(groupJid, next);
229
+ return next.finally(() => {
230
+ if (pendingMutations.get(groupJid) === next) {
231
+ pendingMutations.delete(groupJid);
232
+ }
233
+ });
234
+ };
224
235
  return {
225
236
  resolveParticipantUsers,
226
237
  refreshParticipantUsers,
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createAppStateSyncKeyProtocol = createAppStateSyncKeyProtocol;
4
- const _proto_1 = require("../../proto.js");
4
+ const _proto_1 = require("../../proto");
5
5
  const jid_1 = require("../../protocol/jid");
6
6
  const bytes_1 = require("../../util/bytes");
7
7
  function createAppStateSyncKeyProtocol(options) {
@@ -6,7 +6,7 @@ const media_1 = require("../media");
6
6
  const constants_1 = require("../../media/constants");
7
7
  const WaMediaCrypto_1 = require("../../media/crypto/WaMediaCrypto");
8
8
  const detect_1 = require("../../message/addons/link-preview/detect");
9
- const _proto_1 = require("../../proto.js");
9
+ const _proto_1 = require("../../proto");
10
10
  const primitives_1 = require("../../util/primitives");
11
11
  const INLINE_THUMBNAIL_MAX_BYTES = 64 * 1024;
12
12
  async function resolveLinkPreview(text, perMessage, deps) {
@@ -5,7 +5,7 @@ exports.getMediaConn = getMediaConn;
5
5
  const node_fs_1 = require("node:fs");
6
6
  const node_stream_1 = require("node:stream");
7
7
  const media_1 = require("../media");
8
- const _crypto_1 = require("../../crypto/index.js");
8
+ const _crypto_1 = require("../../crypto");
9
9
  const constants_1 = require("../../media/constants");
10
10
  const WaMediaCrypto_1 = require("../../media/crypto/WaMediaCrypto");
11
11
  const sticker_pack_1 = require("../../media/sticker/sticker-pack");
@@ -15,7 +15,7 @@ const addon_crypto_1 = require("../../message/crypto/addon-crypto");
15
15
  const use_case_secret_1 = require("../../message/crypto/use-case-secret");
16
16
  const content_1 = require("../../message/encode/content");
17
17
  const sticker_pack_2 = require("../../message/kinds/sticker-pack");
18
- const _proto_1 = require("../../proto.js");
18
+ const _proto_1 = require("../../proto");
19
19
  const constants_2 = require("../../protocol/constants");
20
20
  const jid_1 = require("../../protocol/jid");
21
21
  const media_2 = require("../../transport/node/builders/media");
@@ -8,7 +8,7 @@ const sticker_pack_1 = require("../../media/sticker/sticker-pack");
8
8
  const context_info_1 = require("../../message/context-info");
9
9
  const content_1 = require("../../message/encode/content");
10
10
  const sticker_pack_2 = require("../../message/kinds/sticker-pack");
11
- const _proto_1 = require("../../proto.js");
11
+ const _proto_1 = require("../../proto");
12
12
  const message_1 = require("../../protocol/message");
13
13
  const bytes_1 = require("../../util/bytes");
14
14
  async function uploadNewsletterMedia(options, input) {
@@ -4,7 +4,7 @@ exports.runHistorySyncNotification = runHistorySyncNotification;
4
4
  exports.processHistorySyncNotification = processHistorySyncNotification;
5
5
  const node_util_1 = require("node:util");
6
6
  const node_zlib_1 = require("node:zlib");
7
- const _proto_1 = require("../../proto.js");
7
+ const _proto_1 = require("../../proto");
8
8
  const jid_1 = require("../../protocol/jid");
9
9
  const bytes_1 = require("../../util/bytes");
10
10
  const primitives_1 = require("../../util/primitives");
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.persistIncomingMailboxEntities = persistIncomingMailboxEntities;
4
4
  const content_1 = require("../../message/encode/content");
5
- const _proto_1 = require("../../proto.js");
5
+ const _proto_1 = require("../../proto");
6
6
  const jid_1 = require("../../protocol/jid");
7
7
  const primitives_1 = require("../../util/primitives");
8
8
  function pairLidPn(a, b) {
@@ -32,7 +32,7 @@ const SYNC_RELATED_PROTOCOL_TYPES = new Set([
32
32
  *
33
33
  * @example
34
34
  * ```ts
35
- * import { createPinoLogger, createStore, WaClient } from '../index.js'
35
+ * import { createPinoLogger, createStore, WaClient } from '..'
36
36
  * import { createSqliteStore } from '@zapo-js/store-sqlite'
37
37
  *
38
38
  * const store = createStore({
@@ -149,7 +149,8 @@ function createIncomingNodeRuntime(input) {
149
149
  emitRegistrationCode: (event) => emitEvent('mobile_registration_code', event),
150
150
  emitAccountTakeoverNotice: (event) => emitEvent('mobile_account_takeover_notice', event),
151
151
  emitGroupEvent: (event) => {
152
- emitEvent('group', event);
152
+ // Register the cache mutation before emitting so a handler that
153
+ // sends synchronously sees the fresh participants, not the stale ones.
153
154
  void messageDispatch.mutateGroupMetadataCacheFromGroupEvent(event).catch((error) => {
154
155
  logger.warn('failed to mutate group metadata cache from group event', {
155
156
  action: event.action,
@@ -158,6 +159,7 @@ function createIncomingNodeRuntime(input) {
158
159
  message: toError(error).message
159
160
  });
160
161
  });
162
+ emitEvent('group', event);
161
163
  },
162
164
  emitBusinessEvent: (event) => emitEvent('business', event),
163
165
  emitPictureEvent: (event) => emitEvent('picture', event),
@@ -50,11 +50,10 @@ export function createStreamControlHandler(options) {
50
50
  const reason = WA_DISCONNECT_REASONS.STREAM_ERROR_FORCE_LOGIN;
51
51
  stopCommsImmediately();
52
52
  await runStreamControlLifecycle(reason, async () => {
53
- logger.warn('received forced login stream error; starting login lifecycle', {
53
+ logger.warn('received forced login stream error; reconnecting, keeping credentials', {
54
54
  code
55
55
  });
56
- await disconnect(reason, true, code);
57
- await clearStoredCredentials();
56
+ await disconnect(reason, false, code);
58
57
  await restartBackendAfterStreamControl(reason);
59
58
  });
60
59
  };
@@ -60,8 +60,8 @@ export function parseWebpAnimation(data) {
60
60
  }
61
61
  return null;
62
62
  }
63
- const IMAGE_THUMB_MAX_EDGE = 320;
64
- const VIDEO_THUMB_MAX_EDGE = 48;
63
+ const IMAGE_THUMB_MAX_EDGE = 100;
64
+ const VIDEO_THUMB_MAX_EDGE = 100;
65
65
  const STICKER_THUMB_MAX_EDGE = 100;
66
66
  const EMPTY_PROCESSED = {};
67
67
  export function isReadableStream(value) {
@@ -4,6 +4,7 @@ import { toError } from '../../util/primitives.js';
4
4
  export function createGroupMetadataCache(options) {
5
5
  const { groupMetadataStore, queryGroupMetadata, logger } = options;
6
6
  const dedup = new PromiseDedup();
7
+ const pendingMutations = new Map();
7
8
  const sanitizeParticipantUsers = (participants) => {
8
9
  const deduped = new Set();
9
10
  for (const participant of participants) {
@@ -106,14 +107,9 @@ export function createGroupMetadataCache(options) {
106
107
  const extractParticipantUsersFromGroupEvent = (event) => {
107
108
  const candidates = [];
108
109
  for (const participant of event.participants ?? []) {
109
- if (participant.jid) {
110
- candidates.push(participant.jid);
111
- }
112
- if (participant.lidJid) {
113
- candidates.push(participant.lidJid);
114
- }
115
- if (participant.phoneJid) {
116
- candidates.push(participant.phoneJid);
110
+ const canonical = participant.jid ?? participant.lidJid ?? participant.phoneJid;
111
+ if (canonical) {
112
+ candidates.push(canonical);
117
113
  }
118
114
  }
119
115
  return sanitizeParticipantUsers(candidates);
@@ -130,6 +126,7 @@ export function createGroupMetadataCache(options) {
130
126
  return participants;
131
127
  });
132
128
  const resolveParticipantUsers = (groupJid) => dedup.run(`resolve:${groupJid}`, async () => {
129
+ await pendingMutations.get(groupJid)?.catch(() => undefined);
133
130
  const cached = await groupMetadataStore.getGroupMetadata(groupJid);
134
131
  if (cached && cached.participants.length > 0) {
135
132
  return sanitizeParticipantUsers(cached.participants);
@@ -149,7 +146,7 @@ export function createGroupMetadataCache(options) {
149
146
  const refreshed = await groupMetadataStore.getGroupMetadata(groupJid);
150
147
  return refreshed?.ephemeral ?? null;
151
148
  };
152
- const mutateFromGroupEvent = async (event) => {
149
+ const applyGroupEvent = async (event) => {
153
150
  const groupJid = resolveGroupJidForGroupCacheEvent(event);
154
151
  if (!groupJid) {
155
152
  return;
@@ -218,6 +215,20 @@ export function createGroupMetadataCache(options) {
218
215
  await replaceParticipantUsersInCache(groupJid, cachedWithSanitized, authorUsers, participantUsers);
219
216
  }
220
217
  };
218
+ const mutateFromGroupEvent = (event) => {
219
+ const groupJid = resolveGroupJidForGroupCacheEvent(event);
220
+ if (!groupJid) {
221
+ return applyGroupEvent(event);
222
+ }
223
+ const prev = pendingMutations.get(groupJid) ?? Promise.resolve();
224
+ const next = prev.then(() => applyGroupEvent(event), () => applyGroupEvent(event));
225
+ pendingMutations.set(groupJid, next);
226
+ return next.finally(() => {
227
+ if (pendingMutations.get(groupJid) === next) {
228
+ pendingMutations.delete(groupJid);
229
+ }
230
+ });
231
+ };
221
232
  return {
222
233
  resolveParticipantUsers,
223
234
  refreshParticipantUsers,
@@ -231,7 +231,9 @@ export class SignalDeviceSyncApi {
231
231
  {
232
232
  tag: WA_NODE_TAGS.CONTACT,
233
233
  attrs: {},
234
- content: splitJid(jid).user
234
+ // E.164 '+': without it the server normalizes under the
235
+ // account's country and resolves the wrong contact.
236
+ content: `+${splitJid(jid).user}`
235
237
  }
236
238
  ]
237
239
  };
@@ -13,8 +13,9 @@ export async function createAndStoreInitialKeys(store, preKeyStore) {
13
13
  // Keep writes ordered so partial commit failures don't leave split registration bootstrap state.
14
14
  await store.setRegistrationInfo(registrationInfo);
15
15
  await store.setSignedPreKey(signedPreKey);
16
- // eslint-disable-next-line @typescript-eslint/require-await
17
- await preKeyStore.getOrGenSinglePreKey(async () => firstPreKey);
16
+ // putPreKey (idempotent), not getOrGenSinglePreKey: a fixed-keyId generator
17
+ // collides with a stale keyId 1 and would spin forever inside getOrGen*.
18
+ await preKeyStore.putPreKey(firstPreKey);
18
19
  return {
19
20
  registrationInfo,
20
21
  signedPreKey,
@@ -3,6 +3,9 @@ import { StoreLock } from '../../infra/perf/StoreLock.js';
3
3
  const WA_PREKEY_KEY = 'prekey:prekeys';
4
4
  const WA_PREKEY_SERVER_KEY = 'prekey:serverHasPreKeys';
5
5
  const WA_PREKEY_CLEAR_KEY = 'prekey:clear';
6
+ // consume is independent of the counter/generation and atomic in the store, so it
7
+ // uses a per-id key instead of WA_PREKEY_KEY: no queueing behind generation/upload.
8
+ const WA_PREKEY_CONSUME_PREFIX = 'prekey:consume:';
6
9
  export function withPreKeyLock(store) {
7
10
  const lock = new StoreLock();
8
11
  const gate = new SharedExclusiveGate();
@@ -12,7 +15,7 @@ export function withPreKeyLock(store) {
12
15
  getOrGenPreKeys: (count, generator) => gate.runShared(() => lock.run(WA_PREKEY_KEY, () => store.getOrGenPreKeys(count, generator))),
13
16
  getPreKeyById: (keyId) => gate.runShared(() => store.getPreKeyById(keyId)),
14
17
  getPreKeysById: (keyIds) => gate.runShared(() => store.getPreKeysById(keyIds)),
15
- consumePreKeyById: (keyId) => gate.runShared(() => lock.run(WA_PREKEY_KEY, () => store.consumePreKeyById(keyId))),
18
+ consumePreKeyById: (keyId) => gate.runShared(() => lock.run(`${WA_PREKEY_CONSUME_PREFIX}${keyId}`, () => store.consumePreKeyById(keyId))),
16
19
  getOrGenSinglePreKey: (generator) => gate.runShared(() => lock.run(WA_PREKEY_KEY, () => store.getOrGenSinglePreKey(generator))),
17
20
  markKeyAsUploaded: (keyId) => gate.runShared(() => lock.run(WA_PREKEY_KEY, () => store.markKeyAsUploaded(keyId))),
18
21
  setServerHasPreKeys: (value) => gate.runShared(() => lock.run(WA_PREKEY_SERVER_KEY, () => store.setServerHasPreKeys(value))),
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.WA_DIRTY_PROTOCOLS = exports.WA_DEFAULTS = exports.WA_COMPANION_PLATFORM_IDS = exports.WA_BUSINESS_HOURS_MODES = exports.WA_BUSINESS_HOURS_DAYS = 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.resolveMessageTarget = exports.getContentType = exports.parseUsyncResultEnvelope = exports.WaClient = void 0;
4
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 = void 0;
5
- var _client_1 = require("./client/index.js");
5
+ var _client_1 = require("./client");
6
6
  Object.defineProperty(exports, "WaClient", { enumerable: true, get: function () { return _client_1.WaClient; } });
7
7
  var usync_1 = require("./transport/node/builders/usync");
8
8
  Object.defineProperty(exports, "parseUsyncResultEnvelope", { enumerable: true, get: function () { return usync_1.parseUsyncResultEnvelope; } });
@@ -18,12 +18,12 @@ Object.defineProperty(exports, "PinoLogger", { enumerable: true, get: function (
18
18
  Object.defineProperty(exports, "createPinoLogger", { enumerable: true, get: function () { return PinoLogger_1.createPinoLogger; } });
19
19
  var types_1 = require("./infra/log/types");
20
20
  Object.defineProperty(exports, "createNoopLogger", { enumerable: true, get: function () { return types_1.createNoopLogger; } });
21
- var _store_1 = require("./store/index.js");
21
+ var _store_1 = require("./store");
22
22
  Object.defineProperty(exports, "createStore", { enumerable: true, get: function () { return _store_1.createStore; } });
23
23
  Object.defineProperty(exports, "WaAuthMemoryStore", { enumerable: true, get: function () { return _store_1.WaAuthMemoryStore; } });
24
24
  var async_1 = require("./util/async");
25
25
  Object.defineProperty(exports, "delay", { enumerable: true, get: function () { return async_1.delay; } });
26
- var _protocol_1 = require("./protocol/index.js");
26
+ var _protocol_1 = require("./protocol");
27
27
  Object.defineProperty(exports, "buildDeviceJid", { enumerable: true, get: function () { return _protocol_1.buildDeviceJid; } });
28
28
  Object.defineProperty(exports, "canonicalizeSignalJid", { enumerable: true, get: function () { return _protocol_1.canonicalizeSignalJid; } });
29
29
  Object.defineProperty(exports, "canonicalizeSignalServer", { enumerable: true, get: function () { return _protocol_1.canonicalizeSignalServer; } });
@@ -84,5 +84,5 @@ Object.defineProperty(exports, "WA_PRIVACY_SETTING_TO_CATEGORY", { enumerable: t
84
84
  Object.defineProperty(exports, "WA_PRIVACY_TAGS", { enumerable: true, get: function () { return _protocol_1.WA_PRIVACY_TAGS; } });
85
85
  Object.defineProperty(exports, "WA_PRIVACY_VALUES", { enumerable: true, get: function () { return _protocol_1.WA_PRIVACY_VALUES; } });
86
86
  Object.defineProperty(exports, "WA_XMLNS", { enumerable: true, get: function () { return _protocol_1.WA_XMLNS; } });
87
- var _proto_1 = require("./proto.js");
87
+ var _proto_1 = require("./proto");
88
88
  Object.defineProperty(exports, "proto", { enumerable: true, get: function () { return _proto_1.proto; } });
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createDefaultLinkPreviewFetcher = createDefaultLinkPreviewFetcher;
4
- const _proto_1 = require("../../../proto.js");
4
+ const _proto_1 = require("../../../proto");
5
5
  const proxy_1 = require("../../../transport/proxy");
6
6
  const bytes_1 = require("../../../util/bytes");
7
7
  const primitives_1 = require("../../../util/primitives");
@@ -8,10 +8,10 @@ exports.identifyEncryptedAddon = identifyEncryptedAddon;
8
8
  exports.decodeAddonPlaintext = decodeAddonPlaintext;
9
9
  exports.resolveParentMessageSecret = resolveParentMessageSecret;
10
10
  exports.resolvePollOptionNames = resolvePollOptionNames;
11
- const _crypto_1 = require("../../crypto/index.js");
11
+ const _crypto_1 = require("../../crypto");
12
12
  const use_case_secret_1 = require("../crypto/use-case-secret");
13
13
  const content_1 = require("../encode/content");
14
- const _proto_1 = require("../../proto.js");
14
+ const _proto_1 = require("../../proto");
15
15
  const bytes_1 = require("../../util/bytes");
16
16
  const WA_ADDON_ENCRYPTION_NONCE_BYTES = 12;
17
17
  /** Returns `true` when an addon kind binds its AES-GCM ciphertext to additional data (polls + event responses). */