mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 19:41:09 +02:00
feat: rename mukke to music, add cover art upload via mana-media
Rename the music module from "Mukke" to "Music" across the entire codebase: API routes, web app module, shared packages, search provider, dashboard widgets, i18n keys, app registry, and route paths. Add POST /api/v1/music/cover/upload endpoint that uploads cover art images through mana-media for deduplication, thumbnails, and Photos gallery visibility. Dexie table names (mukkePlaylists, mukkeProjects) kept unchanged to preserve existing IndexedDB data. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ee7ff7d5e8
commit
d4700a07f9
64 changed files with 258 additions and 214 deletions
|
|
@ -18,7 +18,7 @@ import {
|
|||
// Module routes
|
||||
import { calendarRoutes } from './modules/calendar/routes';
|
||||
import { contactsRoutes } from './modules/contacts/routes';
|
||||
import { mukkeRoutes } from './modules/mukke/routes';
|
||||
import { musicRoutes } from './modules/music/routes';
|
||||
import { chatRoutes } from './modules/chat/routes';
|
||||
import { contextRoutes } from './modules/context/routes';
|
||||
import { pictureRoutes } from './modules/picture/routes';
|
||||
|
|
@ -48,7 +48,7 @@ app.use('/api/*', authMiddleware());
|
|||
// ─── Module Routes ──────────────────────────────────────────
|
||||
app.route('/api/v1/calendar', calendarRoutes);
|
||||
app.route('/api/v1/contacts', contactsRoutes);
|
||||
app.route('/api/v1/mukke', mukkeRoutes);
|
||||
app.route('/api/v1/music', musicRoutes);
|
||||
app.route('/api/v1/chat', chatRoutes);
|
||||
app.route('/api/v1/context', contextRoutes);
|
||||
app.route('/api/v1/picture', pictureRoutes);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
* Mukke module — Audio upload, presigned URLs, cover art
|
||||
* Ported from apps/mukke/apps/server
|
||||
* Music module — Audio upload, presigned URLs, cover art
|
||||
* Renamed from Mukke.
|
||||
*/
|
||||
|
||||
import { Hono } from 'hono';
|
||||
|
|
@ -18,8 +18,8 @@ routes.post('/songs/upload', async (c) => {
|
|||
const key = `users/${userId}/songs/${songId}/${filename}`;
|
||||
|
||||
try {
|
||||
const { createMukkeStorage } = await import('@manacore/shared-storage');
|
||||
const storage = createMukkeStorage();
|
||||
const { createMusicStorage } = await import('@manacore/shared-storage');
|
||||
const storage = createMusicStorage();
|
||||
const uploadUrl = await storage.getUploadUrl(key, { expiresIn: 3600 });
|
||||
|
||||
return c.json({
|
||||
|
|
@ -38,8 +38,8 @@ routes.get('/songs/:id/download-url', async (c) => {
|
|||
if (!storagePath) return c.json({ error: 'storagePath required' }, 400);
|
||||
|
||||
try {
|
||||
const { createMukkeStorage } = await import('@manacore/shared-storage');
|
||||
const storage = createMukkeStorage();
|
||||
const { createMusicStorage } = await import('@manacore/shared-storage');
|
||||
const storage = createMusicStorage();
|
||||
const url = await storage.getDownloadUrl(storagePath, { expiresIn: 3600 });
|
||||
return c.json({ url });
|
||||
} catch {
|
||||
|
|
@ -47,6 +47,35 @@ routes.get('/songs/:id/download-url', async (c) => {
|
|||
}
|
||||
});
|
||||
|
||||
// ─── Cover Art Upload (via mana-media) ─────────────────────
|
||||
|
||||
routes.post('/cover/upload', async (c) => {
|
||||
const userId = c.get('userId');
|
||||
const formData = await c.req.formData();
|
||||
const file = formData.get('file') as File | null;
|
||||
|
||||
if (!file) return c.json({ error: 'No file' }, 400);
|
||||
if (file.size > 10 * 1024 * 1024) return c.json({ error: 'Max 10MB' }, 400);
|
||||
if (!file.type.startsWith('image/')) return c.json({ error: 'Must be an image' }, 400);
|
||||
|
||||
try {
|
||||
const { uploadImageToMedia } = await import('../../lib/media');
|
||||
const buffer = await file.arrayBuffer();
|
||||
const result = await uploadImageToMedia(buffer, file.name, { app: 'music', userId });
|
||||
|
||||
return c.json(
|
||||
{
|
||||
coverArtPath: result.id,
|
||||
coverUrl: result.urls.thumbnail || result.urls.original,
|
||||
mediaId: result.id,
|
||||
},
|
||||
201
|
||||
);
|
||||
} catch {
|
||||
return c.json({ error: 'Upload failed' }, 500);
|
||||
}
|
||||
});
|
||||
|
||||
// ─── Cover Art URL ──────────────────────────────────────────
|
||||
|
||||
routes.get('/songs/:id/cover-url', async (c) => {
|
||||
|
|
@ -54,8 +83,8 @@ routes.get('/songs/:id/cover-url', async (c) => {
|
|||
if (!coverArtPath) return c.json({ url: null });
|
||||
|
||||
try {
|
||||
const { createMukkeStorage } = await import('@manacore/shared-storage');
|
||||
const storage = createMukkeStorage();
|
||||
const { createMusicStorage } = await import('@manacore/shared-storage');
|
||||
const storage = createMusicStorage();
|
||||
const url = await storage.getDownloadUrl(coverArtPath, { expiresIn: 3600 });
|
||||
return c.json({ url });
|
||||
} catch {
|
||||
|
|
@ -70,8 +99,8 @@ routes.post('/library/cover-urls', async (c) => {
|
|||
if (!paths?.length) return c.json({ urls: {} });
|
||||
|
||||
try {
|
||||
const { createMukkeStorage } = await import('@manacore/shared-storage');
|
||||
const storage = createMukkeStorage();
|
||||
const { createMusicStorage } = await import('@manacore/shared-storage');
|
||||
const storage = createMusicStorage();
|
||||
const urls: Record<string, string> = {};
|
||||
|
||||
for (const path of paths.slice(0, 50)) {
|
||||
|
|
@ -88,4 +117,4 @@ routes.post('/library/cover-urls', async (c) => {
|
|||
}
|
||||
});
|
||||
|
||||
export { routes as mukkeRoutes };
|
||||
export { routes as musicRoutes };
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue