@borealise/api 1.0.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.
package/dist/index.js ADDED
@@ -0,0 +1,623 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ Api: () => Api,
34
+ ApiError: () => ApiError,
35
+ ApiResource: () => ApiResource,
36
+ AuthResource: () => AuthResource,
37
+ ChatResource: () => ChatResource,
38
+ Logger: () => Logger,
39
+ PlaylistResource: () => PlaylistResource,
40
+ RoomResource: () => RoomResource,
41
+ SourceResource: () => SourceResource,
42
+ UserResource: () => UserResource,
43
+ authResource: () => authResource,
44
+ chatResource: () => chatResource,
45
+ playlistResource: () => playlistResource,
46
+ roomResource: () => roomResource,
47
+ sourceResource: () => sourceResource,
48
+ userResource: () => userResource
49
+ });
50
+ module.exports = __toCommonJS(index_exports);
51
+
52
+ // src/Api.ts
53
+ var import_axios = __toESM(require("axios"));
54
+
55
+ // src/Logger.ts
56
+ var Logger = class _Logger {
57
+ constructor(name, enabled = true) {
58
+ this.name = name;
59
+ this.enabled = enabled;
60
+ }
61
+ static create(name) {
62
+ return new _Logger(name);
63
+ }
64
+ enable() {
65
+ this.enabled = true;
66
+ }
67
+ disable() {
68
+ this.enabled = false;
69
+ }
70
+ log(level, message, ...args) {
71
+ if (!this.enabled) return;
72
+ const prefix = `[${this.name}]`;
73
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
74
+ switch (level) {
75
+ case "debug":
76
+ console.debug(`${timestamp} ${prefix} ${message}`, ...args);
77
+ break;
78
+ case "info":
79
+ console.info(`${timestamp} ${prefix} ${message}`, ...args);
80
+ break;
81
+ case "success":
82
+ console.log(`${timestamp} ${prefix} \u2713 ${message}`, ...args);
83
+ break;
84
+ case "error":
85
+ console.error(`${timestamp} ${prefix} \u2717 ${message}`, ...args);
86
+ break;
87
+ }
88
+ }
89
+ debug(message, ...args) {
90
+ this.log("debug", message, ...args);
91
+ }
92
+ info(message, ...args) {
93
+ this.log("info", message, ...args);
94
+ }
95
+ success(message, ...args) {
96
+ this.log("success", message, ...args);
97
+ }
98
+ error(message, ...args) {
99
+ this.log("error", message, ...args);
100
+ }
101
+ };
102
+
103
+ // src/Api.ts
104
+ var ApiError = class extends Error {
105
+ constructor(message, status, code, response) {
106
+ super(message);
107
+ this.name = "ApiError";
108
+ this.status = status;
109
+ this.code = code;
110
+ this.response = response;
111
+ }
112
+ };
113
+ var _Api = class _Api {
114
+ constructor(config) {
115
+ var _a;
116
+ this.config = config;
117
+ this.logger = Logger.create("Api");
118
+ if (config.logging === false) {
119
+ this.logger.disable();
120
+ }
121
+ this.axios = import_axios.default.create({
122
+ baseURL: config.baseURL,
123
+ timeout: (_a = config.timeout) != null ? _a : 3e4,
124
+ headers: {
125
+ "Content-Type": "application/json",
126
+ ...config.headers
127
+ }
128
+ });
129
+ this.setupInterceptors();
130
+ this.logger.success(`initialized (baseURL: ${config.baseURL})`);
131
+ }
132
+ static getInstance(config) {
133
+ if (!_Api.instance) {
134
+ if (!config) {
135
+ throw new Error('Api must be initialized with config first. Call Api.getInstance({ baseURL: "..." }) once before using resources.');
136
+ }
137
+ _Api.instance = new _Api(config);
138
+ }
139
+ return _Api.instance;
140
+ }
141
+ /** Reset the singleton (useful for testing or re-initializing with a new config) */
142
+ static reset() {
143
+ _Api.instance = null;
144
+ }
145
+ setupInterceptors() {
146
+ this.axios.interceptors.request.use(
147
+ (config) => {
148
+ var _a;
149
+ this.logger.debug(`\u2192 ${(_a = config.method) == null ? void 0 : _a.toUpperCase()} ${config.url}`);
150
+ return config;
151
+ },
152
+ (error) => {
153
+ this.logger.error("Request error", error);
154
+ return Promise.reject(error);
155
+ }
156
+ );
157
+ this.axios.interceptors.response.use(
158
+ (response) => {
159
+ this.logger.debug(`\u2190 ${response.status} ${response.config.url}`);
160
+ return response;
161
+ },
162
+ (error) => {
163
+ var _a, _b, _c;
164
+ const apiError = this.parseError(error);
165
+ const status = (_b = (_a = apiError.status) != null ? _a : apiError.code) != null ? _b : "ERR";
166
+ this.logger.error(`\u2190 ${status} ${(_c = error.config) == null ? void 0 : _c.url}: ${apiError.message}`);
167
+ return Promise.reject(apiError);
168
+ }
169
+ );
170
+ }
171
+ parseError(error) {
172
+ if (error.response) {
173
+ const responseData = error.response.data;
174
+ let message;
175
+ let backendResponse;
176
+ if (responseData && "error" in responseData && responseData.error) {
177
+ message = responseData.error;
178
+ backendResponse = responseData;
179
+ } else if (responseData && "message" in responseData && responseData.message) {
180
+ message = responseData.message;
181
+ } else {
182
+ message = error.message;
183
+ }
184
+ return new ApiError(message, error.response.status, error.code, backendResponse);
185
+ }
186
+ if (error.request) {
187
+ return new ApiError("No response received from server", void 0, "NETWORK_ERROR");
188
+ }
189
+ return new ApiError(error.message, void 0, error.code);
190
+ }
191
+ setAuthToken(token) {
192
+ if (token) {
193
+ this.axios.defaults.headers.common["Authorization"] = `Bearer ${token}`;
194
+ this.logger.debug("Auth token set");
195
+ } else {
196
+ delete this.axios.defaults.headers.common["Authorization"];
197
+ this.logger.debug("Auth token cleared");
198
+ }
199
+ }
200
+ setHeader(key, value) {
201
+ this.axios.defaults.headers.common[key] = value;
202
+ }
203
+ removeHeader(key) {
204
+ delete this.axios.defaults.headers.common[key];
205
+ }
206
+ async get(url, config) {
207
+ const response = await this.axios.get(url, config);
208
+ return this.wrapResponse(response);
209
+ }
210
+ async post(url, data, config) {
211
+ const response = await this.axios.post(url, data, config);
212
+ return this.wrapResponse(response);
213
+ }
214
+ async put(url, data, config) {
215
+ const response = await this.axios.put(url, data, config);
216
+ return this.wrapResponse(response);
217
+ }
218
+ async patch(url, data, config) {
219
+ const response = await this.axios.patch(url, data, config);
220
+ return this.wrapResponse(response);
221
+ }
222
+ async delete(url, config) {
223
+ const response = await this.axios.delete(url, config);
224
+ return this.wrapResponse(response);
225
+ }
226
+ wrapResponse(response) {
227
+ return {
228
+ data: response.data,
229
+ status: response.status,
230
+ headers: response.headers
231
+ };
232
+ }
233
+ get axiosInstance() {
234
+ return this.axios;
235
+ }
236
+ };
237
+ _Api.instance = null;
238
+ var Api = _Api;
239
+
240
+ // src/ApiResource.ts
241
+ var ApiResource = class {
242
+ constructor() {
243
+ this._logger = null;
244
+ }
245
+ get api() {
246
+ return Api.getInstance();
247
+ }
248
+ get logger() {
249
+ if (!this._logger) {
250
+ this._logger = Logger.create(this.constructor.name);
251
+ }
252
+ return this._logger;
253
+ }
254
+ buildUrl(path) {
255
+ if (path !== void 0) {
256
+ return `${this.endpoint}/${path}`;
257
+ }
258
+ return this.endpoint;
259
+ }
260
+ buildConfig(options) {
261
+ return {
262
+ params: options == null ? void 0 : options.params,
263
+ headers: options == null ? void 0 : options.headers
264
+ };
265
+ }
266
+ async index(options) {
267
+ this.logger.debug("index");
268
+ return this.api.get(this.endpoint, this.buildConfig(options));
269
+ }
270
+ async paginate(page = 1, perPage = 15, options) {
271
+ this.logger.debug(`paginate (page: ${page}, perPage: ${perPage})`);
272
+ return this.api.get(this.endpoint, {
273
+ ...this.buildConfig(options),
274
+ params: { page, per_page: perPage, ...options == null ? void 0 : options.params }
275
+ });
276
+ }
277
+ async show(id, options) {
278
+ this.logger.debug(`show (id: ${id})`);
279
+ return this.api.get(this.buildUrl(id), this.buildConfig(options));
280
+ }
281
+ async store(data, options) {
282
+ this.logger.debug("store");
283
+ return this.api.post(this.endpoint, data, this.buildConfig(options));
284
+ }
285
+ async update(id, data, options) {
286
+ this.logger.debug(`update (id: ${id})`);
287
+ return this.api.put(this.buildUrl(id), data, this.buildConfig(options));
288
+ }
289
+ async patch(id, data, options) {
290
+ this.logger.debug(`patch (id: ${id})`);
291
+ return this.api.patch(this.buildUrl(id), data, this.buildConfig(options));
292
+ }
293
+ async destroy(id, options) {
294
+ this.logger.debug(`destroy (id: ${id})`);
295
+ return this.api.delete(this.buildUrl(id), this.buildConfig(options));
296
+ }
297
+ async get(path, options) {
298
+ return this.api.get(`${this.endpoint}/${path}`, this.buildConfig(options));
299
+ }
300
+ async post(path, data, options) {
301
+ return this.api.post(`${this.endpoint}/${path}`, data, this.buildConfig(options));
302
+ }
303
+ async put(path, data, options) {
304
+ return this.api.put(`${this.endpoint}/${path}`, data, this.buildConfig(options));
305
+ }
306
+ async delete(path, options) {
307
+ return this.api.delete(`${this.endpoint}/${path}`, this.buildConfig(options));
308
+ }
309
+ };
310
+
311
+ // src/resources/AuthResource.ts
312
+ var AuthResource = class extends ApiResource {
313
+ constructor() {
314
+ super(...arguments);
315
+ this.endpoint = "/auth";
316
+ }
317
+ // POST /api/auth/login
318
+ async login(credentials) {
319
+ return this.post("login", credentials);
320
+ }
321
+ // POST /api/auth/register
322
+ async register(data) {
323
+ return this.post("register", data);
324
+ }
325
+ // POST /api/auth/refresh
326
+ async refresh(refreshToken) {
327
+ return this.post("refresh", { refreshToken });
328
+ }
329
+ // POST /api/auth/logout
330
+ async logout() {
331
+ return this.post("logout");
332
+ }
333
+ // GET /api/auth/me
334
+ async me() {
335
+ return this.get("me");
336
+ }
337
+ };
338
+ var authResource = new AuthResource();
339
+
340
+ // src/resources/UserResource.ts
341
+ var UserResource = class extends ApiResource {
342
+ constructor() {
343
+ super(...arguments);
344
+ this.endpoint = "/users";
345
+ }
346
+ // GET /api/users/:id
347
+ async getById(id) {
348
+ return this.show(id);
349
+ }
350
+ // GET /api/users/username/:username
351
+ async getByUsername(username) {
352
+ return this.get(`username/${username}`);
353
+ }
354
+ // PATCH /api/users/me
355
+ async updateProfile(data) {
356
+ return this.api.patch(`${this.endpoint}/me`, data);
357
+ }
358
+ // DELETE /api/users/me
359
+ async deleteAccount() {
360
+ return this.api.delete(`${this.endpoint}/me`);
361
+ }
362
+ };
363
+ var userResource = new UserResource();
364
+
365
+ // src/resources/RoomResource.ts
366
+ var RoomResource = class extends ApiResource {
367
+ constructor() {
368
+ super(...arguments);
369
+ this.endpoint = "/rooms";
370
+ }
371
+ // GET /api/rooms - List all rooms
372
+ async list() {
373
+ return this.get("");
374
+ }
375
+ // GET /api/rooms/featured - Get featured rooms
376
+ async featured() {
377
+ return this.get("featured");
378
+ }
379
+ // GET /api/rooms/:slug - Get room by slug
380
+ async getBySlug(slug) {
381
+ return this.get(slug);
382
+ }
383
+ // POST /api/rooms - Create a new room
384
+ async create(data) {
385
+ return this.post("", data);
386
+ }
387
+ // PATCH /api/rooms/:slug - Update room
388
+ async updateRoom(slug, data) {
389
+ return this.api.patch(`${this.endpoint}/${slug}`, data);
390
+ }
391
+ // DELETE /api/rooms/:slug - Delete room
392
+ async deleteRoom(slug) {
393
+ return this.api.delete(`${this.endpoint}/${slug}`);
394
+ }
395
+ // GET /api/rooms/:slug/staff - Get room staff
396
+ async getStaff(slug) {
397
+ return this.get(`${slug}/staff`);
398
+ }
399
+ // PUT /api/rooms/:slug/staff/:userId - Update staff role
400
+ async updateStaffRole(slug, userId, role) {
401
+ return this.api.put(`${this.endpoint}/${slug}/staff/${userId}`, { role });
402
+ }
403
+ // DELETE /api/rooms/:slug/staff/:userId - Remove staff
404
+ async removeStaff(slug, userId) {
405
+ return this.api.delete(`${this.endpoint}/${slug}/staff/${userId}`);
406
+ }
407
+ // POST /api/rooms/:slug/join - Join a room (session-based)
408
+ async join(slug) {
409
+ return this.post(`${slug}/join`);
410
+ }
411
+ // POST /api/rooms/:slug/leave - Leave a room
412
+ async leave(slug) {
413
+ return this.post(`${slug}/leave`);
414
+ }
415
+ // ============================================
416
+ // Waitlist methods
417
+ // ============================================
418
+ // GET /api/rooms/:slug/waitlist
419
+ async getWaitlist(slug) {
420
+ return this.get(`${slug}/waitlist`);
421
+ }
422
+ // POST /api/rooms/:slug/waitlist/join
423
+ async joinWaitlist(slug) {
424
+ return this.post(`${slug}/waitlist/join`);
425
+ }
426
+ // POST /api/rooms/:slug/waitlist/leave
427
+ async leaveWaitlist(slug) {
428
+ return this.post(`${slug}/waitlist/leave`);
429
+ }
430
+ // PATCH /api/rooms/:slug/waitlist - Move user in waitlist
431
+ async moveInWaitlist(slug, userId, position) {
432
+ return this.api.patch(`${this.endpoint}/${slug}/waitlist`, { userId, position });
433
+ }
434
+ // DELETE /api/rooms/:slug/waitlist/:userId - Remove user from waitlist
435
+ async removeFromWaitlist(slug, userId) {
436
+ return this.api.delete(`${this.endpoint}/${slug}/waitlist/${userId}`);
437
+ }
438
+ // POST /api/rooms/:slug/waitlist/lock
439
+ async lockWaitlist(slug) {
440
+ return this.post(`${slug}/waitlist/lock`);
441
+ }
442
+ // POST /api/rooms/:slug/waitlist/unlock
443
+ async unlockWaitlist(slug) {
444
+ return this.post(`${slug}/waitlist/unlock`);
445
+ }
446
+ // ============================================
447
+ // Booth methods
448
+ // ============================================
449
+ // GET /api/rooms/:slug/booth
450
+ async getBooth(slug) {
451
+ return this.get(`${slug}/booth`);
452
+ }
453
+ // POST /api/rooms/:slug/booth/skip
454
+ async skipTrack(slug, options) {
455
+ return this.post(`${slug}/booth/skip`, options || {});
456
+ }
457
+ // POST /api/rooms/:slug/vote
458
+ async vote(slug, type) {
459
+ return this.post(`${slug}/vote`, { type });
460
+ }
461
+ // POST /api/rooms/:slug/grab
462
+ async grabTrack(slug, playlistId) {
463
+ return this.post(`${slug}/grab`, playlistId ? { playlistId } : {});
464
+ }
465
+ };
466
+ var roomResource = new RoomResource();
467
+
468
+ // src/resources/ChatResource.ts
469
+ var ChatResource = class extends ApiResource {
470
+ constructor() {
471
+ super(...arguments);
472
+ this.endpoint = "/rooms";
473
+ }
474
+ // POST /api/rooms/:slug/chat - Send a chat message
475
+ async sendMessage(slug, data) {
476
+ return this.api.post(`${this.endpoint}/${slug}/chat`, data);
477
+ }
478
+ // GET /api/rooms/:slug/chat - Get chat history
479
+ async getMessages(slug, before, limit = 50) {
480
+ const params = { limit };
481
+ if (before) {
482
+ params.before = before;
483
+ }
484
+ return this.api.get(`${this.endpoint}/${slug}/chat`, { params });
485
+ }
486
+ // DELETE /api/rooms/:slug/chat/:messageId - Delete a chat message (moderation)
487
+ async deleteMessage(slug, messageId) {
488
+ return this.api.delete(`${this.endpoint}/${slug}/chat/${messageId}`);
489
+ }
490
+ };
491
+ var chatResource = new ChatResource();
492
+
493
+ // src/resources/PlaylistResource.ts
494
+ var PlaylistResource = class extends ApiResource {
495
+ constructor() {
496
+ super(...arguments);
497
+ this.endpoint = "/playlists";
498
+ }
499
+ // GET /api/playlists - Get all user's playlists
500
+ async getAll() {
501
+ return this.api.get(this.endpoint);
502
+ }
503
+ // GET /api/playlists/:id - Get playlist with items
504
+ async getById(playlistId) {
505
+ return this.api.get(`${this.endpoint}/${playlistId}`);
506
+ }
507
+ // POST /api/playlists - Create playlist
508
+ async create(name) {
509
+ return this.api.post(this.endpoint, { name });
510
+ }
511
+ // PATCH /api/playlists/:id - Update playlist
512
+ async rename(playlistId, name) {
513
+ return this.api.patch(`${this.endpoint}/${playlistId}`, { name });
514
+ }
515
+ // DELETE /api/playlists/:id - Delete playlist
516
+ async remove(playlistId) {
517
+ return this.api.delete(`${this.endpoint}/${playlistId}`);
518
+ }
519
+ // POST /api/playlists/:id/activate - Activate playlist
520
+ async activate(playlistId) {
521
+ return this.api.post(`${this.endpoint}/${playlistId}/activate`);
522
+ }
523
+ // POST /api/playlists/:id/shuffle - Shuffle playlist
524
+ async shuffle(playlistId) {
525
+ return this.api.post(`${this.endpoint}/${playlistId}/shuffle`);
526
+ }
527
+ // POST /api/playlists/:id/items - Add item to playlist
528
+ async addItem(playlistId, data) {
529
+ return this.api.post(`${this.endpoint}/${playlistId}/items`, data);
530
+ }
531
+ // DELETE /api/playlists/:id/items/:itemId - Remove item from playlist
532
+ async removeItem(playlistId, itemId) {
533
+ return this.api.delete(`${this.endpoint}/${playlistId}/items/${itemId}`);
534
+ }
535
+ // PATCH /api/playlists/:id/items/:itemId/move - Move item in playlist
536
+ async moveItem(playlistId, itemId, position) {
537
+ return this.api.patch(`${this.endpoint}/${playlistId}/items/${itemId}/move`, { position });
538
+ }
539
+ // POST /api/playlists/:id/import - Import from YouTube/SoundCloud playlist
540
+ async importPlaylist(playlistId, data) {
541
+ return this.api.post(`${this.endpoint}/${playlistId}/import`, data);
542
+ }
543
+ };
544
+ var playlistResource = new PlaylistResource();
545
+
546
+ // src/resources/SourceResource.ts
547
+ var SourceResource = class extends ApiResource {
548
+ constructor() {
549
+ super(...arguments);
550
+ this.endpoint = "/sources";
551
+ }
552
+ // ============================================
553
+ // YouTube
554
+ // ============================================
555
+ // GET /api/sources/youtube/search?q=...&limit=...
556
+ async searchYouTube(query, limit = 10) {
557
+ return this.api.get(`${this.endpoint}/youtube/search`, {
558
+ params: { q: query, limit }
559
+ });
560
+ }
561
+ // GET /api/sources/youtube/videos/:videoId
562
+ async getYouTubeVideo(videoId) {
563
+ return this.api.get(`${this.endpoint}/youtube/videos/${videoId}`);
564
+ }
565
+ // ============================================
566
+ // SoundCloud
567
+ // ============================================
568
+ // GET /api/sources/soundcloud/search?q=...&limit=...
569
+ async searchSoundCloud(query, limit = 10) {
570
+ return this.api.get(`${this.endpoint}/soundcloud/search`, {
571
+ params: { q: query, limit }
572
+ });
573
+ }
574
+ // GET /api/sources/soundcloud/tracks/:trackId
575
+ async getSoundCloudTrack(trackId) {
576
+ return this.api.get(`${this.endpoint}/soundcloud/tracks/${trackId}`);
577
+ }
578
+ // GET /api/sources/soundcloud/resolve?url=...
579
+ async resolveSoundCloudUrl(url) {
580
+ return this.api.get(`${this.endpoint}/soundcloud/resolve`, {
581
+ params: { url }
582
+ });
583
+ }
584
+ // ============================================
585
+ // Combined search (helper)
586
+ // ============================================
587
+ // Search both YouTube and SoundCloud
588
+ async searchAll(query, limit = 10) {
589
+ var _a, _b, _c, _d;
590
+ const [youtube, soundcloud] = await Promise.allSettled([
591
+ this.searchYouTube(query, limit),
592
+ this.searchSoundCloud(query, limit)
593
+ ]);
594
+ const results = [];
595
+ if (youtube.status === "fulfilled" && ((_b = (_a = youtube.value.data) == null ? void 0 : _a.data) == null ? void 0 : _b.results)) {
596
+ results.push(...youtube.value.data.data.results);
597
+ }
598
+ if (soundcloud.status === "fulfilled" && ((_d = (_c = soundcloud.value.data) == null ? void 0 : _c.data) == null ? void 0 : _d.results)) {
599
+ results.push(...soundcloud.value.data.data.results);
600
+ }
601
+ return results;
602
+ }
603
+ };
604
+ var sourceResource = new SourceResource();
605
+ // Annotate the CommonJS export names for ESM import in node:
606
+ 0 && (module.exports = {
607
+ Api,
608
+ ApiError,
609
+ ApiResource,
610
+ AuthResource,
611
+ ChatResource,
612
+ Logger,
613
+ PlaylistResource,
614
+ RoomResource,
615
+ SourceResource,
616
+ UserResource,
617
+ authResource,
618
+ chatResource,
619
+ playlistResource,
620
+ roomResource,
621
+ sourceResource,
622
+ userResource
623
+ });