@hdriel/whatsapp-socket 1.2.4 → 1.2.6
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/README.md +174 -137
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +60 -29
- package/dist/index.d.ts +60 -29
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -48,6 +48,24 @@ The WhatsApp socket connection requires a persistent, stateful connection that s
|
|
|
48
48
|
- Docker containers on persistent infrastructure
|
|
49
49
|
- AWS EC2/ECS, Google Compute Engine, or Azure VM (not Lambda/Cloud Functions)
|
|
50
50
|
|
|
51
|
+
## Demo
|
|
52
|
+
|
|
53
|
+
For fully demo you could see in this project github repository this demos <br>
|
|
54
|
+
Note: to update .env.local in each directory to run on your phone number / mongodb connection
|
|
55
|
+
|
|
56
|
+
* demo-client & demo-server, <br/>
|
|
57
|
+
just run in the demo-server this line, to build and run client and server side
|
|
58
|
+
```bash
|
|
59
|
+
npm run start
|
|
60
|
+
// open when ready: http://localhost:1010
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
* demo-script just run the following scripts to run all method function on your phone <br/>
|
|
64
|
+
```bash
|
|
65
|
+
npm run test:private
|
|
66
|
+
// or
|
|
67
|
+
npm run test:group
|
|
68
|
+
```
|
|
51
69
|
|
|
52
70
|
## Installation
|
|
53
71
|
|
|
@@ -137,21 +155,21 @@ await client.startConnection();
|
|
|
137
155
|
```
|
|
138
156
|
|
|
139
157
|
#### `closeConnection()`
|
|
140
|
-
Close the WhatsApp connection.
|
|
158
|
+
Close the WhatsApp connection. (not really needed, the connection closed automatically when unused)
|
|
141
159
|
|
|
142
160
|
```typescript
|
|
143
161
|
await client.closeConnection();
|
|
144
162
|
```
|
|
145
163
|
|
|
146
164
|
#### `resetConnection(options?)`
|
|
147
|
-
Reset the connection and generate a new QR code
|
|
165
|
+
Reset the connection and generate a new QR code.
|
|
148
166
|
|
|
149
167
|
```typescript
|
|
150
168
|
// Generate new QR code
|
|
151
169
|
await client.resetConnection();
|
|
152
170
|
|
|
153
|
-
// Or use phone number pairing
|
|
154
|
-
await client.resetConnection({ pairingPhone: '050-000-0000' });
|
|
171
|
+
// Or use phone number pairing (not working for now)
|
|
172
|
+
// await client.resetConnection({ pairingPhone: '050-000-0000' });
|
|
155
173
|
```
|
|
156
174
|
|
|
157
175
|
#### `isConnected()`
|
|
@@ -162,22 +180,18 @@ const connected = client.isConnected();
|
|
|
162
180
|
console.log('Connected:', connected);
|
|
163
181
|
```
|
|
164
182
|
|
|
165
|
-
### Messaging Methods
|
|
166
|
-
|
|
167
|
-
#### `sendTextMessage(jid, text)`
|
|
168
|
-
Send a plain text message.
|
|
183
|
+
### Messaging Methods apis
|
|
169
184
|
|
|
170
185
|
```typescript
|
|
186
|
+
import fs from 'fs';
|
|
187
|
+
|
|
188
|
+
// Send a plain text message.
|
|
171
189
|
await client.sendTextMessage(
|
|
172
190
|
'0500000000',// or 050-000-0000 converted to 972500000000 , or define DEFAULT_COUNTRY to change 972 to your country
|
|
173
191
|
'Hello, this is a test message!'
|
|
174
192
|
);
|
|
175
|
-
```
|
|
176
193
|
|
|
177
|
-
|
|
178
|
-
Send an interactive message with action buttons.
|
|
179
|
-
|
|
180
|
-
```typescript
|
|
194
|
+
// Send an interactive message with action buttons.
|
|
181
195
|
await client.sendButtonsMessage('1234567890@s.whatsapp.net', {
|
|
182
196
|
title: 'Welcome to our service!',
|
|
183
197
|
subtitle: 'Please choose an action below',
|
|
@@ -194,12 +208,8 @@ await client.sendButtonsMessage('1234567890@s.whatsapp.net', {
|
|
|
194
208
|
// }
|
|
195
209
|
]
|
|
196
210
|
});
|
|
197
|
-
```
|
|
198
211
|
|
|
199
|
-
|
|
200
|
-
Send a message with reply buttons (quick reply options).
|
|
201
|
-
|
|
202
|
-
```typescript
|
|
212
|
+
// Send a message with reply buttons (quick reply options).
|
|
203
213
|
await client.sendReplyButtonsMessage('1234567890@s.whatsapp.net', {
|
|
204
214
|
title: 'Choose your preferred time',
|
|
205
215
|
subtitle: 'Click one of the options below',
|
|
@@ -209,62 +219,87 @@ await client.sendReplyButtonsMessage('1234567890@s.whatsapp.net', {
|
|
|
209
219
|
'Evening (5-9)'
|
|
210
220
|
]
|
|
211
221
|
});
|
|
212
|
-
```
|
|
213
222
|
|
|
214
|
-
#### `sendImageMessage(jid, buffer, options?)`
|
|
215
|
-
Send an image message.
|
|
216
|
-
|
|
217
|
-
```typescript
|
|
218
|
-
import fs from 'fs';
|
|
219
223
|
|
|
224
|
+
// Send an image message.
|
|
220
225
|
const imageBuffer = fs.readFileSync('./photo.jpg');
|
|
221
226
|
await client.sendImageMessage('050-000-0000', imageBuffer, {
|
|
222
227
|
caption: 'Check out this photo!',
|
|
223
228
|
filename: 'photo.jpg'
|
|
224
229
|
});
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
#### `sendVideoMessage(jid, buffer, caption?)`
|
|
228
|
-
Send a video message.
|
|
229
230
|
|
|
230
|
-
|
|
231
|
+
// Send a video message.
|
|
231
232
|
const videoBuffer = fs.readFileSync('./video.mp4');
|
|
232
233
|
await client.sendVideoMessage(
|
|
233
234
|
'050-000-0000',
|
|
234
235
|
videoBuffer,
|
|
235
236
|
{ caption: 'Amazing video!' }
|
|
236
237
|
);
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
#### `sendAudioMessage(jid, buffer, options?)`
|
|
240
|
-
Send an audio message.
|
|
241
238
|
|
|
242
|
-
|
|
239
|
+
// Send an audio message.
|
|
243
240
|
const audioBuffer = fs.readFileSync('./audio.mp3');
|
|
244
241
|
await client.sendAudioMessage('050-000-0000', audioBuffer, {
|
|
245
242
|
filename: 'audio.mp3',
|
|
246
243
|
mimetype: 'audio/mpeg'
|
|
247
244
|
});
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
#### `sendFileMessage(jid, buffer, options?)`
|
|
251
|
-
Send a document/file message.
|
|
252
245
|
|
|
253
|
-
|
|
246
|
+
// Send a document/file message.
|
|
254
247
|
const fileBuffer = fs.readFileSync('./document.pdf');
|
|
255
248
|
await client.sendFileMessage('050-000-0000', fileBuffer, {
|
|
256
249
|
filename: 'document.pdf',
|
|
257
250
|
mimetype: 'application/pdf',
|
|
258
|
-
caption: 'Here is the requested document'
|
|
251
|
+
caption: 'Here is the requested document',
|
|
252
|
+
autoMessageClassification: false
|
|
259
253
|
});
|
|
260
|
-
```
|
|
261
254
|
|
|
262
|
-
|
|
263
|
-
Send a sticker message (must be WebP format).
|
|
264
|
-
|
|
265
|
-
```typescript
|
|
255
|
+
// Send a sticker message (must be WebP format).
|
|
266
256
|
const stickerBuffer = fs.readFileSync('./sticker.webp');
|
|
267
257
|
await client.sendStickerMessage('050-000-0000', stickerBuffer);
|
|
258
|
+
|
|
259
|
+
// Send a location message
|
|
260
|
+
const position = await getCurrentLocation();
|
|
261
|
+
await was.sendLocationMessage(
|
|
262
|
+
'050-000-0000',
|
|
263
|
+
positon, // { latitude: 31.4117, longitude: 35.0818},
|
|
264
|
+
'Place Name',
|
|
265
|
+
'Full Address'
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
// client side to get current location
|
|
269
|
+
export const getCurrentLocation = async () => {
|
|
270
|
+
try {
|
|
271
|
+
const position: any = await new Promise((resolve, reject) => {
|
|
272
|
+
if (!navigator.geolocation) {
|
|
273
|
+
reject(new Error('Geolocation is not supported by your browser'));
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
navigator.geolocation.getCurrentPosition(resolve, reject, {
|
|
278
|
+
enableHighAccuracy: true,
|
|
279
|
+
timeout: 60_000,
|
|
280
|
+
maximumAge: 0,
|
|
281
|
+
});
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
const location = {
|
|
285
|
+
latitude: position.coords.latitude,
|
|
286
|
+
longitude: position.coords.longitude,
|
|
287
|
+
accuracy: position.coords.accuracy,
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
return location;
|
|
291
|
+
} catch (err: any) {
|
|
292
|
+
if (err.code === 1) {
|
|
293
|
+
throw Error('Location permission denied');
|
|
294
|
+
} else if (err.code === 2) {
|
|
295
|
+
throw Error('Location unavailable');
|
|
296
|
+
} else if (err.code === 3) {
|
|
297
|
+
throw Error('Location request timed out');
|
|
298
|
+
} else {
|
|
299
|
+
throw Error(err instanceof Error ? err.message : 'Failed to send location');
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
};
|
|
268
303
|
```
|
|
269
304
|
|
|
270
305
|
### Utility Methods
|
|
@@ -278,17 +313,6 @@ console.log(qrImage); // data:image/png;base64,...
|
|
|
278
313
|
// In client side <img src={qrImage} />
|
|
279
314
|
```
|
|
280
315
|
|
|
281
|
-
#### `WhatsappSocket.randomPairingCode(pattern)`
|
|
282
|
-
Generate a random pairing code.
|
|
283
|
-
|
|
284
|
-
```typescript
|
|
285
|
-
// Generate 6-digit numeric code
|
|
286
|
-
const code = WhatsappSocket.randomPairingCode('[0-9]');
|
|
287
|
-
|
|
288
|
-
// Generate alphanumeric code
|
|
289
|
-
const alphaCode = WhatsappSocket.randomPairingCode('[a-z0-9]');
|
|
290
|
-
```
|
|
291
|
-
|
|
292
316
|
## Phone Number Format
|
|
293
317
|
|
|
294
318
|
Support normal format and converters to expected format for example:
|
|
@@ -438,8 +462,6 @@ await client.startConnection();
|
|
|
438
462
|
|
|
439
463
|
## Group Operations
|
|
440
464
|
|
|
441
|
-
### Creating Groups
|
|
442
|
-
|
|
443
465
|
```typescript
|
|
444
466
|
// Create a new group
|
|
445
467
|
const group = await client.createGroup({
|
|
@@ -449,11 +471,7 @@ const group = await client.createGroup({
|
|
|
449
471
|
});
|
|
450
472
|
|
|
451
473
|
console.log('Group ID:', group.id);
|
|
452
|
-
```
|
|
453
|
-
|
|
454
|
-
### Group Information
|
|
455
474
|
|
|
456
|
-
```typescript
|
|
457
475
|
// Update group name
|
|
458
476
|
await client.updateGroupName(groupId, 'New Group Name');
|
|
459
477
|
|
|
@@ -468,11 +486,7 @@ console.log('Participants:', metadata.participants.length);
|
|
|
468
486
|
// Get all groups
|
|
469
487
|
const allGroups = await client.getAllGroups();
|
|
470
488
|
console.log('Total groups:', allGroups.length);
|
|
471
|
-
```
|
|
472
|
-
|
|
473
|
-
### Group Settings
|
|
474
489
|
|
|
475
|
-
```typescript
|
|
476
490
|
// Lock group (only admins can send messages)
|
|
477
491
|
await client.updateGroupSettings(groupId, 'announcement');
|
|
478
492
|
|
|
@@ -484,11 +498,7 @@ await client.updateGroupSettings(groupId, 'locked');
|
|
|
484
498
|
|
|
485
499
|
// Unlock group info (everyone can edit)
|
|
486
500
|
await client.updateGroupSettings(groupId, 'unlocked');
|
|
487
|
-
```
|
|
488
|
-
|
|
489
|
-
### Participant Management
|
|
490
501
|
|
|
491
|
-
```typescript
|
|
492
502
|
// Add participants
|
|
493
503
|
await client.addParticipants(groupId, '972501234567');
|
|
494
504
|
// Or add multiple
|
|
@@ -505,11 +515,7 @@ await client.demoteFromAdmin(groupId, '972501234567');
|
|
|
505
515
|
|
|
506
516
|
// Leave group
|
|
507
517
|
await client.leaveGroup(groupId);
|
|
508
|
-
```
|
|
509
518
|
|
|
510
|
-
### Invite Management
|
|
511
|
-
|
|
512
|
-
```typescript
|
|
513
519
|
// Get group invite code
|
|
514
520
|
const inviteCode = await client.getGroupInviteCode(groupId);
|
|
515
521
|
const inviteLink = await client.getGroupInviteCode(groupId, true);
|
|
@@ -525,16 +531,7 @@ console.log('New invite code:', newInviteCode);
|
|
|
525
531
|
|
|
526
532
|
// Join group via invite code
|
|
527
533
|
const joinedGroupId = await client.joinGroupViaInvite(inviteCode);
|
|
528
|
-
```
|
|
529
|
-
|
|
530
|
-
### Profile Picture Management
|
|
531
534
|
|
|
532
|
-
**Note:** Requires `sharp` library to be installed:
|
|
533
|
-
```bash
|
|
534
|
-
npm install sharp
|
|
535
|
-
```
|
|
536
|
-
|
|
537
|
-
```typescript
|
|
538
535
|
import fs from 'fs';
|
|
539
536
|
|
|
540
537
|
// Update group profile picture
|
|
@@ -549,13 +546,8 @@ const highResUrl = await client.getGroupProfilePicture(groupId, true);
|
|
|
549
546
|
|
|
550
547
|
// Remove profile picture
|
|
551
548
|
await client.removeGroupProfilePicture(groupId);
|
|
552
|
-
```
|
|
553
|
-
|
|
554
|
-
### Sending Messages to Groups
|
|
555
|
-
|
|
556
|
-
All messaging methods work the same for groups and individual chats:
|
|
557
549
|
|
|
558
|
-
|
|
550
|
+
// All messaging methods work the same for groups and individual chats:
|
|
559
551
|
// Send text message to group
|
|
560
552
|
await client.sendTextMessage(groupId, 'Hello everyone!');
|
|
561
553
|
|
|
@@ -584,6 +576,86 @@ const imageBuffer = fs.readFileSync('./photo.jpg');
|
|
|
584
576
|
await client.sendImageMessage(groupId, imageBuffer, {
|
|
585
577
|
caption: 'Group photo!'
|
|
586
578
|
});
|
|
579
|
+
|
|
580
|
+
// Send media
|
|
581
|
+
const imageBuffer = fs.readFileSync('./photo.jpg');
|
|
582
|
+
await client.sendFileMessage(groupId, imageBuffer, {
|
|
583
|
+
caption: 'nice photo!',
|
|
584
|
+
filename: 'my best photo.jpg',
|
|
585
|
+
// autoMessageClassification: true (default)
|
|
586
|
+
// true - send as file type, for example here send as image,
|
|
587
|
+
// false - send image as file message
|
|
588
|
+
});
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
## Stream and Buffer params
|
|
592
|
+
|
|
593
|
+
All methods that receive files could get buffer and stream types!
|
|
594
|
+
not stream will converted to buffer data, so will pull all data on your server
|
|
595
|
+
consider not send large files!
|
|
596
|
+
|
|
597
|
+
```typescript
|
|
598
|
+
router.post('/stream-file/:fileKey', async (req: Request, res: Response, next: NextFunction) => {
|
|
599
|
+
// using in this example with @hdriel/aws-utils pakcage..
|
|
600
|
+
if (!s3Util) return next(new Error('AWS FEATURE NOT SUPPORTED'));
|
|
601
|
+
|
|
602
|
+
try {
|
|
603
|
+
const fileKey = decodeURIComponent(req.params.fileKey);
|
|
604
|
+
const fileStream = await s3Util?.getObjectFileStream(fileKey);
|
|
605
|
+
if (!fileStream) {
|
|
606
|
+
res.status(400).json({ message: 'No document file found' });
|
|
607
|
+
return;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
// for private phone messages
|
|
611
|
+
const phoneTo = req.query?.phoneTo as string;
|
|
612
|
+
if (!phoneTo) {
|
|
613
|
+
res.status(400).json({ message: 'not retrieved defined, phoneTo number' });
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
const filename = basename(fileKey);
|
|
618
|
+
logger.info(null, 'Sending message...', { ...req.body, ...req.query, filename });
|
|
619
|
+
|
|
620
|
+
if (phoneTo) {
|
|
621
|
+
const was = new WhatsappSocket({
|
|
622
|
+
mongoURL: USE_MONGODB_STORAGE ? MONGODB_URI : undefined,
|
|
623
|
+
fileAuthStateDirectoryPath: fileAuthPath,
|
|
624
|
+
appName: 'whatsapp-socket-demo',
|
|
625
|
+
debug: true,
|
|
626
|
+
logger,
|
|
627
|
+
});
|
|
628
|
+
|
|
629
|
+
await was.sendFileMessage(phoneTo, fileStream as any, { filename });
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// for groupId messages
|
|
633
|
+
const groupId = req.query?.groupId as string;
|
|
634
|
+
if (!groupId) {
|
|
635
|
+
res.status(400).json({ message: 'not retrieved defined, groupId number' });
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
if (groupId) {
|
|
640
|
+
const was = new WhatsappSocketGroup({
|
|
641
|
+
mongoURL: USE_MONGODB_STORAGE ? MONGODB_URI : undefined,
|
|
642
|
+
fileAuthStateDirectoryPath: fileAuthPath,
|
|
643
|
+
appName: 'whatsapp-socket-demo',
|
|
644
|
+
debug: true,
|
|
645
|
+
logger,
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
await was.sendFileMessage(groupId, fileStream as any, { filename });
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
|
|
652
|
+
|
|
653
|
+
res.status(200).json({ message: 'OK' });
|
|
654
|
+
} catch (err: any) {
|
|
655
|
+
logger.error('AWS', 'failed on getObjectFileStream', { errMsg: err.message });
|
|
656
|
+
next(err);
|
|
657
|
+
}
|
|
658
|
+
});
|
|
587
659
|
```
|
|
588
660
|
|
|
589
661
|
## Complete Group Example
|
|
@@ -677,24 +749,6 @@ const formattedGroupId = WhatsappSocketGroup.formatGroupId('123456789');
|
|
|
677
749
|
// Returns: '123456789@g.us'
|
|
678
750
|
```
|
|
679
751
|
|
|
680
|
-
## Error Handling
|
|
681
|
-
|
|
682
|
-
Always wrap group operations in try-catch blocks:
|
|
683
|
-
|
|
684
|
-
```typescript
|
|
685
|
-
try {
|
|
686
|
-
await client.addParticipants(groupId, phoneNumber);
|
|
687
|
-
} catch (error) {
|
|
688
|
-
console.error('Failed to add participant:', error);
|
|
689
|
-
|
|
690
|
-
if (error.message.includes('item-not-found')) {
|
|
691
|
-
console.log('Group or participant not found');
|
|
692
|
-
} else if (error.message.includes('not-authorized')) {
|
|
693
|
-
console.log('Bot is not an admin');
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
|
-
```
|
|
697
|
-
|
|
698
752
|
## Common Use Cases
|
|
699
753
|
|
|
700
754
|
### Auto-Welcome New Members
|
|
@@ -704,10 +758,7 @@ client.onReceiveMessages = async (messages) => {
|
|
|
704
758
|
for (const msg of messages) {
|
|
705
759
|
if (msg.messageType === 'groupParticipantsUpdate') {
|
|
706
760
|
const groupId = msg.key.remoteJid;
|
|
707
|
-
await client.sendTextMessage(
|
|
708
|
-
groupId,
|
|
709
|
-
'Welcome to the group! 👋'
|
|
710
|
-
);
|
|
761
|
+
await client.sendTextMessage(groupId, 'Welcome to the group! 👋');
|
|
711
762
|
}
|
|
712
763
|
}
|
|
713
764
|
};
|
|
@@ -720,23 +771,9 @@ import cron from 'node-cron';
|
|
|
720
771
|
|
|
721
772
|
// Send daily message at 9 AM
|
|
722
773
|
cron.schedule('0 9 * * *', async () => {
|
|
723
|
-
await client.sendMentionAll(
|
|
724
|
-
groupId,
|
|
725
|
-
'☀️ Good morning everyone! Have a great day!'
|
|
726
|
-
);
|
|
774
|
+
await client.sendMentionAll(groupId, '☀️ Good morning everyone! Have a great day!');
|
|
727
775
|
});
|
|
728
776
|
```
|
|
729
|
-
|
|
730
|
-
### Group Polling System
|
|
731
|
-
|
|
732
|
-
```typescript
|
|
733
|
-
await client.sendReplyButtonsMessage(groupId, {
|
|
734
|
-
title: '📊 Daily Poll',
|
|
735
|
-
subtitle: 'What should we have for lunch?',
|
|
736
|
-
buttons: ['🍕 Pizza', '🍔 Burgers', '🍜 Ramen', '🥗 Salad']
|
|
737
|
-
});
|
|
738
|
-
```
|
|
739
|
-
|
|
740
777
|
## Best Practices
|
|
741
778
|
|
|
742
779
|
1. **Admin Rights**: Many operations require admin rights. Ensure your bot is an admin before performing administrative tasks.
|
|
@@ -786,6 +823,11 @@ For MongoDB storage, install the peer dependency:
|
|
|
786
823
|
npm install mongodb
|
|
787
824
|
```
|
|
788
825
|
|
|
826
|
+
## Known Issues
|
|
827
|
+
* not supported image formats: gif, bmp, and sometime data is corrupted
|
|
828
|
+
* issues to send large videos
|
|
829
|
+
* peering phone not working
|
|
830
|
+
|
|
789
831
|
## Best Practices
|
|
790
832
|
|
|
791
833
|
1. **Session Management**: Always store session data securely. For production, use MongoDB or encrypted file storage.
|
|
@@ -804,17 +846,7 @@ npm install mongodb
|
|
|
804
846
|
|
|
805
847
|
## TypeScript Support
|
|
806
848
|
|
|
807
|
-
The library is written in TypeScript and includes complete type definitions
|
|
808
|
-
|
|
809
|
-
```typescript
|
|
810
|
-
import { WhatsappSocket } from '@hdriel/whatsapp-socket';
|
|
811
|
-
|
|
812
|
-
// All methods and options are fully typed
|
|
813
|
-
const client: WhatsappSocket = new WhatsappSocket({
|
|
814
|
-
fileAuthStateDirectoryPath: './authState',
|
|
815
|
-
debug: true
|
|
816
|
-
});
|
|
817
|
-
```
|
|
849
|
+
The library is written in TypeScript and includes complete type definitions
|
|
818
850
|
|
|
819
851
|
## Troubleshooting
|
|
820
852
|
|
|
@@ -857,6 +889,11 @@ MIT License - see the [LICENSE](LICENSE) file for details.
|
|
|
857
889
|
- [music-metadata](https://www.npmjs.com/package/music-metadata) - Audio metadata extraction
|
|
858
890
|
- [ms](https://www.npmjs.com/package/ms) - Time string parsing
|
|
859
891
|
|
|
892
|
+
## Peer Dependencies
|
|
893
|
+
- [mongodb](https://www.npmjs.com/package/mongodb) ("^5.8.1") for persist connection on db collection
|
|
894
|
+
- [sharp](https://www.npmjs.com/package/sharp) ("^0.32.6") for profile group operators
|
|
895
|
+
|
|
896
|
+
|
|
860
897
|
## Author
|
|
861
898
|
|
|
862
899
|
**Hadriel Benjo**
|