/** * The chainable, thenable media builder — the implementor-facing front-end that compiles to * the same {@link MediaPlan} as the pipe string and JSON ops. * * @remarks * Internal sibling of the `@nhtio/adk/batteries/media` entry. The knex lessons applied: * `mp(input)` opens a fresh immutable builder; every verb returns a new builder; awaiting the * builder executes the chain (no `.execute()`). Domain verbs hang off typed namespaces * (`.sheet`, `.slides`, `.image`, `.audio`); shared transforms live on the root. * * Each verb method appends an op and revalidates lazily — the full plan validates (verb table, * arg schemas, engine narrowing) when the chain executes, so building is cheap and the same * validator serves all three front-ends. */ import type { ImageAnnotation } from "./contracts"; import type { PlanResult, StepPayload } from "./runtime"; import type { MediaOp, MediaArgValue } from "./plan"; /** The function a builder calls to execute its accumulated ops. Bound by the pipeline. */ export type ChainExecutor = (ops: MediaOp[]) => Promise; /** Options accepted by image resize. */ export interface ResizeOptions { /** Target width in pixels. */ width?: number; /** Target height in pixels. */ height?: number; /** Resize fit mode (default cover). */ fit?: 'cover' | 'contain' | 'fill' | 'inside' | 'outside'; } /** A cell update for `sheet.updateCells`. */ export interface CellUpdate { /** A1-notation address, e.g. `B2`. Alternative to row/col. */ address?: string; /** One-based row index. Pair with `col`. */ row?: number; /** One-based column index, or a column letter. Pair with `row`. */ col?: number | string; /** The value to set. A leading `=` writes a formula. */ value: string | number | boolean | null; } /** How other media are referenced from builder verbs: an id string or `{ mediaId }`. */ export type MediaChainRef = string | { mediaId: string; }; /** * The chainable builder. Immutable — every verb returns a new instance sharing the executor. * Thenable — `await` runs the chain and resolves to the terminal step's natural type. */ export declare class MediaChain implements PromiseLike { #private; constructor(exec: ChainExecutor, ops?: MediaOp[]); /** Convert to another format (requires a convert engine). */ convert(to: string): MediaChain; /** Keep only the listed 1-based pages. */ select(options: { pages: number[]; }): MediaChain; /** Split by page (optionally grouped `[[start,end], …]`). Terminal: resolves to media list. */ split(options?: { by?: 'page' | 'section'; ranges?: number[][]; }): MediaChain; /** Merge other media into this one, in order. */ merge(...others: MediaChainRef[]): MediaChain; /** Reorder pages by 1-based index. */ reorder(order: number[]): MediaChain; /** Redact matching text (literals or RegExp). */ redact(options: { match: Array | string | RegExp; replace?: string; }): MediaChain; /** Remove potentially unsafe embedded content. */ sanitize(): MediaChain; /** Normalize structure/encoding. */ normalize(): MediaChain; /** Replace the first occurrence of anchor text. */ updateText(anchor: string, replace: string): MediaChain; /** Compare against another media. Terminal: resolves to a structured diff. */ diff(other: MediaChainRef): MediaChain; /** Apply a unified-diff patch. */ applyPatch(patch: string, options?: { with?: MediaChainRef[]; }): MediaChain; /** Extract text (routes by format; OCR engine used when needed). Terminal: resolves to text. */ extractText(options?: { ocr?: 'off' | 'auto' | 'force'; ocrOut?: 'txt' | 'hocr' | 'json'; lang?: string[]; }): MediaChain; /** Extract metadata. Terminal: resolves to a metadata object. */ extractMetadata(): MediaChain; /** Extract embedded assets. Terminal: resolves to a media list. */ extractAssets(options?: { types?: Array<'image' | 'font' | 'attachment' | 'all'>; }): MediaChain; /** Chunk extracted text. Terminal: resolves to a chunk array. */ chunk(options?: { strategy?: 'sentence' | 'paragraph' | 'fixed'; size?: number; overlap?: number; }): MediaChain; /** Spreadsheet mutations. */ get sheet(): SheetNamespace; /** Presentation mutations. */ get slides(): SlidesNamespace; /** Image transforms. */ get image(): ImageNamespace; /** Audio operations. */ get audio(): AudioNamespace; /** The accumulated ops (a copy). */ toOps(): MediaOp[]; /** The canonical pipe form of the accumulated chain. */ toPipe(): string; /** Internal — used by namespaces to append. */ withOp(verb: string, args: Record): MediaChain; /** Thenable: awaiting the chain executes it. */ then(onfulfilled?: ((value: unknown) => TResult1 | PromiseLike) | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null): PromiseLike; /** Execute and return the raw {@link PlanResult} (no unwrapping). */ run(): Promise; } /** `sheet.*` verbs, mirrored from the verb table. */ export declare class SheetNamespace { #private; constructor(chain: MediaChain); /** Insert rows. */ addRows(rows: Array>, options?: { sheet?: string | number; before?: number; after?: number; }): MediaChain; /** Insert columns. */ addColumns(options: { sheet?: string | number; headers?: string[]; columns?: Array<{ header: string; values?: Array; }>; before?: number; after?: number; }): MediaChain; /** Update cells. */ updateCells(updates: CellUpdate[], options?: { sheet?: string | number; }): MediaChain; /** Delete rows by 1-based index. */ deleteRows(rows: number[], options?: { sheet?: string | number; }): MediaChain; /** Delete columns by 1-based index. */ deleteColumns(columns: number[], options?: { sheet?: string | number; }): MediaChain; /** Rename a worksheet (name-targeted). */ renameSheet(sheet: string, to: string): MediaChain; /** Add a worksheet. */ addSheet(name: string, options?: { at?: number; }): MediaChain; /** Remove a worksheet (name-targeted). */ removeSheet(sheet: string): MediaChain; /** Reorder worksheets by names and/or 1-based indices. */ reorderSheets(order: Array): MediaChain; /** Table transforms by header name. */ transformTable(options: { sheet?: string | number; headerRow?: number; select?: string[]; drop?: string[]; rename?: Array<{ from: string; to: string; }>; }): MediaChain; } /** `slides.*` verbs. */ export declare class SlidesNamespace { #private; constructor(chain: MediaChain); /** Add a slide. */ add(options?: { at?: number; title?: string; layout?: string; }): MediaChain; /** Update text on a slide. */ updateText(text: string, options?: { slide?: string | number; placeholder?: string; }): MediaChain; /** Update table cells on a slide. */ updateTable(updates: Array<{ row: number; col: number; value: string; }>, options?: { slide?: string | number; }): MediaChain; /** Replace an image on a slide with another media. */ updateImage(withMedia: MediaChainRef, options?: { slide?: string | number; placeholder?: string; }): MediaChain; /** Update chart data on a slide. */ updateChart(data: unknown[][], options?: { slide?: string | number; }): MediaChain; /** Delete slides by 1-based index. */ delete(slides: number[]): MediaChain; /** Reorder slides. */ reorder(order: number[]): MediaChain; /** Duplicate a slide. */ duplicate(slide: number, options?: { at?: number; }): MediaChain; } /** `image.*` verbs (the runtime fuses adjacent image steps into one engine pass). */ export declare class ImageNamespace { #private; constructor(chain: MediaChain); /** Resize. */ resize(options: ResizeOptions): MediaChain; /** Re-encode to another format. */ format(to: string, options?: { quality?: number; stripMetadata?: boolean; }): MediaChain; /** Rotate clockwise. */ rotate(deg: 90 | 180 | 270): MediaChain; /** Flip. */ flip(axis: 'horizontal' | 'vertical' | 'both'): MediaChain; /** Strip EXIF/ICC metadata. */ stripMetadata(): MediaChain; /** Draw vector primitives and text over the image. */ annotate(shapes: ImageAnnotation[]): MediaChain; } /** `audio.*` verbs. */ export declare class AudioNamespace { #private; constructor(chain: MediaChain); /** Transcribe speech. Terminal: resolves to text (or srt/vtt/json per `out`). */ transcribe(options?: { language?: string; out?: 'txt' | 'srt' | 'vtt' | 'json'; translate?: boolean; }): MediaChain; } /** The input shapes `mp(...)` accepts. */ export type ChainInput = StepPayload;