Media API reference
Current emitted signatures and options for @db3.ai/app/media.
On this page
Source-backed MarkdownImports and examples
Import supported APIs from @db3.ai/app/media. These signatures come from the staged package used by consumers. Relative filenames in declarations describe type dependencies; they are not extra supported deep imports.
Use the guide for setup, executable examples, failure handling and ownership. A signature is not proof that every deployment or provider has been exercised.
Managed file and library operations
ts
import type { Readable } from 'node:stream';
import type { Storage } from '../storage/index.js';
import type { MediaOptions } from './contracts/index.js';
import { type ImageProcessor, type ImageVariant, type ImageVariantOptions } from './image/index.js';
import { MediaFile } from './MediaFile.js';
import { MediaItem } from './MediaItem.js';
import { MediaLibrary } from './MediaLibrary.js';
import type { MediaAttachFileInput, MediaFolderInput, MediaLibraryInput, MediaLibraryScope, MediaStoreFileInput, MediaStoreFileStreamInput, MediaStoreReconstructedVisibleImageStreamInput, MediaStoredVisibleFile, MediaStoreVisibleFileInput, MediaStoreVisibleFileStreamInput } from './types.js';
/**
* Framework service for managed media libraries, files, and browser items.
*
* Storage remains responsible for bytes. This manager records file metadata,
* scopes files through media libraries, and creates optional folder-tree rows
* for media browser UIs.
*/
export declare class MediaManager {
#private;
private readonly storage;
/**
* Creates a media manager backed by the application storage service.
*
* @param storage - Storage manager used to write and read file bytes.
* @param options - Media rendering and derived-file cache configuration.
* @param imageProcessor - Concrete image processing engine.
*/
constructor(storage: Storage, options?: MediaOptions, imageProcessor?: ImageProcessor);
/**
* Finds or creates the media library for an application-owned scope.
*
* @param input - Scope identity and defaults for a new library.
* @returns Existing or newly-created media library.
*
* @example
* const library = await app.media.libraryFor({
* scopeType: 'scout.website',
* scopeId: website.id,
* key: 'default',
* name: 'Website media',
* });
*/
libraryFor(input: MediaLibraryScope): Promise<MediaLibrary>;
/**
* Loads one media library by id.
*
* @param id - Media library ULID.
* @returns Media library row or null.
*/
library(id: string): Promise<MediaLibrary | null>;
/**
* Loads one managed file by id.
*
* @param id - Managed file ULID.
* @returns Managed file row or null.
*/
file(id: string): Promise<MediaFile | null>;
/**
* Writes bytes to storage and records a managed file row.
*
* The file is not visible in the media browser until `attachFile()` creates a
* `MediaItem` that points to it.
*
* @param input - File contents, library, storage options, and metadata.
* @returns Managed file row.
*/
storeFile(input: MediaStoreFileInput): Promise<MediaFile>;
/**
* Streams bytes to storage and records a managed file row.
*
* This is the preferred media finalization path for resumable uploads because
* completed temporary files do not need to be buffered in application memory.
*
* @param input - File stream, library, storage options, and metadata.
* @returns Managed file row.
*/
storeFileStream(input: MediaStoreFileStreamInput): Promise<MediaFile>;
/**
* Reads managed file bytes from the storage disk recorded on the file row.
*
* @param fileOrId - Managed file row or id.
* @returns Stored file bytes.
*/
readFile(fileOrId: MediaFile | string): Promise<Buffer>;
/**
* Opens a managed file as a storage-backed readable stream.
*
* @param fileOrId - Managed file row or ULID.
* @returns Stream containing the stored file bytes.
*/
readFileStream(fileOrId: MediaFile | string): Promise<Readable>;
/**
* Renders a responsive managed image into the configured disposable cache.
*
* @param fileOrId - Managed image row or ULID.
* @param options - Requested responsive image dimensions.
* @returns Rendered image stream and cache metadata.
*
* @example
* const image = await app.media.renderImage(imageId, {
* width: 640,
* });
*/
renderImage(fileOrId: MediaFile | string, options: ImageVariantOptions): Promise<ImageVariant>;
/**
* Permanently deletes a managed file, its browser placements, and stored bytes.
*
* Browser item rows are removed through their database foreign key to the
* managed file. Disposable responsive-image variants are cleared before the
* durable source bytes and database record are removed.
*
* @param fileOrId - Managed file row or ULID to permanently delete.
*/
deleteFile(fileOrId: MediaFile | string): Promise<void>;
/**
* Finds or creates the root browser item for a library.
*
* @param libraryOrId - Media library row or id.
* @returns Root browser item for the library.
*/
rootFor(libraryOrId: MediaLibraryInput): Promise<MediaItem>;
/**
* Finds or creates a slash-prefixed browser folder path.
*
* @param input - Library and folder path to ensure.
* @returns Folder item for the requested path, or the root for `/`.
*/
ensureFolder(input: MediaFolderInput): Promise<MediaItem>;
/**
* Places an existing managed file into the browser tree.
*
* @param input - File, target library, folder path, and optional item metadata.
* @returns Browser item pointing at the managed file.
*/
attachFile(input: MediaAttachFileInput): Promise<MediaItem>;
/**
* Writes bytes to storage and creates a browser item for the file.
*
* @param input - File storage input plus optional browser placement.
* @returns Stored file and browser item rows.
*/
storeVisibleFile(input: MediaStoreVisibleFileInput): Promise<MediaStoredVisibleFile>;
/**
* Streams bytes to storage and creates a browser item for the file.
*
* @param input - File stream and storage input plus optional browser placement.
* @returns Stored file and browser item rows.
*/
storeVisibleFileStream(input: MediaStoreVisibleFileStreamInput): Promise<MediaStoredVisibleFile>;
/**
* Fully decodes and reconstructs an untrusted image before durable storage.
*
* The processor emits new canonical bytes without source metadata or trailing
* payloads. No media row becomes visible unless the complete processor stream
* is successfully written.
*
* @param input - Untrusted image stream and browser placement metadata.
* @returns Stored reconstructed file and browser item rows.
*/
storeReconstructedVisibleImageStream(input: MediaStoreReconstructedVisibleImageStreamInput): Promise<MediaStoredVisibleFile>;
}
Inputs and results
ts
import type { Readable } from 'node:stream';
import type { StorageContents } from '../storage/index.js';
import type { MediaFileVisibility } from './constants.js';
import type { MediaFile } from './MediaFile.js';
import type { MediaItem } from './MediaItem.js';
import type { MediaLibrary } from './MediaLibrary.js';
/**
* App-owned scope used to find or create a media library.
*/
export interface MediaLibraryScope {
/** Opaque scope type such as `scout.website` or `scout.organization`. */
scopeType: string;
/** Opaque app-owned scope id. */
scopeId: string;
/** Scope-local library key. Defaults to `default`. */
key?: string;
/** Human-readable library name used when a new library is created. */
name?: string;
/** Optional default storage disk for files written into this library. */
defaultDisk?: string | null;
/** Optional storage path prefix for files written into this library. */
pathPrefix?: string | null;
/** Optional app-owned library metadata. */
meta?: Record<string, unknown> | null;
}
/**
* Library input accepted by media manager methods.
*/
export type MediaLibraryInput = MediaLibrary | string;
/**
* Input for writing a managed file without making it visible in the browser.
*/
export interface MediaStoreFileInput {
/** Existing media library or library id that will own the file. */
library: MediaLibraryInput;
/** File bytes or text accepted by the storage layer. */
contents: StorageContents;
/** Optional display filename. Defaults to the file id plus MIME extension. */
name?: string | null;
/** MIME type recorded on the file and passed to storage writes. */
mimeType?: string | null;
/** Optional storage disk override. Defaults to the library disk or app default. */
disk?: string | null;
/** Optional storage path override. Defaults to a library-scoped generated path. */
path?: string | null;
/** Optional app-owned source label such as generated-image or upload. */
source?: string | null;
/** Storage visibility used for the write. Defaults to private. */
visibility?: MediaFileVisibility | null;
/** Optional known byte size. Defaults to the byte length of the supplied contents. */
size?: number | null;
/** Optional app-owned file metadata. */
meta?: Record<string, unknown> | null;
}
/**
* Input for streaming a managed file without buffering it in application memory.
*/
export interface MediaStoreFileStreamInput extends Omit<MediaStoreFileInput, 'contents'> {
/** Readable stream containing the file bytes. */
stream: Readable;
/** Known byte size, or null when storage should measure the completed stream. */
size?: number | null;
}
/**
* Input for showing an existing managed file in the browser tree.
*/
export interface MediaAttachFileInput {
/** Existing media library or library id that owns the browser tree. */
library: MediaLibraryInput;
/** Managed file or file id to place in the browser. */
file: MediaFile | string;
/** Slash-prefixed folder path. Defaults to the library root. */
folderPath?: string | null;
/** Optional browser row name. Defaults to the file name. */
name?: string | null;
/** Optional app-owned item metadata. */
meta?: Record<string, unknown> | null;
}
/**
* Input for writing a file and immediately placing it in the browser tree.
*/
export interface MediaStoreVisibleFileInput extends MediaStoreFileInput {
/** Slash-prefixed folder path for the browser item. Defaults to the library root. */
folderPath?: string | null;
/** Optional browser row name. Defaults to the stored filename. */
itemName?: string | null;
/** Optional browser item metadata. */
itemMeta?: Record<string, unknown> | null;
}
/**
* Input for streaming a file and immediately placing it in the browser tree.
*/
export interface MediaStoreVisibleFileStreamInput extends MediaStoreFileStreamInput {
/** Slash-prefixed folder path for the browser item. Defaults to the library root. */
folderPath?: string | null;
/** Optional browser row name. Defaults to the stored filename. */
itemName?: string | null;
/** Optional browser item metadata. */
itemMeta?: Record<string, unknown> | null;
}
/**
* Input for reconstructing an image stream before durable browser placement.
*/
export interface MediaStoreReconstructedVisibleImageStreamInput extends Omit<MediaStoreVisibleFileStreamInput, 'mimeType' | 'size'> {
/** Allowlisted source MIME type used for decoding and canonical output. */
mimeType: string;
}
/**
* Result returned after a file is written and placed in the browser tree.
*/
export interface MediaStoredVisibleFile {
/** Library that owns the file and item. */
library: MediaLibrary;
/** Managed file row for loading bytes by ULID. */
file: MediaFile;
/** Browser-visible item row that points at the managed file. */
item: MediaItem;
}
/**
* Input for creating or finding a browser folder.
*/
export interface MediaFolderInput {
/** Existing media library or library id that owns the browser tree. */
library: MediaLibraryInput;
/** Slash-prefixed folder path to ensure. */
path: string;
/** Optional folder metadata applied only when a folder is created. */
meta?: Record<string, unknown> | null;
}
Service options
ts
import type { ImageVariantCacheOptions } from '../image/contracts/index.js';
/**
* Framework media-service configuration.
*/
export interface MediaOptions {
/** Responsive-image rendering and disposable cache configuration. */
images?: ImageVariantCacheOptions;
}
File model
ts
import { ActiveRecord, type FieldBuilder } from '../db/index.js';
import type { EntityRef } from '../db/fields/LinkField.js';
import { MEDIA_FILE_VISIBILITY } from './constants.js';
import { MediaLibrary } from './MediaLibrary.js';
/**
* Managed file record for bytes stored through the framework storage service.
*
* A file can be managed without appearing in a media browser. Browser placement
* is represented separately by `MediaItem` rows that point to this file.
*/
export declare class MediaFile extends ActiveRecord {
static table: string;
static primaryKey: string;
static labelFields: string[];
static comment: string;
/**
* Defines managed file metadata and storage location fields.
*
* @param field - ActiveRecord field builder.
* @returns Field definitions for schema generation and value conversion.
*/
static fields(field: FieldBuilder): {
id: import("../db/index.js").UlidField;
library: import("../db/index.js").LinkField<MediaLibrary>;
disk: import("../db/index.js").StringField;
path: import("../db/index.js").StringField;
name: import("../db/index.js").StringField;
mimeType: import("../db/index.js").StringField;
size: import("../db/index.js").IntegerField;
visibility: import("../db/index.js").ChoiceStringField;
source: import("../db/index.js").StringField;
meta: import("../db/index.js").JsonField<Record<string, unknown> | null>;
createdAt: import("../db/index.js").TimestampField;
updatedAt: import("../db/index.js").TimestampField;
};
id: string | null;
library: EntityRef<MediaLibrary>;
disk: string | null;
path: string | null;
name: string | null;
mimeType: string | null;
size: number | null;
visibility: typeof MEDIA_FILE_VISIBILITY[keyof typeof MEDIA_FILE_VISIBILITY] | null;
source: string | null;
meta: Record<string, unknown> | null;
createdAt: Date | null;
updatedAt: Date | null;
}
Library model
ts
import { ActiveRecord, type FieldBuilder } from '../db/index.js';
/**
* Scoped namespace for managed files and browser-visible media items.
*
* Apps use `scopeType`, `scopeId`, and `key` to map their own ownership model
* onto the framework media tables without adding app-specific columns such as
* `website_id` or `organization_id`.
*/
export declare class MediaLibrary extends ActiveRecord {
static table: string;
static primaryKey: string;
static labelFields: string[];
static comment: string;
/**
* Defines the media library schema and scope identity indexes.
*
* @param field - ActiveRecord field builder.
* @returns Field definitions for schema generation and value conversion.
*/
static fields(field: FieldBuilder): {
id: import("../db/index.js").UlidField;
scopeType: import("../db/index.js").StringField;
scopeId: import("../db/index.js").StringField;
key: import("../db/index.js").StringField;
name: import("../db/index.js").StringField;
defaultDisk: import("../db/index.js").StringField;
pathPrefix: import("../db/index.js").StringField;
meta: import("../db/index.js").JsonField<Record<string, unknown> | null>;
createdAt: import("../db/index.js").TimestampField;
updatedAt: import("../db/index.js").TimestampField;
};
id: string | null;
scopeType: string | null;
scopeId: string | null;
key: string | null;
name: string | null;
defaultDisk: string | null;
pathPrefix: string | null;
meta: Record<string, unknown> | null;
createdAt: Date | null;
updatedAt: Date | null;
}
Browser item model
ts
import { ActiveRecord, type FieldBuilder } from '../db/index.js';
import type { EntityRef } from '../db/fields/LinkField.js';
import { type MediaItemType } from './constants.js';
import { MediaFile } from './MediaFile.js';
import { MediaLibrary } from './MediaLibrary.js';
/**
* Folder-tree row used by media browser surfaces.
*
* Files can exist without media items. A `file` media item is only created when
* the managed file should be visible inside a library browser.
*/
export declare class MediaItem extends ActiveRecord {
static table: string;
static primaryKey: string;
static labelFields: string[];
static comment: string;
/**
* Defines media browser tree fields and library-scoped path indexes.
*
* @param field - ActiveRecord field builder.
* @returns Field definitions for schema generation and value conversion.
*/
static fields(field: FieldBuilder): {
id: import("../db/index.js").UlidField;
library: import("../db/index.js").LinkField<MediaLibrary>;
type: import("../db/index.js").ChoiceStringField;
root: import("../db/index.js").LinkField<MediaItem>;
parent: import("../db/index.js").LinkField<MediaItem>;
file: import("../db/index.js").LinkField<MediaFile>;
name: import("../db/index.js").StringField;
path: import("../db/index.js").StringField;
meta: import("../db/index.js").JsonField<Record<string, unknown> | null>;
createdAt: import("../db/index.js").TimestampField;
updatedAt: import("../db/index.js").TimestampField;
};
id: string | null;
library: EntityRef<MediaLibrary>;
type: MediaItemType | null;
root: EntityRef<MediaItem> | null;
parent: EntityRef<MediaItem> | null;
file: EntityRef<MediaFile> | null;
name: string | null;
path: string | null;
meta: Record<string, unknown> | null;
createdAt: Date | null;
updatedAt: Date | null;
}
Image request parsing
ts
import type { ImageVariantOptions } from './contracts/index.js';
/**
* Error raised when an untrusted image variant request cannot be translated
* into an allowlisted framework command.
*/
export declare class ImageVariantRequestError extends RangeError {
readonly code: 'invalid_image_width';
/**
* Creates an invalid image request error.
*
* @param message - Safe explanation suitable for an HTTP error response.
* @param code - Stable application error code for HTTP adapters.
*/
constructor(message: string, code: 'invalid_image_width');
}
/**
* Translates URL query parameters into a safe image variant command.
*
* Only documented parameters are interpreted. Unknown parameters are ignored
* and no processor option is accepted directly from the request.
*
* @param searchParams - URL query parameters supplied by an HTTP adapter.
* @returns Validated variant options, or null when the original is requested.
*
* @example
* const options = imageVariantOptionsFromSearchParams(requestUrl.searchParams);
*/
export declare function imageVariantOptionsFromSearchParams(searchParams: URLSearchParams): ImageVariantOptions | null;
Image processing contract
ts
import type { Duplex } from 'node:stream';
/**
* Allowlisted image transformation passed to a concrete processing engine.
*/
export interface ImageProcessorCommand {
/** Normalized MIME type of the encoded source stream. */
sourceMimeType: string;
/** Normalized MIME type the processor must emit. */
outputMimeType: string;
/** Maximum output width in pixels, or null to preserve source dimensions. */
width: number | null;
}
/**
* Canonical image reconstruction passed to a concrete processing engine.
*
* Reconstruction decodes the complete untrusted input and emits a new image
* without preserving source metadata or trailing source bytes.
*/
export interface ImageProcessorReconstructionCommand {
/** Normalized MIME type already identified from the encoded source stream. */
sourceMimeType: string;
/** Normalized MIME type the processor must use for the reconstructed image. */
outputMimeType: string;
}
/**
* Adapter implemented by a concrete image processing engine.
*
* The framework owns request parsing, cache identity, storage, and concurrency.
* Processors only translate a trusted command into a bounded transform stream.
*/
export interface ImageProcessor {
/**
* Creates a stream that transforms encoded source bytes into an image variant.
*
* @param command - Validated transformation command.
* @returns Duplex stream that accepts source bytes and emits encoded output.
*/
transform(command: ImageProcessorCommand): Duplex;
/**
* Creates a stream that fully decodes and reconstructs an untrusted image.
*
* @param command - Validated canonical reconstruction command.
* @returns Duplex stream that accepts source bytes and emits reconstructed bytes.
*/
reconstruct(command: ImageProcessorReconstructionCommand): Duplex;
}
Variant results
ts
import type { Readable } from 'node:stream';
/**
* Maximum rendered image width accepted by the framework.
*
* Bounding width protects the application from accidental or malicious
* requests that would create excessively large decoded images.
*/
export declare const MAX_IMAGE_VARIANT_WIDTH = 4096;
/**
* Options that identify one cached responsive image variant.
*/
export interface ImageVariantOptions {
/**
* Requested pixel width. Aspect ratio is preserved and images are never
* enlarged. Omit the width to compress the source at its original dimensions.
*/
width?: number;
}
/**
* Storage-backed responsive image returned by the media service.
*/
export interface ImageVariant {
/** Rendered image stream loaded from durable storage. */
stream: Readable;
/** MIME type of the rendered bytes. */
mimeType: string;
/** Storage path used on the configured disposable cache disk, or null for passthrough images. */
path: string | null;
/** Whether the bytes were loaded from an existing generated variant. */
cached: boolean;
}
Variant cache options
ts
/**
* Storage configuration for disposable responsive-image variants.
*
* Generated variants are derived from durable managed files and may be removed
* at any time. A missing variant is regenerated on the next image request.
*/
export interface ImageVariantCacheOptions {
/**
* Named storage disk used for generated variants.
*
* Omit this value to use the managed source file's disk.
*/
cacheDisk?: string;
/**
* Relative directory containing generated variants on the cache disk.
*
* Defaults to `image-cache`.
*/
cachePrefix?: string;
}
Reconstruction failures
ts
/**
* Indicates that untrusted source bytes could not be decoded and reconstructed.
*
* Storage and database failures remain their original error types so callers
* can distinguish invalid image input from application infrastructure errors.
*/
export declare class ImageReconstructionError extends Error {
/**
* Creates an image reconstruction error with its processor failure attached.
*
* @param message - Stable application-facing failure summary.
* @param options - Standard error options containing the processor cause.
*/
constructor(message: string, options?: ErrorOptions);
}