/** * WorkbookWriter - Browser Streaming Excel Writer * * This module contains the full cross-platform implementation for the streaming * workbook writer and a browser-compatible `WorkbookWriter` class. * * Node.js uses `workbook-writer.ts`, which extends the same base implementation * with filesystem-specific features (filename output + image loading). */ import { Zip } from "../../archive/zip/stream.js"; import { DefinedNames } from "../defined-names.js"; import { WorksheetWriter } from "./worksheet-writer.js"; import type { Font, ImageData, WorkbookView, WorkbookProtection, AddWorksheetOptions } from "../types.js"; import { SharedStrings } from "../utils/shared-strings.js"; import { StylesXform } from "../xlsx/xform/style/styles-xform.js"; import type { Writable } from "../../stream/index.js"; /** * An image registered in the streaming writer. * * Extends the public {@link ImageData} shape with the unique stored name * (`name`) assigned by `addImage`, and pins `type` to `"image"`. */ export interface Medium extends Omit { type: "image"; name: string; /** * Widened from `ImageData.extension` so an SVG companion medium can carry * the `"svg"` extension (the public `addImage` input stays raster-only). */ extension: string; /** Media index of an SVG companion (raster blip + svgBlip extension). */ svgMediaId?: number; } interface CommentRef { commentName: string; vmlDrawing: string; } export interface ZlibOptions { flush?: number; finishFlush?: number; chunkSize?: number; windowBits?: number; level?: number; memLevel?: number; strategy?: number; dictionary?: Uint8Array | ArrayBuffer; } export interface WorkbookZipOptions { comment?: string; forceLocalTime?: boolean; forceZip64?: boolean; store?: boolean; zlib?: Partial; compressionOptions?: { level?: number; }; } export interface WorkbookWriterOptions { created?: Date; modified?: Date; creator?: string; lastModifiedBy?: string; lastPrinted?: Date; useSharedStrings?: boolean; useStyles?: boolean; zip?: Partial; stream?: Writable | WritableStream; filename?: string; trueStreaming?: boolean; } interface OutputStreamLike { emit(eventName: string | symbol, ...args: unknown[]): boolean; write(chunk: Uint8Array | string): boolean | Promise; end(): void; once(eventName: string | symbol, listener: (...args: any[]) => void): this; removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this; on?(eventName: string | symbol, listener: (...args: any[]) => void): this; } export interface WorksheetWriterLike { id: number; name: string; rId?: string; committed?: boolean; stream: any; commit(): void; /** Drawing model — populated after commit if images were added */ drawing?: { rId: string; name: string; anchors: any[]; rels: any[]; }; } export interface WorksheetWriterConstructor { new (options: { id: number; name: string; workbook: any; useSharedStrings: boolean; properties?: any; state?: any; pageSetup?: any; views?: any; autoFilter?: any; headerFooter?: any; }): T; } export declare abstract class WorkbookWriterBase { created: Date; modified: Date; creator: string; lastModifiedBy: string; lastPrinted?: Date; useSharedStrings: boolean; sharedStrings: SharedStrings; styles: StylesXform; private _definedNames; private _worksheets; views: WorkbookView[]; zipOptions?: Partial; compressionLevel: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; media: Medium[]; commentRefs: CommentRef[]; /** Number of cells with dynamic array formulas, accumulated during worksheet commit */ dynamicArrayCount: number; /** Workbook-level structure protection */ protection?: { lockStructure?: boolean; lockWindows?: boolean; lockRevision?: boolean; algorithmName?: string; hashValue?: string; saltValue?: string; spinCount?: number; }; zip: Zip; stream: OutputStreamLike; promise: Promise; protected _trueStreaming: boolean; protected WorksheetWriterClass: WorksheetWriterConstructor; private _needsDrain; private _drainResolvers; private _drainListenerAttached; private _sinkError; constructor(options: WorkbookWriterOptions, WorksheetWriterClass: WorksheetWriterConstructor); /** * Create output stream - can be overridden by Node.js to support filename */ protected _createOutputStream(options: WorkbookWriterOptions): OutputStreamLike; /** * Internal: record whether the sink accepted the last write. The * `OutputStreamLike.write` type advertises `boolean | Promise` * for forward compatibility, but in practice every concrete sink we * accept (Node `Writable`, browser `Writable` from `@stream`, internal * `StreamBuf`, fs.WriteStream, etc) returns a sync `boolean`. We * defensively handle the Promise shape but it's never exercised. */ private _trackBackpressure; private _ensureDrainListener; /** * Attach error/close listeners on the user sink so any parked backpressure * waiters are released the moment the sink fails. Without this, a * `commit()` parked on `_waitForUserSinkDrain()` would hang forever if * the sink errored before emitting 'drain'. Idempotent and a no-op for * sinks that don't expose `.on` (e.g. internal `StreamBuf`). * * Uses a non-consuming listener: if the user has their own 'error' handler * it still fires (EventEmitter broadcasts to all listeners). The error is * also captured into `_sinkError` so `_finalize()` can replay it — `_finalize` * registers its own listener with `once()`, which would miss errors that * arrived earlier in the commit pipeline. */ private _lifecycleListenersAttached; private _attachSinkLifecycleListeners; private _wakeAllBackpressureWaiters; /** * Park here until any async writes have settled and the user sink has * drained below its high-water mark. Resolves immediately when no * backpressure is in flight. * * Called at async boundaries inside `commit()` so a slow sink throttles * the producer instead of letting bytes accumulate unboundedly. */ private _waitForUserSinkDrain; get definedNames(): DefinedNames; /** * The default font for the workbook (fontId=0 / "Normal" style). * Must be set before any worksheet rows are committed. */ get defaultFont(): Partial | undefined; set defaultFont(font: Partial | undefined); protected _addFile(data: string | Uint8Array, name: string, base64?: boolean): void; private _commitWorksheets; commit(): Promise; get nextId(): number; /** * Register an image with the workbook and return its numeric id. * * Supply `buffer`/`base64`/`filename` to **embed** the bytes, or only `link` * (a URL or local file path) to reference it **externally** — in which case * no bytes are written into the package and the relationship is emitted with * `TargetMode="External"`. If both are provided, embedding wins. * * Linked images work with cell pictures and overlay watermarks; worksheet * background images and header/footer (VML) watermarks cannot be linked. * * @example * ```typescript * const id = wb.addImage({ extension: "png", link: "https://example.com/logo.png" }); * ws.addImage(id, "B2:D6"); * ``` */ addImage(image: ImageData): number; getImage(id: number): Medium | undefined; /** * Protect the workbook structure with an optional password. * Prevents users from adding, deleting, renaming, moving, or copying worksheets. */ protect(password?: string, options?: Partial): Promise; /** * Remove workbook structure protection. */ unprotect(): void; addWorksheet(name?: string, options?: Partial): TWorksheetWriter; getWorksheet(id?: string | number): TWorksheetWriter | undefined; addStyles(): Promise; addThemes(): Promise; addOfficeRels(): Promise; addContentTypes(): Promise; /** * Add media files - can be overridden by Node.js for file system support */ addMedia(): Promise; /** * Generate drawing XML and drawing relationship files for worksheets that have images. * Must be called after _commitWorksheets() so that each WorksheetWriter has built its * drawing model, and after addMedia() so that media files are already in the ZIP. */ protected addDrawings(): void; addApp(): Promise; addCore(): Promise; addSharedStrings(): Promise; addFeaturePropertyBag(): Promise; addMetadata(): Promise; addWorkbookRels(): Promise; addWorkbook(): Promise; private _finalize; } export declare const WorkbookWriterOptionsSchema: { readonly useSharedStrings: readonly ["boolean"]; readonly useStyles: readonly ["boolean"]; readonly trueStreaming: readonly ["boolean"]; }; declare class WorkbookWriter extends WorkbookWriterBase { constructor(options?: WorkbookWriterOptions); } export { WorkbookWriter };