feat: add STEM file support per track
- DB: stems table with trackId FK, fileKey, sortOrder, createdById - API: GET/POST/DELETE stems, presigned upload URL, ZIP download via fflate - Web: StemUploadDropzone (multi-file, batch upload, progress bars) - Web: StemList with download-all-ZIP and per-stem delete - Web: STEMs tab in track detail view - Icon: add 'music' icon to inline set - Auto-migration runs stems table creation on boot Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -53,6 +53,20 @@ export const updateVersionSchema = z.object({
|
||||
branchLabel: z.string().max(100).nullable().optional(),
|
||||
});
|
||||
|
||||
export const requestStemUploadUrlSchema = z.object({
|
||||
fileName: z.string().min(1),
|
||||
mimeType: z.string().min(1),
|
||||
fileSize: z.number().int().positive().max(MAX_FILE_SIZE),
|
||||
});
|
||||
|
||||
export const createStemSchema = z.object({
|
||||
fileKey: z.string().min(1),
|
||||
name: z.string().min(1).max(255),
|
||||
originalFileName: z.string().min(1),
|
||||
mimeType: z.string().min(1),
|
||||
fileSize: z.number().int().positive(),
|
||||
});
|
||||
|
||||
export const createShareLinkSchema = z.object({
|
||||
expiresAt: z.string().datetime().optional(),
|
||||
allowComments: z.boolean().optional(),
|
||||
@@ -75,3 +89,5 @@ export type UpdateVersionInput = z.infer<typeof updateVersionSchema>;
|
||||
export type CreateShareLinkInput = z.infer<typeof createShareLinkSchema>;
|
||||
export type CoverUploadInput = z.infer<typeof coverUploadSchema>;
|
||||
export type GuestCommentInput = z.infer<typeof guestCommentSchema>;
|
||||
export type RequestStemUploadUrlInput = z.infer<typeof requestStemUploadUrlSchema>;
|
||||
export type CreateStemInput = z.infer<typeof createStemSchema>;
|
||||
|
||||
Reference in New Issue
Block a user