@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 +1 -1
- package/src/codegen/routes.ts +1 -0
- package/src/codegen/schema.ts +42 -2
- package/src/domains/video.ts +12 -0
- package/src/permissions.ts +13 -3
package/package.json
CHANGED
package/src/codegen/routes.ts
CHANGED
|
@@ -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 },
|
package/src/codegen/schema.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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(),
|
package/src/domains/video.ts
CHANGED
|
@@ -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(
|
package/src/permissions.ts
CHANGED
|
@@ -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);
|