/** * This Source Code is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Copyright (c) Infonomic Company Limited */ import type { RequestContext } from '@byline/auth'; import { type FilenameSlugifierFn } from '../utils/slugify-filename.js'; import type { CollectionDefinition, IDbAdapter, IStorageProvider, StoredFileLocation, StoredFileValue, UploadConfig } from '../@types/index.js'; import type { BylineLogger } from '../lib/logger.js'; import type { SlugifierFn } from '../utils/slugify.js'; export interface UploadImageMeta { width: number | null; height: number | null; format: string | null; } /** * One generated image variant returned by the image processor adapter. * * The processor knows the resolved dimensions / output format from the * Sharp pipeline, so the upload service persists them onto * `StoredFileValue.variants` without a re-read. `storageUrl` is captured * via `storage.getUrl(storagePath)` if the processor doesn't supply it * directly. */ export interface UploadVariantResult { name: string; storagePath: string; storageUrl?: string; width?: number; height?: number; format?: string; } export interface UploadImageProcessor { extractMeta: (buffer: Buffer, mimeType: string) => Promise; isBypassMimeType?: (mimeType: string) => boolean; generateVariants?: (params: { buffer: Buffer; mimeType: string; storedFile: StoredFileLocation; storage: IStorageProvider; upload: UploadConfig; logger: BylineLogger; }) => Promise; } export interface FieldUploadContext { db: IDbAdapter; definition: CollectionDefinition; collectionId: string; /** * Current schema version for this collection. Forwarded into the * lifecycle context so the `documentVersions` row created by the upload * flow is stamped consistently with direct writes. */ collectionVersion: number; collectionPath: string; /** * Name of the upload-capable image/file field on this collection. The * service resolves the field, validates that it carries an `upload` * block, and reads MIME / size / sizes / storage / hooks from there. */ fieldName: string; storage: IStorageProvider; logger: BylineLogger; imageProcessor?: UploadImageProcessor; /** Default content locale, forwarded to the lifecycle context. */ defaultLocale: string; /** Optional installation slugifier, forwarded to the lifecycle context. */ slugifier?: SlugifierFn; /** * Optional installation filename slugifier * (`ServerConfig.uploads.filenameSlugifier`), applied to the uploaded base * name before the `beforeStore` chain. Defaults to `slugifyFilename`. */ filenameSlugifier?: FilenameSlugifierFn; /** * Request-scoped auth context. Forwarded to the internal * `DocumentLifecycleContext` when an upload creates a document, and * consulted directly at the upload entry for the kind-aware write ability * check. Required at the field-level upload boundary so `beforeStore` / * `afterStore` hooks can branch on `actor`. */ requestContext?: RequestContext; } export interface UploadFieldParams { buffer: Buffer; originalFilename: string; mimeType: string; fileSize: number; fields?: Record; shouldCreateDocument?: boolean; locale?: string; } export interface UploadFieldResult { revision?: number; documentId?: string; documentVersionId?: string; /** * The persisted file value, including the `variants` array with * `storagePath`, `storageUrl`, `width`, `height`, and `format` for each * generated derivative. Single source of truth — the legacy top-level * `variants` list is gone. */ storedFile: StoredFileValue; } export declare function uploadField(ctx: FieldUploadContext, params: UploadFieldParams): Promise;