{
+ if (!xmlUrl.startsWith('s3:')) {
+ // local file path; resolve to file URL
+ const fileUrl = resolve(xmlUrl, '..', filePath, fileName)
+ return fileUrl
+ }
+
+ const s3url = new URL(`${filePath}${fileName}`, xmlUrl)
+ const Bucket = s3url.host
+ const Key = s3url.pathname.substring(1)
+ const source = sources.findByXmlUrl(xmlUrl)
+ const s3 = dialS3(source)
+ const command = new GetObjectCommand({ Bucket, Key })
+ const signed = await getSignedUrl(s3 as any, command as any, {
+ expiresIn: expiresInSeconds,
+ })
+ return signed
+}
+
// sdk helpers
async function readFileToBuffer(filePath: string) {
const buffer = await readFile(filePath)
diff --git a/src/server.tsx b/src/server.tsx
index ac1ced6..3ed82b4 100644
--- a/src/server.tsx
+++ b/src/server.tsx
@@ -23,7 +23,12 @@ import {
import { DDEXContributor, DDEXRelease, parseDdexXml } from './parseDelivery'
import { prepareAlbumMetadata, prepareTrackMetadatas } from './publishRelease'
import { generateSalesReport } from './reporting/sales_report'
-import { dialS3, parseS3Url, readAssetWithCaching } from './s3poller'
+import {
+ dialS3,
+ getPresignedAssetUrl,
+ parseS3Url,
+ readAssetWithCaching,
+} from './s3poller'
import { sources } from './sources'
import { parseBool } from './util'
@@ -336,6 +341,7 @@ app.get('/releases', async (c) => {
| Genre |
Release |
Clear |
+ Status |
|
|
debug |
@@ -400,6 +406,28 @@ ${row.soundRecordings.length} tracks`}
)}
+
+ {row.status}
+ {row.problems?.length > 0 && (
+
+ {row.problems.map((p) => (
+
+ {p}
+
+ ))}
+
+ )}
+ |
{row.publishErrorCount > 0 && (
@@ -758,6 +786,19 @@ app.get('/release/:source/:key/:ref/:size?', async (c) => {
const asset = await assetRepo.get(source, key, ref)
if (!asset) return c.json({ error: 'not found' }, 404)
+ // If no resizing requested (a stream instead of an image),
+ // redirect to presigned S3 URL to avoid proxying bytes
+ if (!size) {
+ const url = await getPresignedAssetUrl({
+ xmlUrl: asset.xmlUrl,
+ filePath: asset.filePath,
+ fileName: asset.fileName,
+ expiresInSeconds: 600
+ })
+ return c.redirect(url, 302)
+ }
+
+ // Resize requested: keep existing behavior (read, resize via cache helper) for now
const ok = await readAssetWithCaching(
asset.xmlUrl,
asset.filePath,
|