@freqhole/api-client 0.3.1 → 0.3.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@freqhole/api-client",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -261,6 +261,7 @@ export const routes = {
261
261
  query_video_series: { method: 'POST', path: '/api/video/series/query', req: s.QueryParamsSchema, resp: s.SeriesQueryResultSchema, auth: { type: 'authenticated' } as const },
262
262
  query_videos: { method: 'POST', path: '/api/video/videos/query', req: s.QueryVideosRequestSchema, resp: s.VideosQueryResultSchema, auth: { type: 'authenticated' } as const },
263
263
  recently_added_videos: { method: 'POST', path: '/api/video/relations/recently-added-videos', req: s.RecentlyAddedVideosRequestSchema, resp: s.RecentlyAddedVideosResponseSchema, auth: { type: 'authenticated' } as const },
264
+ reprocess_video: { method: 'POST', path: '/api/video/videos/reprocess', req: s.ReprocessVideoRequestSchema, resp: s.ReprocessVideoResultSchema, auth: { type: 'role', role: 'admin' } as const },
264
265
  sync_video_by_blake3: { method: 'POST', path: '/api/sync/video-by-blake3', req: s.SyncVideoByBlake3RequestSchema, resp: s.SyncVideoByBlake3ResponseSchema, auth: { type: 'role', role: 'member' } as const },
265
266
  unassigned_videos: { method: 'POST', path: '/api/video/relations/unassigned-videos', req: s.UnassignedVideosRequestSchema, resp: s.UnassignedVideosResponseSchema, auth: { type: 'authenticated' } as const },
266
267
  update_video_season: { method: 'POST', path: '/api/video/seasons/update', req: s.UpdateVideoSeasonRequestSchema, resp: s.VideoSeasonSchema, auth: { type: 'role', role: 'admin' } as const },
@@ -2340,6 +2340,8 @@ export const FavoriteItemSchema = z.union([z.intersection(z.object({
2340
2340
  title: z.string(),
2341
2341
  description: z.string().nullish(),
2342
2342
  is_public: z.number(),
2343
+ collaborative: z.number(),
2344
+ private: z.number(),
2343
2345
  images: z.array(z.object({
2344
2346
  blob_id: z.string(),
2345
2347
  is_primary: z.number(),
@@ -2357,6 +2359,7 @@ export const FavoriteItemSchema = z.union([z.intersection(z.object({
2357
2359
  deleted_by: z.string().nullish(),
2358
2360
  created_by: z.string().nullish(),
2359
2361
  updated_by: z.string().nullish(),
2362
+ created_by_username: z.string().nullish(),
2360
2363
  song_count: z.number()
2361
2364
  }),
2362
2365
  song_count: z.number(),
@@ -2420,6 +2423,8 @@ export const FavoritePlaylistResultSchema = z.object({
2420
2423
  title: z.string(),
2421
2424
  description: z.string().nullish(),
2422
2425
  is_public: z.number(),
2426
+ collaborative: z.number(),
2427
+ private: z.number(),
2423
2428
  images: z.array(z.object({
2424
2429
  blob_id: z.string(),
2425
2430
  is_primary: z.number(),
@@ -2437,6 +2442,7 @@ export const FavoritePlaylistResultSchema = z.object({
2437
2442
  deleted_by: z.string().nullish(),
2438
2443
  created_by: z.string().nullish(),
2439
2444
  updated_by: z.string().nullish(),
2445
+ created_by_username: z.string().nullish(),
2440
2446
  song_count: z.number()
2441
2447
  }),
2442
2448
  song_count: z.number(),
@@ -3246,6 +3252,11 @@ export const JobStateSnapshotSchema = z.object({
3246
3252
  created_by: z.string().nullish(),
3247
3253
  last_stage: z.string().nullish(),
3248
3254
  last_message: z.string().nullish(),
3255
+ errors: z.array(z.object({
3256
+ error_type: z.string(),
3257
+ title: z.string(),
3258
+ detail: z.string()
3259
+ })).nullish(),
3249
3260
  updated_at: z.number()
3250
3261
  });
3251
3262
  export type JobStateSnapshot = z.infer<typeof JobStateSnapshotSchema>;
@@ -3625,6 +3636,8 @@ export const ListFavoritesResponseSchema = z.object({
3625
3636
  title: z.string(),
3626
3637
  description: z.string().nullish(),
3627
3638
  is_public: z.number(),
3639
+ collaborative: z.number(),
3640
+ private: z.number(),
3628
3641
  images: z.array(z.object({
3629
3642
  blob_id: z.string(),
3630
3643
  is_primary: z.number(),
@@ -3642,6 +3655,7 @@ export const ListFavoritesResponseSchema = z.object({
3642
3655
  deleted_by: z.string().nullish(),
3643
3656
  created_by: z.string().nullish(),
3644
3657
  updated_by: z.string().nullish(),
3658
+ created_by_username: z.string().nullish(),
3645
3659
  song_count: z.number()
3646
3660
  }),
3647
3661
  song_count: z.number(),
@@ -4623,6 +4637,8 @@ export const PlaylistSchema = z.object({
4623
4637
  title: z.string(),
4624
4638
  description: z.string().nullish(),
4625
4639
  is_public: z.number(),
4640
+ collaborative: z.number(),
4641
+ private: z.number(),
4626
4642
  images: z.array(z.object({
4627
4643
  blob_id: z.string(),
4628
4644
  is_primary: z.number(),
@@ -4640,6 +4656,7 @@ export const PlaylistSchema = z.object({
4640
4656
  deleted_by: z.string().nullish(),
4641
4657
  created_by: z.string().nullish(),
4642
4658
  updated_by: z.string().nullish(),
4659
+ created_by_username: z.string().nullish(),
4643
4660
  song_count: z.number()
4644
4661
  });
4645
4662
  export type Playlist = z.infer<typeof PlaylistSchema>;
@@ -4667,6 +4684,8 @@ export const PlaylistQueryResultSchema = z.object({
4667
4684
  title: z.string(),
4668
4685
  description: z.string().nullish(),
4669
4686
  is_public: z.number(),
4687
+ collaborative: z.number(),
4688
+ private: z.number(),
4670
4689
  images: z.array(z.object({
4671
4690
  blob_id: z.string(),
4672
4691
  is_primary: z.number(),
@@ -4684,6 +4703,7 @@ export const PlaylistQueryResultSchema = z.object({
4684
4703
  deleted_by: z.string().nullish(),
4685
4704
  created_by: z.string().nullish(),
4686
4705
  updated_by: z.string().nullish(),
4706
+ created_by_username: z.string().nullish(),
4687
4707
  song_count: z.number()
4688
4708
  }),
4689
4709
  song_count: z.number(),
@@ -5004,6 +5024,8 @@ export const PlaylistsQueryResultSchema = z.object({
5004
5024
  title: z.string(),
5005
5025
  description: z.string().nullish(),
5006
5026
  is_public: z.number(),
5027
+ collaborative: z.number(),
5028
+ private: z.number(),
5007
5029
  images: z.array(z.object({
5008
5030
  blob_id: z.string(),
5009
5031
  is_primary: z.number(),
@@ -5021,6 +5043,7 @@ export const PlaylistsQueryResultSchema = z.object({
5021
5043
  deleted_by: z.string().nullish(),
5022
5044
  created_by: z.string().nullish(),
5023
5045
  updated_by: z.string().nullish(),
5046
+ created_by_username: z.string().nullish(),
5024
5047
  song_count: z.number()
5025
5048
  }),
5026
5049
  song_count: z.number(),
@@ -5265,7 +5288,9 @@ export const QueryParamsSchema = z.object({
5265
5288
  min_rating: z.number().nullish(),
5266
5289
  mb_lookup_status: z.array(z.string()).nullish(),
5267
5290
  pending_review: z.boolean().nullish(),
5268
- caller_is_admin: z.boolean().nullish()
5291
+ own_or_collaborative_only: z.boolean().nullish(),
5292
+ caller_is_admin: z.boolean().nullish(),
5293
+ caller_user_id: z.string().nullish()
5269
5294
  });
5270
5295
  export type QueryParams = z.infer<typeof QueryParamsSchema>;
5271
5296
 
@@ -5315,7 +5340,9 @@ export const QueryVideosRequestSchema = z.object({
5315
5340
  min_rating: z.number().nullish(),
5316
5341
  mb_lookup_status: z.array(z.string()).nullish(),
5317
5342
  pending_review: z.boolean().nullish(),
5318
- caller_is_admin: z.boolean().nullish()
5343
+ own_or_collaborative_only: z.boolean().nullish(),
5344
+ caller_is_admin: z.boolean().nullish(),
5345
+ caller_user_id: z.string().nullish()
5319
5346
  }),
5320
5347
  series_id: z.string().nullish(),
5321
5348
  season_id: z.string().nullish(),
@@ -5882,6 +5909,17 @@ export const ReplaceAlbumsTagsRequestSchema = z.object({
5882
5909
  });
5883
5910
  export type ReplaceAlbumsTagsRequest = z.infer<typeof ReplaceAlbumsTagsRequestSchema>;
5884
5911
 
5912
+ export const ReprocessVideoRequestSchema = z.object({
5913
+ id: z.string()
5914
+ });
5915
+ export type ReprocessVideoRequest = z.infer<typeof ReprocessVideoRequestSchema>;
5916
+
5917
+ export const ReprocessVideoResultSchema = z.object({
5918
+ video_id: z.string(),
5919
+ job_id: z.string().nullish()
5920
+ });
5921
+ export type ReprocessVideoResult = z.infer<typeof ReprocessVideoResultSchema>;
5922
+
5885
5923
  export const RequeryEnrichmentRequestSchema = z.object({
5886
5924
  album_id: z.string(),
5887
5925
  source: z.union([z.literal('Mb'), z.literal('Lastfm'), z.literal('Audiodb')]),
@@ -7402,6 +7440,8 @@ export const UpdatePlaylistRequestSchema = z.object({
7402
7440
  title: z.string().nullish(),
7403
7441
  description: z.string().nullish(),
7404
7442
  is_public: z.boolean().nullish(),
7443
+ collaborative: z.boolean().nullish(),
7444
+ private: z.boolean().nullish(),
7405
7445
  entity_urls: z.array(z.object({
7406
7446
  id: z.string().nullish(),
7407
7447
  name: z.string().nullish(),
@@ -167,6 +167,18 @@ export function createVideoMethods(call: CallFn) {
167
167
  );
168
168
  },
169
169
 
170
+ reprocessVideo: (params: s.ReprocessVideoRequest) => {
171
+ return call(
172
+ "video",
173
+ "reprocess_video",
174
+ routes.video.reprocess_video.resp,
175
+ routes.video.reprocess_video.req,
176
+ routes.video.reprocess_video.method,
177
+ routes.video.reprocess_video.path,
178
+ params,
179
+ );
180
+ },
181
+
170
182
  // playback progress
171
183
  upsertPlaybackProgress: (params: s.UpsertPlaybackProgressRequest) => {
172
184
  return call(
@@ -120,13 +120,17 @@ export function canUpdatePlaylist(
120
120
 
121
121
  /**
122
122
  * check if user can add songs to a playlist.
123
- * playlists use OwnerOr(Admin).
123
+ * playlists use OwnerOr(Admin) - collaborative playlists additionally
124
+ * allow any authenticated user, mirroring the backend's
125
+ * `require_owner_or_collaborative_or_scope`.
124
126
  */
125
127
  export function canAddSongsToPlaylist(
126
128
  userId: string,
127
129
  playlistOwnerId: string | null,
128
130
  userRole: UserRoleName,
131
+ isCollaborative = false,
129
132
  ): boolean {
133
+ if (isCollaborative) return true;
130
134
  const auth = routes.music.add_songs_to_playlist.auth;
131
135
  if (auth.type === "owner_or") {
132
136
  return canAccessOwnerOr(userId, playlistOwnerId, userRole, auth.role);
@@ -136,13 +140,16 @@ export function canAddSongsToPlaylist(
136
140
 
137
141
  /**
138
142
  * check if user can remove songs from a playlist.
139
- * playlists use OwnerOr(Admin).
143
+ * playlists use OwnerOr(Admin) - collaborative playlists additionally
144
+ * allow any authenticated user.
140
145
  */
141
146
  export function canRemoveSongsFromPlaylist(
142
147
  userId: string,
143
148
  playlistOwnerId: string | null,
144
149
  userRole: UserRoleName,
150
+ isCollaborative = false,
145
151
  ): boolean {
152
+ if (isCollaborative) return true;
146
153
  const auth = routes.music.remove_songs_from_playlist.auth;
147
154
  if (auth.type === "owner_or") {
148
155
  return canAccessOwnerOr(userId, playlistOwnerId, userRole, auth.role);
@@ -402,13 +409,16 @@ export function canAccessMusicBrainz(userRole: UserRoleName): boolean {
402
409
 
403
410
  /**
404
411
  * check if user can reorder songs in a playlist.
405
- * playlists use OwnerOr(Admin).
412
+ * playlists use OwnerOr(Admin) - collaborative playlists additionally
413
+ * allow any authenticated user.
406
414
  */
407
415
  export function canReorderPlaylistSongs(
408
416
  userId: string,
409
417
  playlistOwnerId: string | null,
410
418
  userRole: UserRoleName,
419
+ isCollaborative = false,
411
420
  ): boolean {
421
+ if (isCollaborative) return true;
412
422
  const auth = routes.music.reorder_playlist_songs.auth;
413
423
  if (auth.type === "owner_or") {
414
424
  return canAccessOwnerOr(userId, playlistOwnerId, userRole, auth.role);