@wavezfm/api 0.1.9 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +34 -431
  3. package/dist/index.d.ts +217 -31
  4. package/dist/index.js.map +1 -1
  5. package/dist/realtime/roomBot.js +50 -0
  6. package/dist/realtime/roomBot.js.map +1 -1
  7. package/dist/resources/billing.d.ts +80 -1
  8. package/dist/resources/billing.js +32 -0
  9. package/dist/resources/billing.js.map +1 -1
  10. package/dist/resources/chat.d.ts +3 -1
  11. package/dist/resources/chat.js +19 -0
  12. package/dist/resources/chat.js.map +1 -1
  13. package/dist/resources/friend.d.ts +1 -12
  14. package/dist/resources/friend.js +3 -18
  15. package/dist/resources/friend.js.map +1 -1
  16. package/dist/resources/playlist.d.ts +33 -8
  17. package/dist/resources/playlist.js +29 -3
  18. package/dist/resources/playlist.js.map +1 -1
  19. package/dist/resources/room.d.ts +32 -3
  20. package/dist/resources/room.js +53 -6
  21. package/dist/resources/room.js.map +1 -1
  22. package/dist/resources/roomBot.d.ts +8 -3
  23. package/dist/resources/roomBot.js +7 -2
  24. package/dist/resources/roomBot.js.map +1 -1
  25. package/dist/resources/settings.d.ts +52 -2
  26. package/dist/resources/settings.js +32 -0
  27. package/dist/resources/settings.js.map +1 -1
  28. package/dist/resources/shop.d.ts +5 -0
  29. package/dist/resources/shop.js +3 -0
  30. package/dist/resources/shop.js.map +1 -1
  31. package/dist/resources/source.d.ts +6 -6
  32. package/dist/resources/source.js +6 -3
  33. package/dist/resources/source.js.map +1 -1
  34. package/dist/resources/system.d.ts +3 -1
  35. package/dist/resources/system.js +6 -0
  36. package/dist/resources/system.js.map +1 -1
  37. package/dist/types.d.ts +210 -3
  38. package/package.json +4 -2
package/CHANGELOG.md ADDED
@@ -0,0 +1,31 @@
1
+ # Changelog
2
+
3
+ ## 0.3.0
4
+
5
+ ### Added
6
+
7
+ - Typed room-bot ephemeral chat messages over HTTP and WebSocket.
8
+ - Optional delivery of ephemeral messages to one user ID or up to 50 user IDs.
9
+ - Typed room-bot send-message responses, including persistence and delivery metadata.
10
+ - Canonical documentation links through `https://docs.wavez.fm/docs` package metadata and README navigation.
11
+
12
+ ## 0.2.0
13
+
14
+ ### Added
15
+
16
+ - Chat image uploads and media previews.
17
+ - External room media validation, metadata, Google Drive helpers, room leave, playback history, deletion, audit-log clearing, and word filters.
18
+ - Playlist search, ordering, availability checks, JSON import/export, track clipping, recent-room filtering, and paginated media search.
19
+ - GIF favorites, Last.fm account flows, Discord role sync, and social-image settings.
20
+ - Subscription management, payment history, miscellaneous checkout, Mercado Pago, and room subscription gifts.
21
+ - Notification center status and clearing.
22
+ - Room-bot word filters and superfans.
23
+
24
+ ### Fixed
25
+
26
+ - Unwrapped room detail responses so `room.getBySlug()` and slug-based joins return the actual room.
27
+ - Corrected paginated media search, playlist mutation, user settings, and checkout response types to match the server.
28
+
29
+ ### Removed
30
+
31
+ - Obsolete friend-request methods whose server routes no longer exist. Fan and superfan methods remain under `client.friend` for compatibility.
package/README.md CHANGED
@@ -1,466 +1,69 @@
1
1
  # @wavezfm/api
2
2
 
3
- Official JavaScript/TypeScript API client for WavezFM.
3
+ Official fetch-based JavaScript and TypeScript client for WavezFM. The package ships with zero runtime dependencies.
4
4
 
5
- This package is fetch-based and ships with zero runtime dependencies.
5
+ ## Documentation
6
+
7
+ The canonical documentation is hosted at [docs.wavez.fm](https://docs.wavez.fm/docs).
8
+
9
+ - [Getting started](https://docs.wavez.fm/docs/getting-started)
10
+ - [Frontend API](https://docs.wavez.fm/docs/frontend-api)
11
+ - [SDK reference](https://docs.wavez.fm/docs/sdk)
12
+ - [Room bots](https://docs.wavez.fm/docs/room-bots)
13
+ - [Room Bot HTTP API](https://docs.wavez.fm/docs/room-bots/http-api)
14
+ - [Room Bot Realtime API](https://docs.wavez.fm/docs/room-bots/realtime)
6
15
 
7
16
  ## Installation
8
17
 
9
18
  ```bash
10
- npm install @wavezfm/api
11
- # or
12
- yarn add @wavezfm/api
13
- # or
14
19
  bun add @wavezfm/api
15
20
  ```
16
21
 
17
- ## Quick Start
18
-
19
- ```ts
20
- import { createApiClient } from "@wavezfm/api";
21
-
22
- const client = createApiClient({
23
- baseURL: "https://api.wavez.fm",
24
- });
25
-
26
- const rooms = await client.room.list();
27
- console.log(rooms.data);
22
+ ```bash
23
+ npm install @wavezfm/api
28
24
  ```
29
25
 
30
- ## Configuration
26
+ ## Quick start
31
27
 
32
28
  ```ts
33
- createApiClient({
34
- baseURL: "https://api.wavez.fm",
35
- timeout: 15_000,
36
- logging: false,
37
- headers: { "X-App-Version": "1.0.0" },
38
- credentials: "include",
39
- locale: "en",
40
- });
41
- ```
42
-
43
- The client accepts:
44
-
45
- - `https://api.wavez.fm`
46
-
47
- If you use a dedicated API origin such as `api.wavez.fm`, the SDK keeps root paths like `/rooms`.
48
- If you pass the main site origin, the SDK still falls back to `/api`.
49
-
50
- You can localize SDK-generated errors with `locale` or override specific messages with `messages`:
51
-
52
- ```ts
53
- const client = createApiClient({
54
- baseURL: "https://api.wavez.fm",
55
- locale: "en",
56
- messages: {
57
- roomBotCreatePrefixLengthInvalid: "Custom prefix length message.",
58
- },
59
- });
60
- ```
61
-
62
- ## API Surfaces
63
-
64
- This SDK exposes three distinct surfaces. They do not authenticate the same way.
65
-
66
- ### Site / Browser API
67
-
68
- Use this for the normal site routes:
69
-
70
- - auth
71
- - settings
72
- - users
73
- - rooms
74
- - playlists
75
- - chat
76
- - billing
77
- - shop
78
-
79
- Auth mode:
80
-
81
- - browser session cookies
82
- - same protections used by the site
83
-
84
- This is also where bot tokens are created with `client.room.createBotToken(...)`.
85
-
86
- ### Room Bot HTTP API
87
-
88
- Use this for backend automation scoped to one room:
89
-
90
- - room state
91
- - room event history
92
- - bot chat send/read
93
- - queue actions
94
- - moderation and room management
95
-
96
- Auth mode:
97
-
98
- - room bot token with `client.api.setRoomBotToken(...)`
99
-
100
- ### Room Bot Realtime API
101
-
102
- Use this for low-latency bot behavior:
29
+ import { createApiClient } from '@wavezfm/api';
103
30
 
104
- - chat listeners
105
- - queue/playback/vote listeners
106
- - command reactions
107
-
108
- Auth mode:
109
-
110
- - room bot token over WebSocket
111
-
112
- ## Site / Browser API
113
-
114
- WavezFM uses session cookies for most user-authenticated routes.
115
-
116
- ```ts
117
31
  const client = createApiClient({
118
- baseURL: "https://api.wavez.fm",
119
- });
120
-
121
- await client.auth.login({
122
- email: "user@example.com",
123
- password: "secret",
124
- });
125
-
126
- const me = await client.auth.me();
127
- if (me.data) {
128
- console.log(me.data.displayUsername ?? me.data.username);
129
- }
130
- ```
131
-
132
- For server-side integrations, prefer the room-bot surfaces below. Regular user routes are browser-first.
133
-
134
- ### Site Resources
135
-
136
- All site resources are exposed from the pre-configured client:
137
-
138
- ```ts
139
- const client = createApiClient({ baseURL: "https://api.wavez.fm" });
140
- ```
141
-
142
- #### Auth
143
-
144
- ```ts
145
- await client.auth.login({ email, password });
146
- await client.auth.register({ email, password, name, username });
147
- const me = await client.auth.me();
148
- await client.auth.getPendingTwoFactor();
149
- await client.auth.sendPendingTwoFactorCode();
150
- await client.auth.verifyPendingTwoFactor({ code: "123456" });
151
- ```
152
-
153
- #### Settings
154
-
155
- ```ts
156
- await client.settings.get();
157
- await client.settings.update({
158
- bio: "Late-night selector",
159
- presenceStatus: "busy",
160
- showChatBadge: true,
161
- });
162
- await client.settings.getTwoFactor();
163
- await client.settings.startEmailTwoFactor({ password: "secret" });
164
- await client.settings.startAuthenticatorTwoFactor({ password: "secret" });
165
- await client.settings.disableTwoFactor({ password: "secret" });
166
- ```
167
-
168
- #### Users
169
-
170
- ```ts
171
- await client.user.getById("user-id");
172
- await client.user.getByUsername("haru");
173
- await client.user.getBadges("user-id");
174
- await client.user.listAllBadges();
175
- ```
176
-
177
- #### Rooms
178
-
179
- ```ts
180
- await client.room.list();
181
- await client.room.featured();
182
- await client.room.getBySlug("wavezfm-lounge");
183
- await client.room.getWaitlist("wavezfm-lounge");
184
- await client.room.create({ slug: "my-room", name: "My Room" });
185
- await client.room.join("wavezfm-lounge");
186
- await client.room.favorite("room-id");
187
- await client.room.getManagement("room-id");
188
- ```
189
-
190
- #### Playlists
191
-
192
- ```ts
193
- await client.playlist.list();
194
- await client.playlist.create("My Playlist");
195
- await client.playlist.update("playlist-id", { name: "Late Night Set" });
196
- await client.playlist.getTracks("playlist-id");
197
- await client.playlist.previewUrl("https://youtube.com/watch?v=dQw4w9WgXcQ");
198
- await client.playlist.addTrack("playlist-id", {
199
- source: "youtube",
200
- sourceId: "dQw4w9WgXcQ",
201
- });
202
- await client.playlist.reorderTracks("playlist-id", ["track-a", "track-b"]);
203
- await client.playlist.startSpotifyImport({
204
- playlistId: "playlist-id",
205
- url: "https://open.spotify.com/playlist/...",
206
- });
207
- ```
208
-
209
- #### Sources
210
-
211
- ```ts
212
- await client.source.searchYouTube("lofi hip hop", 10);
213
- await client.source.searchSoundCloud("nightcore", 10);
214
- await client.source.searchAll("ambient");
215
- ```
216
-
217
- #### Chat
218
-
219
- ```ts
220
- await client.chat.getMessages("room-id", 0, 50);
221
- await client.chat.getMessagesBySlug("wavezfm-lounge", 0, 50);
222
- await client.chat.updateMessage("room-id", "message-id", {
223
- content: "edited message",
32
+ baseURL: 'https://api.wavez.fm',
224
33
  });
225
- await client.chat.pinMessage("room-id", "message-id");
226
- await client.chat.clearChat("room-id");
227
- ```
228
-
229
- #### Friends / Fans
230
34
 
231
- ```ts
232
- await client.friend.list();
233
- await client.friend.pending();
234
- await client.friend.sendRequest("user-id");
235
- await client.friend.acceptRequest("request-id");
236
- await client.friend.follow("user-id");
237
- await client.friend.followers();
238
- ```
239
-
240
- #### Shop
241
-
242
- ```ts
243
- await client.shop.getCatalog();
244
- await client.shop.getWallet();
245
- await client.shop.purchase({ itemId: "badge-id" });
246
- await client.shop.equip("avatar-id");
247
- await client.shop.getInventory();
248
- ```
249
-
250
- #### Billing
251
-
252
- ```ts
253
- await client.billing.createSubscriptionCheckout({ cycle: "monthly" });
254
- await client.billing.createDiamondCheckout({ quantity: 1000 });
255
- await client.billing.createRoomDonationCheckout("room-id", { amountCents: 500 });
256
- await client.billing.createGlobalDonationCheckout({ amountCents: 1000 });
257
- await client.billing.createDiamondGiftCheckout({
258
- recipientUsername: "haru",
259
- quantity: 500,
260
- });
261
- await client.billing.listPendingGifts();
35
+ const rooms = await client.room.list();
36
+ console.log(rooms.data);
262
37
  ```
263
38
 
264
- #### System
39
+ ## Room bot quick start
265
40
 
266
41
  ```ts
267
- await client.system.status();
268
- await client.system.publicStats();
269
- await client.system.health();
270
- ```
271
-
272
- ## Room Bot HTTP API
273
-
274
- Room bot tokens are created from the site/session surface, then used on the bot surface.
42
+ import { createApiClient } from '@wavezfm/api';
275
43
 
276
- ```ts
277
44
  const client = createApiClient({
278
- baseURL: "https://api.wavez.fm",
279
- });
280
-
281
- const created = await client.room.createBotToken("room-id", {
282
- botName: "Night Shift Bot",
283
- commandPrefix: "!",
284
- permissions: [
285
- "read_state",
286
- "read_chat",
287
- "send_chat",
288
- "manage_queue",
289
- "skip_others",
290
- "mute_user",
291
- "kick_user",
292
- "ban_user",
293
- "clear_chat",
294
- "manage_room",
295
- ],
296
- });
297
-
298
- const roomBotToken = created.data.token;
299
-
300
- // Store this in your backend or environment store.
301
- client.api.setRoomBotToken(roomBotToken);
302
- ```
303
-
304
- Important:
305
-
306
- - the plain bot token is returned by `client.room.createBotToken(...)`
307
- - it is only available in that creation response
308
- - store it securely on your backend after creation
309
- - later, load it back with `client.api.setRoomBotToken(...)`
310
- - `manage_room` works as a broad administrative permission; granular permissions such as `manage_queue`, `ban_user`, and `clear_chat` can be used when the bot should be narrower
311
-
312
- ### Bot Resources
313
-
314
- ```ts
315
- client.api.setRoomBotToken(process.env.WAVEZ_ROOM_BOT_TOKEN!);
316
-
317
- await client.roomBot.getState("room-id");
318
- await client.roomBot.getQueueStatus("room-id");
319
- await client.roomBot.getMessages("room-id");
320
- await client.roomBot.getEvents("room-id", {
321
- limit: 25,
322
- types: ["user_joined", "waitlist_join", "left"],
323
- });
324
- await client.roomBot.addToQueue("room-id", "user-id");
325
- await client.roomBot.sendMessage("room-id", {
326
- content: "!lockqueue",
45
+ baseURL: 'https://api.wavez.fm',
46
+ roomBotToken: process.env.WAVEZFM_ROOM_BOT_TOKEN,
327
47
  });
328
- await client.roomBot.editMessage("room-id", "message-id", {
329
- content: "!lockqueue agora",
330
- });
331
- await client.roomBot.updateSettings("room-id", {
332
- queueLocked: true,
333
- commandAnnouncement: {
334
- commandId: "lockqueue",
335
- actorUsername: "Night Shift Bot",
336
- },
337
- });
338
-
339
- const state = await client.roomBot.getState("room-id");
340
- console.log(state.data.room?.description);
341
- console.log(state.data.currentUser?.globalRole);
342
- console.log(state.data.currentUser?.roomRole);
343
- ```
344
-
345
- `roomBot.getEvents()` is the normalized HTTP history surface.
346
-
347
- Returned `event` values:
348
-
349
- - `user_joined`
350
- - `waitlist_join`
351
- - `left`
352
-
353
- Accepted filter aliases in `types` for backward compatibility:
354
-
355
- - `queue_joined` -> `waitlist_join`
356
- - `user_left` -> `left`
357
-
358
- ## Room Bot Realtime API
359
48
 
360
- ```ts
361
- import {
362
- createRoomBotRealtimeClient,
363
- formatMentionText,
364
- } from "@wavezfm/api";
365
-
366
- const bot = createRoomBotRealtimeClient({
367
- baseURL: "https://api.wavez.fm",
368
- botToken: process.env.WAVEZ_ROOM_BOT_TOKEN!,
369
- roomId: "room-id",
370
- locale: "en",
371
- autoReconnect: true,
372
- });
373
-
374
- bot.on("message_created", (packet) => {
375
- console.log(packet.payload);
376
- });
49
+ const state = await client.roomBot.getState('room-id');
50
+ console.log(state.data.room);
377
51
 
378
- bot.on("queue_joined", (packet) => {
379
- console.log(packet.payload);
380
- });
381
-
382
- await bot.connect();
383
- bot.sendChat({
384
- content: `${formatMentionText("Agente MIB")} estou em modo AFK agora.`,
52
+ await client.roomBot.sendMessage('room-id', {
53
+ content: 'This live notice is not stored in chat history.',
54
+ ephemeral: true,
385
55
  });
386
56
  ```
387
57
 
388
- The realtime helper automatically retries abnormal disconnects such as WebSocket close code `1006` by default. Fatal closes like revoked or invalid auth are not retried.
389
-
390
- Important:
391
-
392
- - realtime packet names are the raw WebSocket event names
393
- - examples: `message_created`, `user_left`, `queue_joined`, `track_started`
394
- - they are not normalized to the HTTP history names
395
-
396
- ## Error Handling
58
+ Room-bot tokens are backend credentials. Never expose them in browser code, public logs, or client-side storage.
397
59
 
398
- All methods throw `ApiError` on failure.
60
+ ## Build locally
399
61
 
400
- ```ts
401
- import { ApiError } from "@wavezfm/api";
402
-
403
- try {
404
- await client.auth.login({
405
- email: "bad@example.com",
406
- password: "bad",
407
- });
408
- } catch (error) {
409
- if (error instanceof ApiError) {
410
- console.log(error.message);
411
- console.log(error.status);
412
- console.log(error.code);
413
- console.log(error.response);
414
- }
415
- }
416
- ```
417
-
418
- ## Token Management
419
-
420
- ```ts
421
- const client = createApiClient({ baseURL: "https://api.wavez.fm" });
422
-
423
- client.api.setAuthToken("optional-bearer-token");
424
- client.api.setRoomBotToken(process.env.WAVEZ_ROOM_BOT_TOKEN!);
425
-
426
- client.api.getAuthToken();
427
- client.api.getRoomBotToken();
428
- ```
429
-
430
- ## Tree-Shaking
431
-
432
- For maximum tree-shaking, import only what you need:
433
-
434
- ```ts
435
- import { createApi } from "@wavezfm/api";
436
- import { createRoomResource } from "@wavezfm/api/resources/room";
437
- import { createRoomBotResource } from "@wavezfm/api/resources/room-bot";
438
-
439
- const api = createApi({ baseURL: "https://api.wavez.fm" });
440
- const room = createRoomResource(api);
441
- const roomBot = createRoomBotResource(api);
442
- ```
443
-
444
- ## TypeScript
445
-
446
- ```ts
447
- import type {
448
- AuthUser,
449
- RoomSummary,
450
- PlaylistTrack,
451
- MediaSearchResult,
452
- ChatMessage,
453
- RoomBotState,
454
- RoomPresenceEventType,
455
- RoomPresenceEventFilterType,
456
- WsPacket,
457
- } from "@wavezfm/api";
62
+ ```bash
63
+ npm run typecheck
64
+ npm run build
458
65
  ```
459
66
 
460
- ## Notes
67
+ ## License
461
68
 
462
- - site/session routes are browser-first because the backend uses cookies and same-origin protections
463
- - room-bot HTTP routes are backend-first and scoped to one room
464
- - room-bot realtime uses raw WebSocket packet names
465
- - the package is tree-shakable through factory exports in `resources/*`
466
- - the realtime helper expects native `WebSocket` or a custom `websocketFactory`
69
+ MIT