@ctrl/plex 3.10.0 → 3.12.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.
@@ -13,7 +13,13 @@ import { PlexServer } from './server.js';
13
13
  * and return this object.
14
14
  */
15
15
  export class MyPlexAccount {
16
- static { this.key = 'https://plex.tv/api/v2/user'; }
16
+ baseUrl;
17
+ username;
18
+ password;
19
+ token;
20
+ timeout;
21
+ server;
22
+ static key = 'https://plex.tv/api/v2/user';
17
23
  /**
18
24
  * This follows the outline described in https://forums.plex.tv/t/authenticating-with-plex/609370
19
25
  * to fetch a token and potentially compromise username and password. To use first call `getWebLogin()`
@@ -37,7 +43,7 @@ export class MyPlexAccount {
37
43
  });
38
44
  return {
39
45
  ...pin,
40
- uri: `https://app.plex.tv/auth#?clientID=${encodeURIComponent(clientIdentifier)}&code=${encodeURIComponent(pin.code)}&context%5Bdevice%5D%5Bproduct%5D=${encodeURIComponent(appName)}${forwardUrl ? '&forwardUrl=' + encodeURIComponent(forwardUrl) : ''}`,
46
+ uri: `https://app.plex.tv/auth#?clientID=${encodeURIComponent(clientIdentifier)}&code=${encodeURIComponent(pin.code)}&context%5Bdevice%5D%5Bproduct%5D=${encodeURIComponent(appName)}${forwardUrl ? `&forwardUrl=${encodeURIComponent(forwardUrl)}` : ''}`,
41
47
  };
42
48
  }
43
49
  /**
@@ -79,6 +85,18 @@ export class MyPlexAccount {
79
85
  }
80
86
  throw new Error('Failed to authenticate before timeout');
81
87
  }
88
+ FRIENDINVITE = 'https://plex.tv/api/servers/{machineId}/shared_servers'; // post with data
89
+ HOMEUSERCREATE = 'https://plex.tv/api/home/users?title={title}'; // post with data
90
+ EXISTINGUSER = 'https://plex.tv/api/home/users?invitedEmail={username}'; // post with data
91
+ FRIENDSERVERS = 'https://plex.tv/api/servers/{machineId}/shared_servers/{serverId}'; // put with data
92
+ PLEXSERVERS = 'https://plex.tv/api/servers/{machineId}'; // get
93
+ FRIENDUPDATE = 'https://plex.tv/api/friends/{userId}'; // put with args, delete
94
+ REMOVEHOMEUSER = 'https://plex.tv/api/home/users/{userId}'; // delete
95
+ REMOVEINVITE = 'https://plex.tv/api/invites/requested/{userId}?friend=0&server=1&home=0'; // delete
96
+ REQUESTED = 'https://plex.tv/api/invites/requested'; // get
97
+ REQUESTS = 'https://plex.tv/api/invites/requests'; // get
98
+ SIGNIN = 'https://plex.tv/users/sign_in.json'; // get with auth
99
+ WEBHOOKS = 'https://plex.tv/api/v2/user/webhooks'; // get, post with data
82
100
  /**
83
101
  *
84
102
  * @param username Your MyPlex username
@@ -95,18 +113,6 @@ export class MyPlexAccount {
95
113
  this.token = token;
96
114
  this.timeout = timeout;
97
115
  this.server = server;
98
- this.FRIENDINVITE = 'https://plex.tv/api/servers/{machineId}/shared_servers'; // post with data
99
- this.HOMEUSERCREATE = 'https://plex.tv/api/home/users?title={title}'; // post with data
100
- this.EXISTINGUSER = 'https://plex.tv/api/home/users?invitedEmail={username}'; // post with data
101
- this.FRIENDSERVERS = 'https://plex.tv/api/servers/{machineId}/shared_servers/{serverId}'; // put with data
102
- this.PLEXSERVERS = 'https://plex.tv/api/servers/{machineId}'; // get
103
- this.FRIENDUPDATE = 'https://plex.tv/api/friends/{userId}'; // put with args, delete
104
- this.REMOVEHOMEUSER = 'https://plex.tv/api/home/users/{userId}'; // delete
105
- this.REMOVEINVITE = 'https://plex.tv/api/invites/requested/{userId}?friend=0&server=1&home=0'; // delete
106
- this.REQUESTED = 'https://plex.tv/api/invites/requested'; // get
107
- this.REQUESTS = 'https://plex.tv/api/invites/requests'; // get
108
- this.SIGNIN = 'https://plex.tv/users/sign_in.json'; // get with auth
109
- this.WEBHOOKS = 'https://plex.tv/api/v2/user/webhooks'; // get, post with data
110
116
  if (this.token) {
111
117
  Object.defineProperty(this, 'token', {
112
118
  enumerable: false,
@@ -214,7 +220,7 @@ export class MyPlexAccount {
214
220
  */
215
221
  async claimToken() {
216
222
  const url = 'https://plex.tv/api/claim/token.json';
217
- const response = await this.query(url, 'get', undefined);
223
+ const response = await this.query(url, 'get');
218
224
  return response.token;
219
225
  }
220
226
  /**
@@ -292,11 +298,13 @@ async function connect(cls, url, token, timeout) {
292
298
  * content such as Plex Media Servers, iPhone or Android clients, etc.
293
299
  */
294
300
  export class MyPlexResource {
295
- static { this.key = 'https://plex.tv/api/v2/resources?includeHttps=1&includeRelay=1'; }
301
+ account;
302
+ baseUrl;
303
+ static key = 'https://plex.tv/api/v2/resources?includeHttps=1&includeRelay=1';
304
+ TAG = 'Device';
296
305
  constructor(account, data, baseUrl = null) {
297
306
  this.account = account;
298
307
  this.baseUrl = baseUrl;
299
- this.TAG = 'Device';
300
308
  this._loadData(data);
301
309
  }
302
310
  async connect(ssl = null, timeout) {
@@ -354,8 +362,8 @@ export class MyPlexResource {
354
362
  }
355
363
  }
356
364
  export class ResourceConnection {
365
+ TAG = 'Connection';
357
366
  constructor(data) {
358
- this.TAG = 'Connection';
359
367
  this._loadData(data);
360
368
  }
361
369
  _loadData(data) {
@@ -374,8 +382,8 @@ export class ResourceConnection {
374
382
  * https://plex.tv/devices.xml
375
383
  */
376
384
  export class MyPlexDevice extends PlexObject {
377
- static { this.TAG = 'Device'; }
378
- static { this.key = 'https://plex.tv/devices.xml'; }
385
+ static TAG = 'Device';
386
+ static key = 'https://plex.tv/devices.xml';
379
387
  async connect() {
380
388
  // TODO: switch between PlexServer and PlexClient
381
389
  // Try connecting to all known resource connections in parellel, but
@@ -414,8 +422,8 @@ export class MyPlexDevice extends PlexObject {
414
422
  });
415
423
  this.screenResolution = data.$.screenResolution;
416
424
  this.screenDensity = data.$.screenDensity;
417
- this.createdAt = new Date(parseInt(data.$.createdAt, 10));
418
- this.lastSeenAt = new Date(parseInt(data.$.lastSeenAt, 10));
425
+ this.createdAt = new Date(Number.parseInt(data.$.createdAt, 10));
426
+ this.lastSeenAt = new Date(Number.parseInt(data.$.lastSeenAt, 10));
419
427
  this.connections = data.Connection?.map(connection => connection.$.uri);
420
428
  }
421
429
  }
@@ -1,4 +1,4 @@
1
- import { URLSearchParams } from 'url';
1
+ import { URLSearchParams } from 'node:url';
2
2
  import { Playable } from './base/playable.js';
3
3
  import { Album, Artist, Track } from './audio.js';
4
4
  import { fetchItems } from './baseFunctionality.js';
@@ -9,28 +9,28 @@ import { Episode, Movie } from './video.js';
9
9
  */
10
10
  function contentClass(data) {
11
11
  switch (data.type) {
12
- case 'episode':
12
+ case 'episode': {
13
13
  return Episode;
14
- case 'movie':
14
+ }
15
+ case 'movie': {
15
16
  return Movie;
16
- case 'track':
17
+ }
18
+ case 'track': {
17
19
  return Track;
18
- case 'album':
20
+ }
21
+ case 'album': {
19
22
  return Album;
20
- case 'artist':
23
+ }
24
+ case 'artist': {
21
25
  return Artist;
22
- default:
26
+ }
27
+ default: {
23
28
  throw new Error(`Media type '${data.type}' not implemented`);
29
+ }
24
30
  }
25
31
  }
26
32
  export class Playlist extends Playable {
27
- constructor() {
28
- super(...arguments);
29
- this.TYPE = 'playlist';
30
- /** Cache of playlist items */
31
- this._items = null;
32
- }
33
- static { this.TAG = 'Playlist'; }
33
+ static TAG = 'Playlist';
34
34
  static async create(server, title, options) {
35
35
  if (options.smart) {
36
36
  throw new Error('not yet supported');
@@ -86,6 +86,9 @@ export class Playlist extends Playable {
86
86
  const data = await server.query(key, 'post');
87
87
  return new Playlist(server, data.MediaContainer.Metadata[0], key);
88
88
  }
89
+ TYPE = 'playlist';
90
+ /** Cache of playlist items */
91
+ _items = null;
89
92
  async _edit(args) {
90
93
  const searchparams = new URLSearchParams(args);
91
94
  const key = `${this.key}?${searchparams.toString()}`;
@@ -99,7 +102,7 @@ export class Playlist extends Playable {
99
102
  */
100
103
  async item(title) {
101
104
  const items = await this.items();
102
- const matched = items.find(item => item.title.toLowerCase() === title.toLowerCase());
105
+ const matched = items.find(item => item.title?.toLowerCase() === title.toLowerCase());
103
106
  return matched ?? null;
104
107
  }
105
108
  async items() {
@@ -9,13 +9,10 @@ import { BadRequest } from './exceptions.js';
9
9
  * removing, and reordering items.
10
10
  */
11
11
  export class PlayQueue extends PlexObject {
12
- constructor() {
13
- super(...arguments);
14
- /** Cache of PlayQueue items */
15
- this._items = null;
16
- }
17
- static { this.TAG = 'PlayQueue'; }
18
- static { this.TYPE = 'playqueue'; }
12
+ static TAG = 'PlayQueue';
13
+ static TYPE = 'playqueue';
14
+ /** Cache of PlayQueue items */
15
+ _items = null;
19
16
  /**
20
17
  * Retrieve an existing PlayQueue by identifier.
21
18
  */
@@ -258,7 +255,7 @@ export class PlayQueue extends PlexObject {
258
255
  this.playQueueSourceURI = data.playQueueSourceURI;
259
256
  this.playQueueTotalCount = data.playQueueTotalCount;
260
257
  this.playQueueVersion = data.playQueueVersion;
261
- this.size = data.size || this.playQueueTotalCount;
258
+ this.size = data.size > 0 ? data.size : this.playQueueTotalCount;
262
259
  // selectedItem will be set lazily when accessing items
263
260
  }
264
261
  _invalidateCacheAndLoadData(data) {
@@ -1,7 +1,7 @@
1
1
  import { PlexObject } from './base/plexObject.js';
2
2
  import { rsplit } from './util.js';
3
3
  export class SearchResult extends PlexObject {
4
- static { this.TAG = 'SearchResult'; }
4
+ static TAG = 'SearchResult';
5
5
  _loadData(data) {
6
6
  this.guid = data.guid;
7
7
  this.lifespanEnded = data.lifespanEnded;
@@ -14,7 +14,7 @@ export class SearchResult extends PlexObject {
14
14
  * Represents a single Agent
15
15
  */
16
16
  export class Agent extends PlexObject {
17
- static { this.TAG = 'Agent'; }
17
+ static TAG = 'Agent';
18
18
  // languageCode: any[] = [];
19
19
  _loadData(data) {
20
20
  this.hasAttribution = data.hasAttribution;
@@ -1,4 +1,4 @@
1
- import { URL, URLSearchParams } from 'url';
1
+ import { URL, URLSearchParams } from 'node:url';
2
2
  import { Playable } from './base/playable.js';
3
3
  import { PlexClient } from './client.js';
4
4
  import { Hub, Library } from './library.js';
@@ -1,5 +1,5 @@
1
+ import { URL, URLSearchParams } from 'node:url';
1
2
  import { ofetch } from 'ofetch';
2
- import { URL, URLSearchParams } from 'url';
3
3
  import { fetchItem, fetchItems } from './baseFunctionality.js';
4
4
  import { PlexClient } from './client.js';
5
5
  import { BASE_HEADERS, TIMEOUT, X_PLEX_CONTAINER_SIZE } from './config.js';
@@ -17,6 +17,13 @@ import { Settings } from './settings.js';
17
17
  * can also create an PlexServer instance from :class:`~plexapi.myplex.MyPlexAccount`.
18
18
  */
19
19
  export class PlexServer {
20
+ baseurl;
21
+ token;
22
+ timeout;
23
+ key = '/';
24
+ _library;
25
+ _settings;
26
+ _myPlexAccount;
20
27
  constructor(baseurl, token,
21
28
  /**
22
29
  * Default request timeout in milliseconds.
@@ -26,7 +33,6 @@ export class PlexServer {
26
33
  this.baseurl = baseurl;
27
34
  this.token = token;
28
35
  this.timeout = timeout;
29
- this.key = '/';
30
36
  }
31
37
  async agents(mediaType) {
32
38
  let key = '/system/agents';
@@ -87,7 +93,7 @@ export class PlexServer {
87
93
  if (limit) {
88
94
  params.limit = limit.toString();
89
95
  }
90
- const key = '/hubs/search?' + new URLSearchParams(params).toString();
96
+ const key = `/hubs/search?${new URLSearchParams(params).toString()}`;
91
97
  const hubs = await fetchItems(this, key, undefined, Hub, this);
92
98
  return hubs;
93
99
  }
@@ -131,7 +137,7 @@ export class PlexServer {
131
137
  * @param accountId request history for a specific account ID.
132
138
  * @param librarySectionId request history for a specific library section ID.
133
139
  */
134
- async history(maxresults = 9999999, mindate, ratingKey, accountId, librarySectionId) {
140
+ async history(maxresults = 9_999_999, mindate, ratingKey, accountId, librarySectionId) {
135
141
  const args = { sort: 'viewedAt:desc' };
136
142
  if (ratingKey !== undefined) {
137
143
  args.metadataItemID = ratingKey.toString();
@@ -148,21 +154,21 @@ export class PlexServer {
148
154
  args['X-Plex-Container-Start'] = '0';
149
155
  args['X-Plex-Container-Size'] = Math.min(X_PLEX_CONTAINER_SIZE, maxresults).toString();
150
156
  let results = [];
151
- let key = '/status/sessions/history/all?' + new URLSearchParams(args).toString();
157
+ let key = `/status/sessions/history/all?${new URLSearchParams(args).toString()}`;
152
158
  let raw = await this.query(key);
153
159
  const totalResults = raw.MediaContainer.totalSize;
154
160
  // Filter out null/undefined items from the metadata
155
161
  const validMetadata = raw.MediaContainer.Metadata?.filter(Boolean) ?? [];
156
- results = results.concat(validMetadata);
162
+ results.push(...validMetadata);
157
163
  while (results.length <= totalResults &&
158
164
  X_PLEX_CONTAINER_SIZE === raw.MediaContainer.size &&
159
165
  maxresults > results.length) {
160
166
  args['X-Plex-Container-Start'] = (Number(args['X-Plex-Container-Start']) + Number(args['X-Plex-Container-Size'])).toString();
161
- key = '/status/sessions/history/all?' + new URLSearchParams(args).toString();
167
+ key = `/status/sessions/history/all?${new URLSearchParams(args).toString()}`;
162
168
  raw = await this.query(key);
163
169
  // Filter out null/undefined items from the metadata
164
170
  const validMetadata = raw.MediaContainer.Metadata?.filter(item => item != null) ?? [];
165
- results = results.concat(validMetadata);
171
+ results.push(...validMetadata);
166
172
  }
167
173
  return results;
168
174
  }
@@ -1,4 +1,4 @@
1
- import { URLSearchParams } from 'url';
1
+ import { URLSearchParams } from 'node:url';
2
2
  import { PlexObject } from './base/plexObject.js';
3
3
  import { NotFound } from './exceptions.js';
4
4
  import { lowerFirst } from './util.js';
@@ -22,11 +22,8 @@ var Type;
22
22
  Type["Text"] = "text";
23
23
  })(Type || (Type = {}));
24
24
  export class Settings extends PlexObject {
25
- constructor() {
26
- super(...arguments);
27
- this._data = [];
28
- }
29
- static { this.key = '/:/prefs'; }
25
+ static key = '/:/prefs';
26
+ _data = [];
30
27
  all() {
31
28
  return Object.entries(this._settings)
32
29
  .sort((a, b) => a[0].localeCompare(b[0]))
@@ -70,17 +67,14 @@ export class Settings extends PlexObject {
70
67
  * Represents a single Plex setting
71
68
  */
72
69
  export class Setting extends PlexObject {
73
- constructor() {
74
- super(...arguments);
75
- this._setValue = null;
76
- }
70
+ _setValue = null;
77
71
  /**
78
72
  * Set a new value for this setitng. NOTE: You must call {@link Settings.save} before
79
73
  * any changes to setting values are persisted to the PlexServer.
80
74
  */
81
75
  set(value) {
82
76
  if (typeof value !== typeof this.value) {
83
- throw new Error('Invalid type');
77
+ throw new TypeError('Invalid type');
84
78
  }
85
79
  this._setValue = value;
86
80
  }
@@ -99,11 +93,8 @@ export class Setting extends PlexObject {
99
93
  }
100
94
  }
101
95
  export class Preferences extends Setting {
102
- constructor() {
103
- super(...arguments);
104
- this.FILTER = 'preferences';
105
- }
106
- static { this.TAG = 'Preferences'; }
96
+ static TAG = 'Preferences';
97
+ FILTER = 'preferences';
107
98
  }
108
99
  // class Setting(PlexObject):
109
100
  // """ Represents a single Plex setting.
@@ -10,11 +10,11 @@ export interface MetadataContainer<T extends {
10
10
  export declare function rsplit(str: string, sep: string, maxsplit: number): string[];
11
11
  /**
12
12
  * Return the full agent identifier from a short identifier, name, or confirm full identifier.
13
- * @param section
14
- * @param agent
15
13
  */
16
14
  export declare function getAgentIdentifier(section: Section, agent: string): Promise<string>;
17
- /** Simple tag helper for editing a object. */
15
+ /**
16
+ * Simple tag helper for editing a object.
17
+ */
18
18
  export declare function tagHelper(tag: string, items: string[], locked?: boolean, remove?: boolean): Record<string, string | number>;
19
19
  export declare function ltrim(x: string, characters: string[]): string;
20
20
  export declare function lowerFirst(str: string): string;
package/dist/src/util.js CHANGED
@@ -1,11 +1,12 @@
1
1
  export function rsplit(str, sep, maxsplit) {
2
2
  const split = str.split(sep);
3
- return maxsplit ? [split.slice(0, -maxsplit).join(sep)].concat(split.slice(-maxsplit)) : split;
3
+ if (maxsplit) {
4
+ return [split.slice(0, -maxsplit).join(sep), ...split.slice(-maxsplit)];
5
+ }
6
+ return split;
4
7
  }
5
8
  /**
6
9
  * Return the full agent identifier from a short identifier, name, or confirm full identifier.
7
- * @param section
8
- * @param agent
9
10
  */
10
11
  export async function getAgentIdentifier(section, agent) {
11
12
  const agents = [];
@@ -14,11 +15,13 @@ export async function getAgentIdentifier(section, agent) {
14
15
  if (identifiers.includes(agent)) {
15
16
  return ag.identifier;
16
17
  }
17
- agents.concat(identifiers);
18
+ agents.push(...identifiers);
18
19
  }
19
20
  throw new Error(`Couldnt find "${agent}" in agents list (${agents.join(', ')})`);
20
21
  }
21
- /** Simple tag helper for editing a object. */
22
+ /**
23
+ * Simple tag helper for editing a object.
24
+ */
22
25
  export function tagHelper(tag, items, locked = true, remove = false) {
23
26
  const data = {};
24
27
  if (remove) {
@@ -40,9 +43,8 @@ export function ltrim(x, characters) {
40
43
  while (characters.includes(x[start])) {
41
44
  start += 1;
42
45
  }
43
- const end = x.length - 1;
44
- return x.substr(start, end);
46
+ return x.slice(start);
45
47
  }
46
48
  export function lowerFirst(str) {
47
- return str.charAt(0).toUpperCase() + str.slice(1);
49
+ return str.charAt(0).toLowerCase() + str.slice(1);
48
50
  }
@@ -1,4 +1,4 @@
1
- import type { URL } from 'url';
1
+ import type { URL } from 'node:url';
2
2
  import { Playable } from './base/playable.js';
3
3
  import type { ExtrasData, FullShowData, MovieData, ShowData } from './library.types.js';
4
4
  import { Chapter, Collection, Country, Director, Genre, Guid, Marker, Media, Poster, Producer, Rating, Role, Similar, Writer } from './media.js';
package/dist/src/video.js CHANGED
@@ -2,11 +2,8 @@ import { Playable } from './base/playable.js';
2
2
  import { fetchItem, fetchItems, findItems } from './baseFunctionality.js';
3
3
  import { Chapter, Collection, Country, Director, Genre, Guid, Marker, Media, Poster, Producer, Rating, Role, Similar, Writer, } from './media.js';
4
4
  class Video extends Playable {
5
- constructor() {
6
- super(...arguments);
7
- /** Hardcoded as 'video' (useful for search filters). */
8
- this.listType = 'video';
9
- }
5
+ /** Hardcoded as 'video' (useful for search filters). */
6
+ listType = 'video';
10
7
  /**
11
8
  * Returns True if this video is watched.
12
9
  */
@@ -109,12 +106,9 @@ class Video extends Playable {
109
106
  * Represents a single Movie.
110
107
  */
111
108
  export class Movie extends Video {
112
- constructor() {
113
- super(...arguments);
114
- this.TAG = 'Video';
115
- this.TYPE = 'movie';
116
- this.METADATA_TYPE = 'movie';
117
- }
109
+ TAG = 'Video';
110
+ TYPE = 'movie';
111
+ METADATA_TYPE = 'movie';
118
112
  get actors() {
119
113
  return this.roles;
120
114
  }
@@ -190,12 +184,9 @@ export class Movie extends Video {
190
184
  * Represents a single Show (including all seasons and episodes).
191
185
  */
192
186
  export class Show extends Video {
193
- constructor() {
194
- super(...arguments);
195
- this.TAG = 'Directory';
196
- this.TYPE = 'show';
197
- this.METADATA_TYPE = 'episode';
198
- }
187
+ TAG = 'Directory';
188
+ TYPE = 'show';
189
+ METADATA_TYPE = 'episode';
199
190
  /** <:class:`~plexapi.media.Similar`>): List of Similar objects. */
200
191
  // similar: List;
201
192
  /**
@@ -256,12 +247,9 @@ export class Show extends Video {
256
247
  * Represents a single Show Season (including all episodes).
257
248
  */
258
249
  export class Season extends Video {
259
- constructor() {
260
- super(...arguments);
261
- this.TAG = 'Directory';
262
- this.TYPE = 'season';
263
- this.METADATA_TYPE = 'episode';
264
- }
250
+ TAG = 'Directory';
251
+ TYPE = 'season';
252
+ METADATA_TYPE = 'episode';
265
253
  /** Returns season number */
266
254
  get seasonNumber() {
267
255
  return this.index;
@@ -290,12 +278,9 @@ export class Season extends Video {
290
278
  }
291
279
  }
292
280
  export class Episode extends Video {
293
- constructor() {
294
- super(...arguments);
295
- this.TYPE = 'episode';
296
- this.METADATA_TYPE = 'episode';
297
- }
298
- static { this.TAG = 'Video'; }
281
+ static TAG = 'Video';
282
+ TYPE = 'episode';
283
+ METADATA_TYPE = 'episode';
299
284
  /**
300
285
  * Returns this episodes season number.
301
286
  */
@@ -380,12 +365,9 @@ export class Episode extends Video {
380
365
  }
381
366
  }
382
367
  export class Clip extends Video {
383
- constructor() {
384
- super(...arguments);
385
- this.TYPE = 'clip';
386
- this.METADATA_TYPE = 'clip';
387
- }
388
- static { this.TAG = 'Video'; }
368
+ static TAG = 'Video';
369
+ TYPE = 'clip';
370
+ METADATA_TYPE = 'clip';
389
371
  _loadData(data) {
390
372
  super._loadData(data);
391
373
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ctrl/plex",
3
- "version": "3.10.0",
3
+ "version": "3.12.0",
4
4
  "description": "plex api client in typescript using ofetch",
5
5
  "author": "Scott Cooper <scttcper@gmail.com>",
6
6
  "publishConfig": {
@@ -34,33 +34,33 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "@ctrl/mac-address": "^3.1.0",
37
- "ofetch": "^1.4.1",
37
+ "ofetch": "^1.5.1",
38
38
  "p-any": "^4.0.0",
39
- "type-fest": "^5.0.1",
39
+ "type-fest": "^5.3.1",
40
40
  "ws": "^8.18.3",
41
41
  "xml2js": "^0.6.2"
42
42
  },
43
43
  "devDependencies": {
44
- "@ctrl/oxlint-config": "1.2.8",
44
+ "@ctrl/oxlint-config": "1.3.3",
45
45
  "@ctrl/video-filename-parser": "5.4.1",
46
- "@sindresorhus/tsconfig": "8.0.1",
47
- "@trivago/prettier-plugin-sort-imports": "5.2.2",
48
- "@types/node": "24.7.2",
46
+ "@sindresorhus/tsconfig": "8.1.0",
47
+ "@trivago/prettier-plugin-sort-imports": "6.0.0",
48
+ "@types/node": "25.0.3",
49
49
  "@types/ws": "8.18.1",
50
50
  "@types/xml2js": "0.4.14",
51
- "@types/yargs": "17.0.33",
52
- "@vitest/coverage-v8": "3.2.4",
53
- "execa": "9.6.0",
54
- "globby": "15.0.0",
51
+ "@types/yargs": "17.0.35",
52
+ "@vitest/coverage-v8": "4.0.16",
53
+ "execa": "9.6.1",
54
+ "globby": "16.1.0",
55
55
  "make-dir": "5.1.0",
56
56
  "ora": "9.0.0",
57
- "oxlint": "1.22.0",
58
- "p-retry": "7.1.0",
59
- "prettier": "3.6.2",
60
- "tsx": "4.20.6",
61
- "typedoc": "0.28.14",
57
+ "oxlint": "1.35.0",
58
+ "p-retry": "7.1.1",
59
+ "prettier": "3.7.4",
60
+ "tsx": "4.21.0",
61
+ "typedoc": "0.28.15",
62
62
  "typescript": "5.9.3",
63
- "vitest": "3.2.4",
63
+ "vitest": "4.0.16",
64
64
  "yargs": "18.0.0"
65
65
  },
66
66
  "release": {
@@ -91,5 +91,5 @@
91
91
  "engines": {
92
92
  "node": ">=18"
93
93
  },
94
- "packageManager": "pnpm@10.18.2"
94
+ "packageManager": "pnpm@10.26.1"
95
95
  }