@oxidezap/baileyrs 0.0.7

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 (173) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +490 -0
  3. package/WAProto/index.d.ts +13875 -0
  4. package/WAProto/index.js +175 -0
  5. package/lib/Defaults/index.d.ts +9 -0
  6. package/lib/Defaults/index.d.ts.map +1 -0
  7. package/lib/Defaults/index.js +32 -0
  8. package/lib/Defaults/index.js.map +1 -0
  9. package/lib/Socket/blocking.d.ts +6 -0
  10. package/lib/Socket/blocking.d.ts.map +1 -0
  11. package/lib/Socket/blocking.js +9 -0
  12. package/lib/Socket/blocking.js.map +1 -0
  13. package/lib/Socket/chat-actions.d.ts +32 -0
  14. package/lib/Socket/chat-actions.d.ts.map +1 -0
  15. package/lib/Socket/chat-actions.js +78 -0
  16. package/lib/Socket/chat-actions.js.map +1 -0
  17. package/lib/Socket/contacts.d.ts +10 -0
  18. package/lib/Socket/contacts.d.ts.map +1 -0
  19. package/lib/Socket/contacts.js +21 -0
  20. package/lib/Socket/contacts.js.map +1 -0
  21. package/lib/Socket/events.d.ts +10 -0
  22. package/lib/Socket/events.d.ts.map +1 -0
  23. package/lib/Socket/events.js +293 -0
  24. package/lib/Socket/events.js.map +1 -0
  25. package/lib/Socket/groups.d.ts +28 -0
  26. package/lib/Socket/groups.d.ts.map +1 -0
  27. package/lib/Socket/groups.js +90 -0
  28. package/lib/Socket/groups.js.map +1 -0
  29. package/lib/Socket/index.d.ts +202 -0
  30. package/lib/Socket/index.d.ts.map +1 -0
  31. package/lib/Socket/index.js +378 -0
  32. package/lib/Socket/index.js.map +1 -0
  33. package/lib/Socket/messages.d.ts +42 -0
  34. package/lib/Socket/messages.d.ts.map +1 -0
  35. package/lib/Socket/messages.js +172 -0
  36. package/lib/Socket/messages.js.map +1 -0
  37. package/lib/Socket/newsletter.d.ts +9 -0
  38. package/lib/Socket/newsletter.d.ts.map +1 -0
  39. package/lib/Socket/newsletter.js +18 -0
  40. package/lib/Socket/newsletter.js.map +1 -0
  41. package/lib/Socket/presence.d.ts +7 -0
  42. package/lib/Socket/presence.d.ts.map +1 -0
  43. package/lib/Socket/presence.js +12 -0
  44. package/lib/Socket/presence.js.map +1 -0
  45. package/lib/Socket/profile.d.ts +14 -0
  46. package/lib/Socket/profile.d.ts.map +1 -0
  47. package/lib/Socket/profile.js +36 -0
  48. package/lib/Socket/profile.js.map +1 -0
  49. package/lib/Socket/transport.d.ts +12 -0
  50. package/lib/Socket/transport.d.ts.map +1 -0
  51. package/lib/Socket/transport.js +90 -0
  52. package/lib/Socket/transport.js.map +1 -0
  53. package/lib/Socket/types.d.ts +30 -0
  54. package/lib/Socket/types.d.ts.map +1 -0
  55. package/lib/Socket/types.js +3 -0
  56. package/lib/Socket/types.js.map +1 -0
  57. package/lib/Types/Auth.d.ts +144 -0
  58. package/lib/Types/Auth.d.ts.map +1 -0
  59. package/lib/Types/Auth.js +2 -0
  60. package/lib/Types/Auth.js.map +1 -0
  61. package/lib/Types/BinaryNode.d.ts +15 -0
  62. package/lib/Types/BinaryNode.d.ts.map +1 -0
  63. package/lib/Types/BinaryNode.js +2 -0
  64. package/lib/Types/BinaryNode.js.map +1 -0
  65. package/lib/Types/Bussines.d.ts +25 -0
  66. package/lib/Types/Bussines.d.ts.map +1 -0
  67. package/lib/Types/Bussines.js +2 -0
  68. package/lib/Types/Bussines.js.map +1 -0
  69. package/lib/Types/Call.d.ts +15 -0
  70. package/lib/Types/Call.d.ts.map +1 -0
  71. package/lib/Types/Call.js +2 -0
  72. package/lib/Types/Call.js.map +1 -0
  73. package/lib/Types/Chat.d.ts +123 -0
  74. package/lib/Types/Chat.d.ts.map +1 -0
  75. package/lib/Types/Chat.js +8 -0
  76. package/lib/Types/Chat.js.map +1 -0
  77. package/lib/Types/Contact.d.ts +24 -0
  78. package/lib/Types/Contact.d.ts.map +1 -0
  79. package/lib/Types/Contact.js +2 -0
  80. package/lib/Types/Contact.js.map +1 -0
  81. package/lib/Types/Events.d.ts +238 -0
  82. package/lib/Types/Events.d.ts.map +1 -0
  83. package/lib/Types/Events.js +2 -0
  84. package/lib/Types/Events.js.map +1 -0
  85. package/lib/Types/GroupMetadata.d.ts +67 -0
  86. package/lib/Types/GroupMetadata.d.ts.map +1 -0
  87. package/lib/Types/GroupMetadata.js +2 -0
  88. package/lib/Types/GroupMetadata.js.map +1 -0
  89. package/lib/Types/Label.d.ts +47 -0
  90. package/lib/Types/Label.d.ts.map +1 -0
  91. package/lib/Types/Label.js +25 -0
  92. package/lib/Types/Label.js.map +1 -0
  93. package/lib/Types/LabelAssociation.d.ts +30 -0
  94. package/lib/Types/LabelAssociation.d.ts.map +1 -0
  95. package/lib/Types/LabelAssociation.js +7 -0
  96. package/lib/Types/LabelAssociation.js.map +1 -0
  97. package/lib/Types/Message.d.ts +298 -0
  98. package/lib/Types/Message.d.ts.map +1 -0
  99. package/lib/Types/Message.js +12 -0
  100. package/lib/Types/Message.js.map +1 -0
  101. package/lib/Types/Newsletter.d.ts +98 -0
  102. package/lib/Types/Newsletter.d.ts.map +1 -0
  103. package/lib/Types/Newsletter.js +31 -0
  104. package/lib/Types/Newsletter.js.map +1 -0
  105. package/lib/Types/Socket.d.ts +54 -0
  106. package/lib/Types/Socket.d.ts.map +1 -0
  107. package/lib/Types/Socket.js +2 -0
  108. package/lib/Types/Socket.js.map +1 -0
  109. package/lib/Types/State.d.ts +29 -0
  110. package/lib/Types/State.d.ts.map +1 -0
  111. package/lib/Types/State.js +2 -0
  112. package/lib/Types/State.js.map +1 -0
  113. package/lib/Types/index.d.ts +60 -0
  114. package/lib/Types/index.d.ts.map +1 -0
  115. package/lib/Types/index.js +25 -0
  116. package/lib/Types/index.js.map +1 -0
  117. package/lib/Utils/browser-utils.d.ts +3 -0
  118. package/lib/Utils/browser-utils.d.ts.map +1 -0
  119. package/lib/Utils/browser-utils.js +22 -0
  120. package/lib/Utils/browser-utils.js.map +1 -0
  121. package/lib/Utils/event-buffer.d.ts +7 -0
  122. package/lib/Utils/event-buffer.d.ts.map +1 -0
  123. package/lib/Utils/event-buffer.js +42 -0
  124. package/lib/Utils/event-buffer.js.map +1 -0
  125. package/lib/Utils/generics.d.ts +13 -0
  126. package/lib/Utils/generics.d.ts.map +1 -0
  127. package/lib/Utils/generics.js +40 -0
  128. package/lib/Utils/generics.js.map +1 -0
  129. package/lib/Utils/index.d.ts +10 -0
  130. package/lib/Utils/index.d.ts.map +1 -0
  131. package/lib/Utils/index.js +10 -0
  132. package/lib/Utils/index.js.map +1 -0
  133. package/lib/Utils/logger.d.ts +13 -0
  134. package/lib/Utils/logger.d.ts.map +1 -0
  135. package/lib/Utils/logger.js +3 -0
  136. package/lib/Utils/logger.js.map +1 -0
  137. package/lib/Utils/messages-media.d.ts +51 -0
  138. package/lib/Utils/messages-media.d.ts.map +1 -0
  139. package/lib/Utils/messages-media.js +223 -0
  140. package/lib/Utils/messages-media.js.map +1 -0
  141. package/lib/Utils/messages.d.ts +88 -0
  142. package/lib/Utils/messages.d.ts.map +1 -0
  143. package/lib/Utils/messages.js +730 -0
  144. package/lib/Utils/messages.js.map +1 -0
  145. package/lib/Utils/use-bridge-store.d.ts +13 -0
  146. package/lib/Utils/use-bridge-store.d.ts.map +1 -0
  147. package/lib/Utils/use-bridge-store.js +124 -0
  148. package/lib/Utils/use-bridge-store.js.map +1 -0
  149. package/lib/Utils/use-memory-store.d.ts +9 -0
  150. package/lib/Utils/use-memory-store.d.ts.map +1 -0
  151. package/lib/Utils/use-memory-store.js +23 -0
  152. package/lib/Utils/use-memory-store.js.map +1 -0
  153. package/lib/Utils/use-multi-file-auth-state.d.ts +13 -0
  154. package/lib/Utils/use-multi-file-auth-state.d.ts.map +1 -0
  155. package/lib/Utils/use-multi-file-auth-state.js +26 -0
  156. package/lib/Utils/use-multi-file-auth-state.js.map +1 -0
  157. package/lib/Utils/wrap-legacy-store.d.ts +36 -0
  158. package/lib/Utils/wrap-legacy-store.d.ts.map +1 -0
  159. package/lib/Utils/wrap-legacy-store.js +708 -0
  160. package/lib/Utils/wrap-legacy-store.js.map +1 -0
  161. package/lib/WABinary/index.d.ts +2 -0
  162. package/lib/WABinary/index.d.ts.map +1 -0
  163. package/lib/WABinary/index.js +2 -0
  164. package/lib/WABinary/index.js.map +1 -0
  165. package/lib/WABinary/jid-utils.d.ts +20 -0
  166. package/lib/WABinary/jid-utils.d.ts.map +1 -0
  167. package/lib/WABinary/jid-utils.js +51 -0
  168. package/lib/WABinary/jid-utils.js.map +1 -0
  169. package/lib/index.d.ts +10 -0
  170. package/lib/index.d.ts.map +1 -0
  171. package/lib/index.js +9 -0
  172. package/lib/index.js.map +1 -0
  173. package/package.json +98 -0
@@ -0,0 +1,708 @@
1
+ /**
2
+ * Wraps any upstream Baileys AuthenticationState as bridge-compatible
3
+ * JsStoreCallbacks. Users keep their existing custom stores (MySQL,
4
+ * MongoDB, Redis, etc.) — zero migration needed.
5
+ *
6
+ * ```typescript
7
+ * const { state, saveCreds } = await useMongoAuthState(db)
8
+ * const sock = makeWASocket({
9
+ * auth: { store: await wrapLegacyStore(state, saveCreds) }
10
+ * })
11
+ * ```
12
+ */
13
+ import { Buffer } from 'node:buffer';
14
+ import { mkdir, readFile, stat, unlink, writeFile } from 'node:fs/promises';
15
+ import { join } from 'node:path';
16
+ import { proto } from '../../WAProto/index.js';
17
+ const protoLookup = proto;
18
+ const ADVSignedDeviceIdentity = protoLookup.ADVSignedDeviceIdentity ?? protoLookup.AdvSignedDeviceIdentity;
19
+ function warn(msg, err) {
20
+ if (_warnFn)
21
+ _warnFn(msg, err);
22
+ else
23
+ console.warn(`[wrapLegacyStore] ${msg}`, err ?? '');
24
+ }
25
+ let _warnFn;
26
+ // ---- Store routing ----
27
+ // Bridge store name → upstream store type name for keys.get/set.
28
+ // ALL data goes through the user-provided keys interface — no separate files.
29
+ const STORE_MAP = {
30
+ // Signal protocol (binary passthrough with write-through cache)
31
+ identity: 'identity-key',
32
+ session: 'session',
33
+ sender_key: 'sender-key',
34
+ // Upstream Baileys types (with format converters)
35
+ prekey: 'pre-key',
36
+ sync_key: 'app-state-sync-key',
37
+ sync_version: 'app-state-sync-version',
38
+ tc_token: 'tctoken',
39
+ device_list: 'device-list',
40
+ // Bridge-only (stored as raw Buffers with their own type prefix)
41
+ lid_mapping: 'lid-mapping',
42
+ signed_prekey: 'bridge-signed-prekey',
43
+ sender_key_devices: 'bridge-sender-key-devices',
44
+ base_key: 'bridge-base-key',
45
+ sent_message: 'bridge-sent-message',
46
+ mutation_mac: 'bridge-mutation-mac',
47
+ meta: 'bridge-meta'
48
+ };
49
+ // Stores where bridge data is passthrough binary (no conversion)
50
+ const BINARY_STORES = new Set(['identity', 'session', 'sender_key']);
51
+ // Bridge-only stores — raw binary persisted through keys interface
52
+ const BRIDGE_ONLY_STORES = new Set([
53
+ 'lid_mapping',
54
+ 'signed_prekey',
55
+ 'sender_key_devices',
56
+ 'base_key',
57
+ 'sent_message',
58
+ 'mutation_mac',
59
+ 'meta'
60
+ ]);
61
+ /** Reconstruct a JID string from the bridge's serialized Jid object.
62
+ * Format: "user:device@server" (device omitted when 0). */
63
+ function bridgeJidToString(j) {
64
+ if (!j?.user || !j?.server)
65
+ return null;
66
+ const device = j.device ?? 0;
67
+ return `${j.user}${device > 0 ? ':' + device : ''}@${j.server}`;
68
+ }
69
+ // ---- Helpers ----
70
+ const toJson = (v) => new TextEncoder().encode(JSON.stringify(v));
71
+ const fromJson = (b) => JSON.parse(new TextDecoder().decode(b));
72
+ const toBuf = (v) => v instanceof Uint8Array ? v : Buffer.isBuffer(v) ? new Uint8Array(v) : null;
73
+ /** Convert Buffer/Uint8Array to a plain number[] for JSON serialization.
74
+ * Matches Rust's serde_json Vec<u8> format: [byte, byte, ...] */
75
+ const bufToNumArray = (v) => Array.from(Buffer.from(v));
76
+ /** Bridge uses hex-encoded key IDs for sync_key; upstream uses base64. Convert hex→base64. */
77
+ const hexToBase64 = (hex) => Buffer.from(hex, 'hex').toString('base64');
78
+ const converters = {
79
+ prekey: {
80
+ toBridge(key, value) {
81
+ if (value instanceof Uint8Array || Buffer.isBuffer(value))
82
+ return toBuf(value);
83
+ const kp = value;
84
+ return kp.private && kp.public
85
+ ? encodePreKeyRecord(parseInt(key) || 0, Buffer.from(kp.public), Buffer.from(kp.private))
86
+ : null;
87
+ },
88
+ fromBridge(_key, value) {
89
+ return decodePreKeyRecord(value) ?? Buffer.from(value);
90
+ }
91
+ },
92
+ sync_key: {
93
+ toBridge(_key, value) {
94
+ if (value instanceof Uint8Array || Buffer.isBuffer(value))
95
+ return toBuf(value);
96
+ // Rust AppStateSyncKey: key_data=Vec<u8>, fingerprint=Vec<u8> (protobuf-encoded),
97
+ // timestamp=i64. serde_json serializes Vec<u8> as array of numbers.
98
+ const msg = value;
99
+ const fingerprintBytes = msg.fingerprint
100
+ ? proto.Message.AppStateSyncKeyFingerprint.encode(proto.Message.AppStateSyncKeyFingerprint.create(msg.fingerprint)).finish()
101
+ : null;
102
+ return toJson({
103
+ key_data: msg.keyData ? bufToNumArray(Buffer.from(msg.keyData)) : [],
104
+ fingerprint: fingerprintBytes ? bufToNumArray(fingerprintBytes) : [],
105
+ timestamp: Number(msg.timestamp ?? 0)
106
+ });
107
+ },
108
+ fromBridge(_key, value) {
109
+ try {
110
+ const j = fromJson(value);
111
+ const keyData = Array.isArray(j.key_data) ? Buffer.from(j.key_data) : undefined;
112
+ const fingerprint = Array.isArray(j.fingerprint) && j.fingerprint.length > 0
113
+ ? proto.Message.AppStateSyncKeyFingerprint.decode(Buffer.from(j.fingerprint))
114
+ : undefined;
115
+ return proto.Message.AppStateSyncKeyData.fromObject({
116
+ keyData,
117
+ fingerprint,
118
+ timestamp: j.timestamp ?? 0
119
+ });
120
+ }
121
+ catch {
122
+ return Buffer.from(value);
123
+ }
124
+ }
125
+ },
126
+ sync_version: {
127
+ toBridge(_key, value) {
128
+ if (value instanceof Uint8Array || Buffer.isBuffer(value))
129
+ return toBuf(value);
130
+ // Rust HashState: version=u64, hash=[u8;128] (BigArray → number array),
131
+ // index_value_map=HashMap<String, Vec<u8>> (snake_case, plain byte arrays).
132
+ // Upstream LTHashState: hash=Buffer, indexValueMap={[k]: {valueMac: Buffer}} (camelCase, wrapped).
133
+ const v = value;
134
+ const indexValueMap = {};
135
+ if (v.indexValueMap) {
136
+ for (const [k, entry] of Object.entries(v.indexValueMap)) {
137
+ indexValueMap[k] = bufToNumArray(Buffer.from(entry.valueMac));
138
+ }
139
+ }
140
+ return toJson({
141
+ version: v.version ?? 0,
142
+ hash: v.hash ? bufToNumArray(Buffer.from(v.hash)) : Array(128).fill(0),
143
+ index_value_map: indexValueMap
144
+ });
145
+ },
146
+ fromBridge(_key, value) {
147
+ try {
148
+ const j = fromJson(value);
149
+ const indexValueMap = {};
150
+ if (j.index_value_map) {
151
+ for (const [k, v] of Object.entries(j.index_value_map)) {
152
+ indexValueMap[k] = { valueMac: Buffer.from(v) };
153
+ }
154
+ }
155
+ return {
156
+ version: j.version ?? 0,
157
+ hash: Buffer.from(j.hash ?? []),
158
+ indexValueMap
159
+ };
160
+ }
161
+ catch {
162
+ return Buffer.from(value);
163
+ }
164
+ }
165
+ },
166
+ tc_token: {
167
+ toBridge(_key, value) {
168
+ const tc = value;
169
+ return toJson({
170
+ token: tc.token ? Buffer.from(tc.token).toString('base64') : '',
171
+ token_timestamp: tc.timestamp ? parseInt(tc.timestamp) : 0
172
+ });
173
+ },
174
+ fromBridge(_key, value) {
175
+ try {
176
+ const j = fromJson(value);
177
+ return {
178
+ token: j.token ? Buffer.from(j.token, 'base64') : Buffer.alloc(0),
179
+ timestamp: j.token_timestamp?.toString()
180
+ };
181
+ }
182
+ catch {
183
+ return { token: Buffer.from(value) };
184
+ }
185
+ }
186
+ },
187
+ device_list: {
188
+ toBridge(key, value) {
189
+ const list = value;
190
+ return toJson({
191
+ user: key,
192
+ devices: list.map(id => ({ device_id: parseInt(id) || 0 })),
193
+ timestamp: Math.floor(Date.now() / 1000)
194
+ });
195
+ },
196
+ fromBridge(_key, value) {
197
+ try {
198
+ const r = fromJson(value);
199
+ const items = r.devices ?? [];
200
+ return items.map(d => String(d.device_id ?? 0));
201
+ }
202
+ catch {
203
+ return [];
204
+ }
205
+ }
206
+ }
207
+ };
208
+ // ---- Device/Creds ----
209
+ /** Parse a JID string into { user, device, server } */
210
+ function parseJid(jid) {
211
+ if (!jid)
212
+ return null;
213
+ const atIdx = jid.indexOf('@');
214
+ if (atIdx < 0)
215
+ return null;
216
+ const server = jid.slice(atIdx + 1);
217
+ const userPart = jid.slice(0, atIdx);
218
+ const colonIdx = userPart.indexOf(':');
219
+ if (colonIdx >= 0) {
220
+ return { user: userPart.slice(0, colonIdx), device: parseInt(userPart.slice(colonIdx + 1)) || 0, server };
221
+ }
222
+ return { user: userPart, device: 0, server };
223
+ }
224
+ function credsToDeviceJson(creds) {
225
+ /** Serialize a key pair as [private(32) + public(32)] matching Rust key_pair_serde */
226
+ const kp = (pair) => {
227
+ if (!pair)
228
+ return Array(64).fill(0);
229
+ return bufToNumArray(Buffer.from(pair.private)).concat(bufToNumArray(Buffer.from(pair.public)));
230
+ };
231
+ // Extract device number from me.id (e.g. "559984726662:7@s.whatsapp.net")
232
+ // or fall back to me.lid (e.g. "236395184570386:10@lid") for the device index
233
+ const pnJid = parseJid(creds.me?.id);
234
+ const lidJid = parseJid(creds.me?.lid);
235
+ // If me.id has no device suffix, use the LID's device number
236
+ const deviceNum = pnJid && pnJid.device > 0 ? pnJid.device : (lidJid?.device ?? 0);
237
+ return toJson({
238
+ pn: pnJid ? { user: pnJid.user, server: 's.whatsapp.net', device: deviceNum, agent: 0, integrator: 0 } : null,
239
+ lid: lidJid ? { user: lidJid.user, server: 'lid', device: lidJid.device, agent: 0, integrator: 0 } : null,
240
+ registration_id: creds.registrationId ?? 0,
241
+ noise_key: kp(creds.noiseKey),
242
+ identity_key: kp(creds.signedIdentityKey),
243
+ signed_pre_key: kp(creds.signedPreKey?.keyPair),
244
+ signed_pre_key_id: creds.signedPreKey?.keyId ?? 1,
245
+ signed_pre_key_signature: creds.signedPreKey?.signature
246
+ ? bufToNumArray(Buffer.from(creds.signedPreKey.signature))
247
+ : Array(64).fill(0),
248
+ adv_secret_key: creds.advSecretKey
249
+ ? bufToNumArray(Buffer.from(creds.advSecretKey, 'base64'))
250
+ : Array(32).fill(0),
251
+ account: null,
252
+ push_name: creds.me?.name ?? '',
253
+ app_version_primary: 2,
254
+ app_version_secondary: 3000,
255
+ app_version_tertiary: 0,
256
+ app_version_last_fetched_ms: 0,
257
+ edge_routing_info: creds.routingInfo ? bufToNumArray(creds.routingInfo) : null,
258
+ props_hash: creds.lastPropHash ?? null,
259
+ next_pre_key_id: creds.nextPreKeyId ?? 1
260
+ });
261
+ }
262
+ function updateCredsFromDevice(bytes, creds) {
263
+ try {
264
+ const d = fromJson(bytes);
265
+ // Reconstruct pn JID: bridge stores Jid as { user, server, device, agent, integrator }
266
+ // bridgeJidToString produces "user:device@server" (device omitted when 0)
267
+ const pnJid = bridgeJidToString(d.pn);
268
+ if (pnJid) {
269
+ if (!creds.me)
270
+ creds.me = { id: pnJid };
271
+ else
272
+ creds.me.id = pnJid;
273
+ }
274
+ // Reconstruct LID JID
275
+ const lidJid = bridgeJidToString(d.lid);
276
+ if (lidJid && creds.me)
277
+ creds.me.lid = lidJid;
278
+ if (d.push_name && creds.me)
279
+ creds.me.name = d.push_name;
280
+ if (d.registration_id)
281
+ creds.registrationId = d.registration_id;
282
+ if (d.next_pre_key_id)
283
+ creds.nextPreKeyId = d.next_pre_key_id;
284
+ if (d.props_hash !== undefined)
285
+ creds.lastPropHash = d.props_hash ?? undefined;
286
+ if (d.platform)
287
+ creds.platform = d.platform;
288
+ // adv_secret_key: bridge stores as [u8; 32] (array of 32 numbers),
289
+ // upstream stores as base64 string
290
+ if (Array.isArray(d.adv_secret_key)) {
291
+ const buf = Buffer.from(d.adv_secret_key);
292
+ if (buf.some(b => b !== 0)) {
293
+ creds.advSecretKey = buf.toString('base64');
294
+ }
295
+ }
296
+ }
297
+ catch (e) {
298
+ warn('updateCredsFromDevice failed:', e);
299
+ }
300
+ }
301
+ // ---- Protobuf helpers (PreKeyRecordStructure) ----
302
+ function encodePreKeyRecord(id, pub, priv) {
303
+ const out = [];
304
+ out.push(0x08);
305
+ encodeVarint(out, id); // field 1: id
306
+ out.push(0x12);
307
+ encodeVarint(out, pub.length); // field 2: public_key
308
+ for (let i = 0; i < pub.length; i++)
309
+ out.push(pub[i]);
310
+ out.push(0x1a);
311
+ encodeVarint(out, priv.length); // field 3: private_key
312
+ for (let i = 0; i < priv.length; i++)
313
+ out.push(priv[i]);
314
+ return new Uint8Array(out);
315
+ }
316
+ function decodePreKeyRecord(data) {
317
+ try {
318
+ let pos = 0, pub = null, priv = null;
319
+ while (pos < data.length) {
320
+ const [tag, p1] = readVarint(data, pos);
321
+ pos = p1;
322
+ const wt = tag & 7, fn = tag >> 3;
323
+ if (wt === 0) {
324
+ const [, p2] = readVarint(data, pos);
325
+ pos = p2;
326
+ }
327
+ else if (wt === 2) {
328
+ const [len, p2] = readVarint(data, pos);
329
+ pos = p2;
330
+ const bytes = Buffer.from(data.slice(pos, pos + len));
331
+ pos += len;
332
+ if (fn === 2)
333
+ pub = bytes;
334
+ else if (fn === 3)
335
+ priv = bytes;
336
+ }
337
+ else
338
+ break;
339
+ }
340
+ return pub && priv ? { public: pub, private: priv } : null;
341
+ }
342
+ catch {
343
+ return null;
344
+ }
345
+ }
346
+ // ---- Protobuf varint helpers ----
347
+ function encodeVarint(out, v) {
348
+ while (v > 0x7f) {
349
+ out.push((v & 0x7f) | 0x80);
350
+ v >>>= 7;
351
+ }
352
+ out.push(v & 0x7f);
353
+ }
354
+ function readVarint(d, p) {
355
+ let r = 0, s = 0;
356
+ while (p < d.length) {
357
+ const b = d[p];
358
+ p++;
359
+ r |= (b & 0x7f) << s;
360
+ if (!(b & 0x80))
361
+ return [r, p];
362
+ s += 7;
363
+ }
364
+ return [r, p];
365
+ }
366
+ // ---- Signal address translation ----
367
+ // Bridge uses JID-based addresses: "236395184570386@lid.0", "559984726662@c.us.0"
368
+ // Baileys uses domain-type addresses: "236395184570386_1.0", "559984726662.0"
369
+ // Domain types: s.whatsapp.net/c.us=0, lid=1, hosted=2, hosted.lid=3
370
+ const DOMAIN_TYPE_MAP = { lid: 1, 'c.us': 0, 's.whatsapp.net': 0, hosted: 2, 'hosted.lid': 3 };
371
+ /** Convert bridge signal address to Baileys signal address */
372
+ function bridgeAddrToBaileysAddr(bridgeAddr) {
373
+ // Format: "user@domain.signalDevice" or "user:jidDevice@domain.signalDevice"
374
+ const dotIdx = bridgeAddr.lastIndexOf('.');
375
+ if (dotIdx < 0)
376
+ return null;
377
+ const signalDevice = bridgeAddr.slice(dotIdx + 1);
378
+ const jidPart = bridgeAddr.slice(0, dotIdx); // "user@domain" or "user:jidDevice@domain"
379
+ const atIdx = jidPart.indexOf('@');
380
+ if (atIdx < 0)
381
+ return null;
382
+ const domain = jidPart.slice(atIdx + 1);
383
+ const userPart = jidPart.slice(0, atIdx); // "user" or "user:jidDevice"
384
+ const domainType = DOMAIN_TYPE_MAP[domain];
385
+ if (domainType === undefined)
386
+ return null;
387
+ // Baileys format: "user_domainType.device" or "user.device" (when domainType=0)
388
+ // For JID device: "user_domainType:jidDevice.device"
389
+ let baileysUser;
390
+ if (userPart.includes(':')) {
391
+ // Has JID device: "user:jidDevice" → for signal address, device is the JID device
392
+ const [user, jidDevice] = userPart.split(':');
393
+ baileysUser = domainType !== 0 ? `${user}_${domainType}` : user;
394
+ return `${baileysUser}.${jidDevice}`;
395
+ }
396
+ else {
397
+ baileysUser = domainType !== 0 ? `${userPart}_${domainType}` : userPart;
398
+ return `${baileysUser}.${signalDevice}`;
399
+ }
400
+ }
401
+ // ---- Account normalization ----
402
+ // Upstream Baileys stores account fields as base64 strings (protobuf.js toJSON),
403
+ // but the bridge's encodeProto expects Uint8Array for bytes fields.
404
+ function normalizeAccountForEncode(account) {
405
+ const toBytes = (v) => {
406
+ if (v instanceof Uint8Array)
407
+ return v;
408
+ if (Buffer.isBuffer(v))
409
+ return new Uint8Array(v);
410
+ if (typeof v === 'string')
411
+ return Buffer.from(v, 'base64');
412
+ return undefined;
413
+ };
414
+ return {
415
+ details: toBytes(account.details),
416
+ accountSignatureKey: toBytes(account.accountSignatureKey),
417
+ accountSignature: toBytes(account.accountSignature),
418
+ deviceSignature: toBytes(account.deviceSignature)
419
+ };
420
+ }
421
+ // ---- Main ----
422
+ export async function wrapLegacyStore(state, saveCreds, logger) {
423
+ if (logger) {
424
+ _warnFn = (msg, err) => logger.warn({ err }, msg);
425
+ }
426
+ if (!state.creds || !state.keys) {
427
+ throw new Error('wrapLegacyStore requires an AuthenticationState with creds and keys');
428
+ }
429
+ const creds = state.creds;
430
+ const keys = state.keys;
431
+ const store = keys;
432
+ const storeGetOne = async (type, id) => {
433
+ const result = await store.get(type, [id]);
434
+ return result[id] ?? null;
435
+ };
436
+ const storeSetOne = (type, id, value) => store.set({ [type]: { [id]: value } });
437
+ let credsTimer = null;
438
+ const debounceSave = () => {
439
+ if (credsTimer)
440
+ clearTimeout(credsTimer);
441
+ credsTimer = setTimeout(() => {
442
+ credsTimer = null;
443
+ saveCreds().catch(() => { });
444
+ }, 100);
445
+ };
446
+ /** Route a store to its handler */
447
+ const resolve = (store) => {
448
+ if (store === 'device')
449
+ return 'device';
450
+ if (BINARY_STORES.has(store))
451
+ return 'signal';
452
+ if (BRIDGE_ONLY_STORES.has(store))
453
+ return 'bridge-only';
454
+ if (STORE_MAP[store])
455
+ return 'converter';
456
+ return 'unknown';
457
+ };
458
+ /** Translate bridge key format to upstream Baileys key format */
459
+ const translateKey = (store, key) => {
460
+ // Bridge encodes sync_key IDs as hex; upstream stores use base64
461
+ if (store === 'sync_key')
462
+ return hexToBase64(key);
463
+ return key;
464
+ };
465
+ /** Read a binary value from the keys store */
466
+ async function readBinary(type, id) {
467
+ try {
468
+ const val = await storeGetOne(type, id);
469
+ return val != null ? toBuf(val) : null; // eslint-disable-line eqeqeq -- intentional null+undefined check
470
+ }
471
+ catch (e) {
472
+ warn(`GET ${type}/${id} failed:`, e);
473
+ return null;
474
+ }
475
+ }
476
+ /** Write a binary value to the keys store */
477
+ async function writeBinary(type, id, value) {
478
+ try {
479
+ await storeSetOne(type, id, Buffer.from(value));
480
+ }
481
+ catch (e) {
482
+ warn(`SET ${type}/${id} failed:`, e);
483
+ }
484
+ }
485
+ /** Delete a value from the keys store */
486
+ async function storeDelete(type, id) {
487
+ try {
488
+ await storeSetOne(type, id, null);
489
+ }
490
+ catch (e) {
491
+ warn(`DELETE ${type}/${id} failed:`, e);
492
+ }
493
+ }
494
+ return {
495
+ async get(bridgeStore, key) {
496
+ const route = resolve(bridgeStore);
497
+ const type = STORE_MAP[bridgeStore];
498
+ if (route === 'device') {
499
+ if (key === 'device')
500
+ return credsToDeviceJson(creds);
501
+ if (key === 'account') {
502
+ if (!creds.account)
503
+ return null;
504
+ return new Uint8Array(ADVSignedDeviceIdentity.encode(normalizeAccountForEncode(creds.account)).finish());
505
+ }
506
+ return readBinary(type, key);
507
+ }
508
+ if (route === 'signal') {
509
+ const val = await readBinary(type, key);
510
+ if (val)
511
+ return val;
512
+ // Identity fallback: upstream Baileys uses a different address format
513
+ if (bridgeStore === 'identity')
514
+ return identityFallback(key, type);
515
+ return null;
516
+ }
517
+ if (route === 'bridge-only')
518
+ return readBinary(type, key);
519
+ if (route === 'converter') {
520
+ try {
521
+ const upstreamKey = translateKey(bridgeStore, key);
522
+ const value = await storeGetOne(type, upstreamKey);
523
+ if (value == null)
524
+ return null; // eslint-disable-line eqeqeq -- intentional null+undefined check
525
+ return converters[bridgeStore]?.toBridge(key, value) ?? toBuf(value);
526
+ }
527
+ catch (e) {
528
+ warn(`GET ${bridgeStore}/${key} failed:`, e);
529
+ return null;
530
+ }
531
+ }
532
+ warn(`GET unknown store: ${bridgeStore}/${key}`);
533
+ return null;
534
+ },
535
+ async set(bridgeStore, key, value) {
536
+ const route = resolve(bridgeStore);
537
+ const type = STORE_MAP[bridgeStore];
538
+ if (route === 'device') {
539
+ if (key === 'device') {
540
+ updateCredsFromDevice(value, creds);
541
+ debounceSave();
542
+ return;
543
+ }
544
+ if (key === 'account') {
545
+ try {
546
+ creds.account = ADVSignedDeviceIdentity.decode(value);
547
+ debounceSave();
548
+ }
549
+ catch (e) {
550
+ warn('failed to decode account update:', e);
551
+ }
552
+ return;
553
+ }
554
+ return writeBinary(type, key, value);
555
+ }
556
+ if (route === 'signal')
557
+ return writeBinary(type, key, value);
558
+ if (route === 'bridge-only')
559
+ return writeBinary(type, key, value);
560
+ if (route === 'converter') {
561
+ try {
562
+ const upstreamKey = translateKey(bridgeStore, key);
563
+ const typed = converters[bridgeStore]?.fromBridge(key, value) ?? Buffer.from(value);
564
+ await storeSetOne(type, upstreamKey, typed);
565
+ }
566
+ catch (e) {
567
+ warn(`SET ${bridgeStore}/${key} failed:`, e);
568
+ }
569
+ return;
570
+ }
571
+ warn(`SET unknown store: ${bridgeStore}/${key}`);
572
+ },
573
+ async delete(bridgeStore, key) {
574
+ if (bridgeStore === 'device')
575
+ return;
576
+ const route = resolve(bridgeStore);
577
+ const type = STORE_MAP[bridgeStore];
578
+ if (type) {
579
+ const storeKey = route === 'converter' ? translateKey(bridgeStore, key) : key;
580
+ await storeDelete(type, storeKey);
581
+ }
582
+ },
583
+ async flush() {
584
+ if (credsTimer) {
585
+ clearTimeout(credsTimer);
586
+ credsTimer = null;
587
+ await saveCreds();
588
+ }
589
+ },
590
+ dispose() {
591
+ if (credsTimer) {
592
+ clearTimeout(credsTimer);
593
+ saveCreds().catch(() => { });
594
+ }
595
+ }
596
+ };
597
+ // Identity key fallback: upstream Baileys uses different address format
598
+ // (user_domainType.device) and stores 33 bytes (0x05 + 32-byte DJB key)
599
+ async function identityFallback(key, type) {
600
+ try {
601
+ const baileysAddr = bridgeAddrToBaileysAddr(key);
602
+ if (!baileysAddr)
603
+ return null;
604
+ const raw = await storeGetOne('identity-key', baileysAddr);
605
+ if (!raw || (!Buffer.isBuffer(raw) && !(raw instanceof Uint8Array)))
606
+ return null;
607
+ let buf = Buffer.isBuffer(raw) ? raw : Buffer.from(raw);
608
+ if (buf.length === 33 && buf[0] === 0x05)
609
+ buf = buf.slice(1);
610
+ const arr = new Uint8Array(buf);
611
+ await writeBinary(type, key, arr); // persist under bridge key for future reads
612
+ return arr;
613
+ }
614
+ catch (e) {
615
+ warn(`identity fallback failed for ${key}:`, e);
616
+ return null;
617
+ }
618
+ }
619
+ }
620
+ const bufferReviver = (_, value) => {
621
+ if (value !== null &&
622
+ value !== undefined &&
623
+ typeof value === 'object' &&
624
+ (value.type === 'Buffer' || value.buffer === true)) {
625
+ const data = value.data ?? value.value;
626
+ return typeof data === 'string'
627
+ ? Buffer.from(data, 'base64')
628
+ : Buffer.from((Array.isArray(data) ? data : []));
629
+ }
630
+ return value;
631
+ };
632
+ /** JSON replacer that serializes Buffer/Uint8Array → `{ type: "Buffer", data: "base64" }` */
633
+ const bufferReplacer = (_, value) => value instanceof Uint8Array || Buffer.isBuffer(value)
634
+ ? { type: 'Buffer', data: Buffer.from(value).toString('base64') }
635
+ : value;
636
+ const fixFileName = (file) => file?.replace(/\//g, '__')?.replace(/:/g, '-');
637
+ /**
638
+ * Loads an upstream Baileys session (creds.json + key .json files) and returns
639
+ * the standard `{ state, saveCreds }` tuple that `wrapLegacyStore` expects.
640
+ *
641
+ * ```typescript
642
+ * const { state, saveCreds } = await useLegacyMultiFileAuthState('/path/to/baileys_auth_info')
643
+ * const store = await wrapLegacyStore(state, saveCreds)
644
+ * const sock = makeWASocket({ auth: { store } })
645
+ * ```
646
+ */
647
+ export async function useLegacyMultiFileAuthState(folder) {
648
+ const folderInfo = await stat(folder).catch(() => null);
649
+ if (folderInfo && !folderInfo.isDirectory()) {
650
+ throw new Error(`found something that is not a directory at ${folder}`);
651
+ }
652
+ if (!folderInfo) {
653
+ await mkdir(folder, { recursive: true });
654
+ }
655
+ const readData = async (file) => {
656
+ try {
657
+ const data = await readFile(join(folder, fixFileName(file)), 'utf-8');
658
+ return JSON.parse(data, bufferReviver);
659
+ }
660
+ catch {
661
+ return null;
662
+ }
663
+ };
664
+ const writeData = async (data, file) => {
665
+ await writeFile(join(folder, fixFileName(file)), JSON.stringify(data, bufferReplacer));
666
+ };
667
+ const removeData = async (file) => {
668
+ try {
669
+ await unlink(join(folder, fixFileName(file)));
670
+ }
671
+ catch { }
672
+ };
673
+ const creds = await readData('creds.json');
674
+ if (!creds) {
675
+ throw new Error(`No creds.json found in ${folder}. This loader requires an existing upstream Baileys session.`);
676
+ }
677
+ return {
678
+ state: {
679
+ creds,
680
+ keys: {
681
+ get: async (type, ids) => {
682
+ const data = {};
683
+ await Promise.all(ids.map(async (id) => {
684
+ let value = await readData(`${type}-${id}.json`);
685
+ if (type === 'app-state-sync-key' && value) {
686
+ value = proto.Message.AppStateSyncKeyData.fromObject(value);
687
+ }
688
+ data[id] = value;
689
+ }));
690
+ return data;
691
+ },
692
+ set: async (data) => {
693
+ const tasks = [];
694
+ for (const category in data) {
695
+ for (const id in data[category]) {
696
+ const value = data[category][id];
697
+ const file = `${category}-${id}.json`;
698
+ tasks.push(value ? writeData(value, file) : removeData(file));
699
+ }
700
+ }
701
+ await Promise.all(tasks);
702
+ }
703
+ }
704
+ },
705
+ saveCreds: () => writeData(creds, 'creds.json')
706
+ };
707
+ }
708
+ //# sourceMappingURL=wrap-legacy-store.js.map