From 8c55f899b58f07f55aa5ee3748c33b957cd86f39 Mon Sep 17 00:00:00 2001 From: seb Date: Thu, 15 Oct 2026 00:30:23 +0200 Subject: [PATCH] u --- docs/api/routes-all.md | 2 +- docs/api/routes.md | 2 +- docs/api/routes/delivery/_id/pdf.md | 2 +- docs/api/routes/delivery/create.md | 2 +- docs/api/routes/delivery/get.md | 2 +- docs/api/routes/delivery/update.md | 2 +- docs/api/routes/order/_id/pdf.md | 2 +- docs/api/routes/order/_id/shipment.get.md | 2 +- docs/api/routes/order/_id/shipment.post.md | 2 +- docs/api/routes/order/create.md | 4 +- docs/api/routes/order/get.md | 4 +- docs/api/routes/order/list.md | 4 +- docs/api/routes/order/update.md | 4 +- docs/api/routes/quote/_id/pdf.md | 2 +- docs/api/routes/quote/create.md | 2 +- docs/api/routes/quote/get.md | 2 +- docs/api/routes/quote/list.md | 2 +- docs/api/routes/quote/update.md | 2 +- docs/api/routes/shipment/_id.get.md | 2 +- docs/api/routes/shipment/_id/pdf.md | 2 +- src/api/openapi.js | 5 +-- src/db/delivery.js | 31 +++++++++++--- src/db/order.js | 10 +++-- src/db/quote.js | 23 +++++++--- src/db/shipment.js | 10 +++-- src/services/manifestPdf.js | 5 ++- src/util/manifestAttachment.js | 50 ++++++++++++++++++++++ 27 files changed, 136 insertions(+), 46 deletions(-) create mode 100644 src/util/manifestAttachment.js diff --git a/docs/api/routes-all.md b/docs/api/routes-all.md index 82bd381..ff3adb0 100644 --- a/docs/api/routes-all.md +++ b/docs/api/routes-all.md @@ -23,7 +23,7 @@ Params: path values first, then `query:` and `body:` (`body?` = optional body). - `T12` = `{ labeltemplate: T14 }` - `T13` = `{ attachment: T15, fileUrl: str }` - `T14` = `{ id: int, name: str, width: num, height: num, dpi: int, type: str, content: T25, thumb?: str|null }` -- `T15` = `{ id: int, manifestId: int, fileId: int, sort: int, hash: str, mimetype: str, name: str, size: int, created?: str, modified?: str, thumbavif?: str|null, thumbx?: int|null, thumby?: int|null, meta?: { [k]: str }|null }` +- `T15` = `{ id: int, manifestId: int, fileId: int, sort: int, hash: str, mimetype: str, name: str, size: int, created?: str, modified?: str, skeledash?: str|null, thumbx?: int|null, thumby?: int|null, meta?: { [k]: str }|null }` - `T16` = `{ id: int, name: str, pairingpin?: str|null, token?: str|null, pairedAt?: str|null, clientserial?: str|null, rootCategoryId?: int|null, syncRootArticles?: bool, lastseenAt?: str|null, updatedAt?: str|null, categoryIds?: int[] }` - `T17` = `{ id: int, articleId: int, entityId: int, pu: num, sort: int, supplierName?: str|null, sku?: str|null, stock?: num|null, priceId?: int|null, price?: T54|null }` - `T18` = `{ vfs: T52, storage: T52, database: T45 }` diff --git a/docs/api/routes.md b/docs/api/routes.md index 0cf7ed3..df6b4c7 100644 --- a/docs/api/routes.md +++ b/docs/api/routes.md @@ -21,7 +21,7 @@ Params: path values first, then `query:` and `body:` (`body?` = optional body). - `T10` = `{ labeltemplate: T12 }` - `T11` = `{ attachment: T13, fileUrl: str }` - `T12` = `{ id: int, name: str, width: num, height: num, dpi: int, type: str, content: T19, thumb?: str|null }` -- `T13` = `{ id: int, manifestId: int, fileId: int, sort: int, hash: str, mimetype: str, name: str, size: int, created?: str, modified?: str, thumbavif?: str|null, thumbx?: int|null, thumby?: int|null, meta?: { [k]: str }|null }` +- `T13` = `{ id: int, manifestId: int, fileId: int, sort: int, hash: str, mimetype: str, name: str, size: int, created?: str, modified?: str, skeledash?: str|null, thumbx?: int|null, thumby?: int|null, meta?: { [k]: str }|null }` - `T14` = `{ id: int, articleId: int, entityId: int, pu: num, sort: int, supplierName?: str|null, sku?: str|null, stock?: num|null, priceId?: int|null, price?: T45|null }` - `T15` = `{ id: int, entityId: int, addressType: str, firstName?: str|null, name?: str|null, street?: str|null, streetNumber?: str|null, zip?: str|null, city?: str|null, county?: str|null }` - `T16` = `{ ledger: T17[] }` diff --git a/docs/api/routes/delivery/_id/pdf.md b/docs/api/routes/delivery/_id/pdf.md index 429c57e..42502e0 100644 --- a/docs/api/routes/delivery/_id/pdf.md +++ b/docs/api/routes/delivery/_id/pdf.md @@ -35,7 +35,7 @@ PDF generated and attached to delivery "size": 1, "created": "2026-08-10T00:00:00.000Z", "modified": "2026-08-10T00:00:00.000Z", - "thumbavif": "…", + "skeledash": "…", "thumbx": 1, "thumby": 1, "meta": {} diff --git a/docs/api/routes/delivery/create.md b/docs/api/routes/delivery/create.md index 7864c02..dd8731c 100644 --- a/docs/api/routes/delivery/create.md +++ b/docs/api/routes/delivery/create.md @@ -97,7 +97,7 @@ Created delivery "size": 1, "created": "2026-08-10T00:00:00.000Z", "modified": "2026-08-10T00:00:00.000Z", - "thumbavif": "…", + "skeledash": "…", "thumbx": 1, "thumby": 1, "meta": {} diff --git a/docs/api/routes/delivery/get.md b/docs/api/routes/delivery/get.md index 81d199a..40f206f 100644 --- a/docs/api/routes/delivery/get.md +++ b/docs/api/routes/delivery/get.md @@ -55,7 +55,7 @@ Delivery "size": 1, "created": "2026-08-10T00:00:00.000Z", "modified": "2026-08-10T00:00:00.000Z", - "thumbavif": "…", + "skeledash": "…", "thumbx": 1, "thumby": 1, "meta": {} diff --git a/docs/api/routes/delivery/update.md b/docs/api/routes/delivery/update.md index 488b94b..3a53799 100644 --- a/docs/api/routes/delivery/update.md +++ b/docs/api/routes/delivery/update.md @@ -84,7 +84,7 @@ Updated delivery "size": 1, "created": "2026-08-10T00:00:00.000Z", "modified": "2026-08-10T00:00:00.000Z", - "thumbavif": "…", + "skeledash": "…", "thumbx": 1, "thumby": 1, "meta": {} diff --git a/docs/api/routes/order/_id/pdf.md b/docs/api/routes/order/_id/pdf.md index ff0a9da..65c3f1b 100644 --- a/docs/api/routes/order/_id/pdf.md +++ b/docs/api/routes/order/_id/pdf.md @@ -35,7 +35,7 @@ PDF generated and attached to order "size": 1, "created": "2026-08-10T00:00:00.000Z", "modified": "2026-08-10T00:00:00.000Z", - "thumbavif": "…", + "skeledash": "…", "thumbx": 1, "thumby": 1, "meta": {} diff --git a/docs/api/routes/order/_id/shipment.get.md b/docs/api/routes/order/_id/shipment.get.md index 4fd38e9..3adbb61 100644 --- a/docs/api/routes/order/_id/shipment.get.md +++ b/docs/api/routes/order/_id/shipment.get.md @@ -65,7 +65,7 @@ List of shipments "size": 1, "created": "2026-08-10T00:00:00.000Z", "modified": "2026-08-10T00:00:00.000Z", - "thumbavif": "…", + "skeledash": "…", "thumbx": 1, "thumby": 1, "meta": {} diff --git a/docs/api/routes/order/_id/shipment.post.md b/docs/api/routes/order/_id/shipment.post.md index a399c07..0cc00d7 100644 --- a/docs/api/routes/order/_id/shipment.post.md +++ b/docs/api/routes/order/_id/shipment.post.md @@ -102,7 +102,7 @@ Created shipment "size": 1, "created": "2026-08-10T00:00:00.000Z", "modified": "2026-08-10T00:00:00.000Z", - "thumbavif": "…", + "skeledash": "…", "thumbx": 1, "thumby": 1, "meta": {} diff --git a/docs/api/routes/order/create.md b/docs/api/routes/order/create.md index fff771b..ec14283 100644 --- a/docs/api/routes/order/create.md +++ b/docs/api/routes/order/create.md @@ -153,7 +153,7 @@ Created order "size": 1, "created": "2026-08-10T00:00:00.000Z", "modified": "2026-08-10T00:00:00.000Z", - "thumbavif": "…", + "skeledash": "…", "thumbx": 1, "thumby": 1, "meta": {} @@ -173,7 +173,7 @@ Created order "size": 1, "created": "2026-08-10T00:00:00.000Z", "modified": "2026-08-10T00:00:00.000Z", - "thumbavif": "…", + "skeledash": "…", "thumbx": 1, "thumby": 1, "meta": {} diff --git a/docs/api/routes/order/get.md b/docs/api/routes/order/get.md index a2cc26d..33494bc 100644 --- a/docs/api/routes/order/get.md +++ b/docs/api/routes/order/get.md @@ -128,7 +128,7 @@ Order "size": 1, "created": "2026-08-10T00:00:00.000Z", "modified": "2026-08-10T00:00:00.000Z", - "thumbavif": "…", + "skeledash": "…", "thumbx": 1, "thumby": 1, "meta": {} @@ -148,7 +148,7 @@ Order "size": 1, "created": "2026-08-10T00:00:00.000Z", "modified": "2026-08-10T00:00:00.000Z", - "thumbavif": "…", + "skeledash": "…", "thumbx": 1, "thumby": 1, "meta": {} diff --git a/docs/api/routes/order/list.md b/docs/api/routes/order/list.md index 114d2f0..6dc8d83 100644 --- a/docs/api/routes/order/list.md +++ b/docs/api/routes/order/list.md @@ -137,7 +137,7 @@ Order list "size": 1, "created": "2026-08-10T00:00:00.000Z", "modified": "2026-08-10T00:00:00.000Z", - "thumbavif": "…", + "skeledash": "…", "thumbx": 1, "thumby": 1, "meta": {} @@ -157,7 +157,7 @@ Order list "size": 1, "created": "2026-08-10T00:00:00.000Z", "modified": "2026-08-10T00:00:00.000Z", - "thumbavif": "…", + "skeledash": "…", "thumbx": 1, "thumby": 1, "meta": {} diff --git a/docs/api/routes/order/update.md b/docs/api/routes/order/update.md index 7e87af3..9b37e31 100644 --- a/docs/api/routes/order/update.md +++ b/docs/api/routes/order/update.md @@ -147,7 +147,7 @@ Updated order "size": 1, "created": "2026-08-10T00:00:00.000Z", "modified": "2026-08-10T00:00:00.000Z", - "thumbavif": "…", + "skeledash": "…", "thumbx": 1, "thumby": 1, "meta": {} @@ -167,7 +167,7 @@ Updated order "size": 1, "created": "2026-08-10T00:00:00.000Z", "modified": "2026-08-10T00:00:00.000Z", - "thumbavif": "…", + "skeledash": "…", "thumbx": 1, "thumby": 1, "meta": {} diff --git a/docs/api/routes/quote/_id/pdf.md b/docs/api/routes/quote/_id/pdf.md index bf243e6..c2176ba 100644 --- a/docs/api/routes/quote/_id/pdf.md +++ b/docs/api/routes/quote/_id/pdf.md @@ -35,7 +35,7 @@ PDF generated and attached to quote "size": 1, "created": "2026-08-10T00:00:00.000Z", "modified": "2026-08-10T00:00:00.000Z", - "thumbavif": "…", + "skeledash": "…", "thumbx": 1, "thumby": 1, "meta": {} diff --git a/docs/api/routes/quote/create.md b/docs/api/routes/quote/create.md index e84c38e..d61aaf1 100644 --- a/docs/api/routes/quote/create.md +++ b/docs/api/routes/quote/create.md @@ -79,7 +79,7 @@ Created quote "size": 1, "created": "2026-08-10T00:00:00.000Z", "modified": "2026-08-10T00:00:00.000Z", - "thumbavif": "…", + "skeledash": "…", "thumbx": 1, "thumby": 1, "meta": {} diff --git a/docs/api/routes/quote/get.md b/docs/api/routes/quote/get.md index c47b2c7..f055d6e 100644 --- a/docs/api/routes/quote/get.md +++ b/docs/api/routes/quote/get.md @@ -54,7 +54,7 @@ Quote "size": 1, "created": "2026-08-10T00:00:00.000Z", "modified": "2026-08-10T00:00:00.000Z", - "thumbavif": "…", + "skeledash": "…", "thumbx": 1, "thumby": 1, "meta": {} diff --git a/docs/api/routes/quote/list.md b/docs/api/routes/quote/list.md index 6d52ca8..b0425cf 100644 --- a/docs/api/routes/quote/list.md +++ b/docs/api/routes/quote/list.md @@ -60,7 +60,7 @@ Quote list "size": 1, "created": "2026-08-10T00:00:00.000Z", "modified": "2026-08-10T00:00:00.000Z", - "thumbavif": "…", + "skeledash": "…", "thumbx": 1, "thumby": 1, "meta": {} diff --git a/docs/api/routes/quote/update.md b/docs/api/routes/quote/update.md index 25446f1..5acaea8 100644 --- a/docs/api/routes/quote/update.md +++ b/docs/api/routes/quote/update.md @@ -73,7 +73,7 @@ Updated quote "size": 1, "created": "2026-08-10T00:00:00.000Z", "modified": "2026-08-10T00:00:00.000Z", - "thumbavif": "…", + "skeledash": "…", "thumbx": 1, "thumby": 1, "meta": {} diff --git a/docs/api/routes/shipment/_id.get.md b/docs/api/routes/shipment/_id.get.md index 6217cbd..d4e247a 100644 --- a/docs/api/routes/shipment/_id.get.md +++ b/docs/api/routes/shipment/_id.get.md @@ -64,7 +64,7 @@ Shipment details "size": 1, "created": "2026-08-10T00:00:00.000Z", "modified": "2026-08-10T00:00:00.000Z", - "thumbavif": "…", + "skeledash": "…", "thumbx": 1, "thumby": 1, "meta": {} diff --git a/docs/api/routes/shipment/_id/pdf.md b/docs/api/routes/shipment/_id/pdf.md index 5685331..b859d9e 100644 --- a/docs/api/routes/shipment/_id/pdf.md +++ b/docs/api/routes/shipment/_id/pdf.md @@ -36,7 +36,7 @@ PDF generated and attached to shipment "size": 1, "created": "2026-08-10T00:00:00.000Z", "modified": "2026-08-10T00:00:00.000Z", - "thumbavif": "…", + "skeledash": "…", "thumbx": 1, "thumby": 1, "meta": {} diff --git a/src/api/openapi.js b/src/api/openapi.js index f636fe2..1b37959 100644 --- a/src/api/openapi.js +++ b/src/api/openapi.js @@ -834,11 +834,10 @@ * modified: * type: string * format: date-time - * thumbavif: + * skeledash: * type: string - * format: byte * nullable: true - * description: Base64-encoded AVIF thumbnail generated server-side (null for text files) + * description: Base62 skelehash string of the document thumbnail * thumbx: * type: integer * nullable: true diff --git a/src/db/delivery.js b/src/db/delivery.js index dd1c0e2..cbf05bb 100644 --- a/src/db/delivery.js +++ b/src/db/delivery.js @@ -1,23 +1,40 @@ import { getStore } from './store.js'; +import { formatAttachments } from '../util/manifestAttachment.js'; + +async function formatDelivery(delivery) { + if (!delivery) return delivery; + if (Array.isArray(delivery.files) && delivery.files.length > 0) { + const files = await formatAttachments(delivery.files); + return { ...delivery, files }; + } + return delivery; +} export async function list(googleAuthId) { const store = await getStore(); - return store.delivery.list(googleAuthId); + const result = await store.delivery.list(googleAuthId); + if (Array.isArray(result)) { + return Promise.all(result.map(formatDelivery)); + } + return result; } export async function getById(googleAuthId, id) { const store = await getStore(); - return store.delivery.getById(googleAuthId, id); + const delivery = await store.delivery.getById(googleAuthId, id); + return formatDelivery(delivery); } export async function create(googleAuthId, data) { const store = await getStore(); - return store.delivery.create(googleAuthId, data); + const delivery = await store.delivery.create(googleAuthId, data); + return formatDelivery(delivery); } export async function update(googleAuthId, id, data) { const store = await getStore(); - return store.delivery.update(googleAuthId, id, data); + const delivery = await store.delivery.update(googleAuthId, id, data); + return formatDelivery(delivery); } export async function remove(googleAuthId, id) { @@ -32,12 +49,14 @@ export async function getFile(googleAuthId, deliveryId, fileId) { export async function addAttachment(googleAuthId, deliveryId, data) { const store = await getStore(); - return store.manifestattachment.add(googleAuthId, deliveryId, data); + const raw = await store.manifestattachment.add(googleAuthId, deliveryId, data); + return formatAttachments([raw]).then((r) => r[0]); } export async function listAttachments(googleAuthId, deliveryId) { const store = await getStore(); - return store.manifestattachment.listByManifestId(googleAuthId, deliveryId); + const raw = await store.manifestattachment.listByManifestId(googleAuthId, deliveryId); + return formatAttachments(raw); } export async function removeAttachment(googleAuthId, deliveryId, fileId) { diff --git a/src/db/order.js b/src/db/order.js index 5393d17..cf2e836 100644 --- a/src/db/order.js +++ b/src/db/order.js @@ -1,4 +1,5 @@ import { getStore } from './store.js'; +import { formatAttachments } from '../util/manifestAttachment.js'; function round2(num) { return Math.round((Number(num) || 0) * 100) / 100; @@ -46,13 +47,14 @@ function calculateShippedQuantity(shipments = []) { async function enrichSingleOrder(store, googleAuthId, order) { if (!order) return order; - const [shippings, payments, shipments, files] = await Promise.all([ + const [shippings, payments, shipments, rawFiles] = await Promise.all([ store.shipping.listByManifestId(googleAuthId, order.id).catch(() => []), store.payment.listByManifestId(googleAuthId, order.id).catch(() => []), store.shipment.listByOrderId(googleAuthId, order.id).catch(() => []), store.manifestattachment.listByManifestId(googleAuthId, order.id).catch(() => []), ]); + const files = await formatAttachments(rawFiles); const orderLines = Array.isArray(order.lines) ? order.lines : []; const paymentsList = Array.isArray(payments) ? payments : []; const shipmentsList = Array.isArray(shipments) ? shipments : []; @@ -165,12 +167,14 @@ export async function getFile(googleAuthId, orderId, fileId) { export async function addAttachment(googleAuthId, orderId, data) { const store = await getStore(); - return store.manifestattachment.add(googleAuthId, orderId, data); + const raw = await store.manifestattachment.add(googleAuthId, orderId, data); + return formatAttachments([raw]).then((r) => r[0]); } export async function listAttachments(googleAuthId, orderId) { const store = await getStore(); - return store.manifestattachment.listByManifestId(googleAuthId, orderId); + const raw = await store.manifestattachment.listByManifestId(googleAuthId, orderId); + return formatAttachments(raw); } export async function removeAttachment(googleAuthId, orderId, fileId) { diff --git a/src/db/quote.js b/src/db/quote.js index f07bb12..6c17eaf 100644 --- a/src/db/quote.js +++ b/src/db/quote.js @@ -1,4 +1,5 @@ import { getStore } from './store.js'; +import { formatAttachments } from '../util/manifestAttachment.js'; function round2(num) { return Math.round((Number(num) || 0) * 100) / 100; @@ -47,13 +48,19 @@ export async function list(googleAuthId, opts) { const result = await store.quote.list(googleAuthId, opts); if (Array.isArray(result)) { const filesList = await Promise.all( - result.map((q) => store.manifestattachment.listByManifestId(googleAuthId, q.id).catch(() => [])) + result.map(async (q) => { + const raw = await store.manifestattachment.listByManifestId(googleAuthId, q.id).catch(() => []); + return formatAttachments(raw); + }) ); return result.map((q, i) => enrichQuote(q, filesList[i])); } if (result && Array.isArray(result.quotes)) { const filesList = await Promise.all( - result.quotes.map((q) => store.manifestattachment.listByManifestId(googleAuthId, q.id).catch(() => [])) + result.quotes.map(async (q) => { + const raw = await store.manifestattachment.listByManifestId(googleAuthId, q.id).catch(() => []); + return formatAttachments(raw); + }) ); return { ...result, @@ -65,10 +72,11 @@ export async function list(googleAuthId, opts) { export async function getById(googleAuthId, id) { const store = await getStore(); - const [quote, files] = await Promise.all([ + const [quote, rawFiles] = await Promise.all([ store.quote.getById(googleAuthId, id), store.manifestattachment.listByManifestId(googleAuthId, id).catch(() => []), ]); + const files = await formatAttachments(rawFiles); return enrichQuote(quote, files); } @@ -80,10 +88,11 @@ export async function create(googleAuthId, data) { export async function update(googleAuthId, id, data) { const store = await getStore(); - const [quote, files] = await Promise.all([ + const [quote, rawFiles] = await Promise.all([ store.quote.update(googleAuthId, id, data), store.manifestattachment.listByManifestId(googleAuthId, id).catch(() => []), ]); + const files = await formatAttachments(rawFiles); return enrichQuote(quote, files); } @@ -104,12 +113,14 @@ export async function getFile(googleAuthId, quoteId, fileId) { export async function addAttachment(googleAuthId, quoteId, data) { const store = await getStore(); - return store.manifestattachment.add(googleAuthId, quoteId, data); + const raw = await store.manifestattachment.add(googleAuthId, quoteId, data); + return formatAttachments([raw]).then((r) => r[0]); } export async function listAttachments(googleAuthId, quoteId) { const store = await getStore(); - return store.manifestattachment.listByManifestId(googleAuthId, quoteId); + const raw = await store.manifestattachment.listByManifestId(googleAuthId, quoteId); + return formatAttachments(raw); } export async function removeAttachment(googleAuthId, quoteId, fileId) { diff --git a/src/db/shipment.js b/src/db/shipment.js index 6cdba43..4aae4db 100644 --- a/src/db/shipment.js +++ b/src/db/shipment.js @@ -1,4 +1,5 @@ import { getStore } from './store.js'; +import { formatAttachments } from '../util/manifestAttachment.js'; export async function create(googleAuthId, data) { const store = await getStore(); @@ -7,11 +8,12 @@ export async function create(googleAuthId, data) { export async function getById(googleAuthId, id) { const store = await getStore(); - const [shipment, files] = await Promise.all([ + const [shipment, rawFiles] = await Promise.all([ store.shipment.getById(googleAuthId, id), store.manifestattachment.listByManifestId(googleAuthId, id).catch(() => []), ]); if (!shipment) return shipment; + const files = await formatAttachments(rawFiles); return { ...shipment, files: Array.isArray(files) ? files : [], @@ -35,12 +37,14 @@ export async function getFile(googleAuthId, shipmentId, fileId) { export async function addAttachment(googleAuthId, shipmentId, data) { const store = await getStore(); - return store.manifestattachment.add(googleAuthId, shipmentId, data); + const raw = await store.manifestattachment.add(googleAuthId, shipmentId, data); + return formatAttachments([raw]).then((r) => r[0]); } export async function listAttachments(googleAuthId, shipmentId) { const store = await getStore(); - return store.manifestattachment.listByManifestId(googleAuthId, shipmentId); + const raw = await store.manifestattachment.listByManifestId(googleAuthId, shipmentId); + return formatAttachments(raw); } export async function removeAttachment(googleAuthId, shipmentId, fileId) { diff --git a/src/services/manifestPdf.js b/src/services/manifestPdf.js index cf60318..1ffe448 100644 --- a/src/services/manifestPdf.js +++ b/src/services/manifestPdf.js @@ -2,6 +2,7 @@ import PDFDocument from 'pdfkit'; import { getStore } from '../db/store.js'; import * as dbOrder from '../db/order.js'; import { emit } from '../api/sse.js'; +import { formatAttachment } from '../util/manifestAttachment.js'; /** * Formats a Date or date string to German format DD.MM.YYYY. @@ -786,13 +787,15 @@ export async function createAndAttachManifestPdf(googleAuthId, companyId, manife const safeNumber = String(manifest.number || manifest.id).replace(/[^a-zA-Z0-9._-]/g, '_'); const filename = `${config.filenamePrefix}-${safeNumber}.pdf`; - const attachment = await store.manifestattachment.add(googleAuthId, manifest.id, { + const rawAttachment = await store.manifestattachment.add(googleAuthId, manifest.id, { mimetype: 'application/pdf', name: filename, content: pdfBuffer, meta: { type: `${type}_pdf` }, }); + const attachment = await formatAttachment(rawAttachment); + emit(type, { companyId }); return { manifest, attachment, pdfBuffer, filename }; diff --git a/src/util/manifestAttachment.js b/src/util/manifestAttachment.js new file mode 100644 index 0000000..db24794 --- /dev/null +++ b/src/util/manifestAttachment.js @@ -0,0 +1,50 @@ +import { computeSkeleHash } from '../services/companyImport/imageHasher.js'; + +const skeleCache = new Map(); + +/** + * Strips raw binary `thumbavif` buffer and attaches `skeledash` (base62 skelehash string). + * + * @param {object} file - Raw attachment file object from libdashstore. + * @returns {Promise} Formatted attachment with `skeledash` and without `thumbavif`. + */ +export async function formatAttachment(file) { + if (!file || typeof file !== 'object') return file; + + let skeledash = file.skeledash || file.skelehash || file.meta?.skeledash || file.meta?.skelehash || null; + + if (!skeledash && file.hash && skeleCache.has(file.hash)) { + skeledash = skeleCache.get(file.hash); + } + + if (!skeledash && file.thumbavif) { + try { + const result = await computeSkeleHash(file.thumbavif); + skeledash = result?.base62 || null; + if (file.hash && skeledash) { + skeleCache.set(file.hash, skeledash); + } + } catch { + skeledash = null; + } + } + + const { thumbavif: _thumbavif, ...rest } = file; + + return { + ...rest, + skeledash, + skelehash: skeledash, + }; +} + +/** + * Formats a list of attachments in parallel. + * + * @param {Array} files - Array of raw file attachment objects. + * @returns {Promise>} + */ +export async function formatAttachments(files = []) { + if (!Array.isArray(files) || files.length === 0) return []; + return Promise.all(files.map(formatAttachment)); +}