# API reference ## Module forms CommonJS returns the historical callable factory: ```js const createWriteStreamAtomic = require('@stackline/fs-write-stream-atomic') ``` The factory is callable with or without `new`. Its non-enumerable `WriteStreamAtomic` property exposes the constructor identity. ESM provides the same factory as the default export and the constructor as a named export: ```js import createWriteStreamAtomic, { WriteStreamAtomic } from '@stackline/fs-write-stream-atomic' ``` The supported package entries are the root, `./index`, `./index.js`, and `./package.json`. There are no historical `lib/*` deep entries. ## `createWriteStreamAtomic(filename[, options])` Creates a Writable stream whose accepted bytes are written to a randomized, exclusive sibling temporary file. After the underlying file stream closes, the temporary file is renamed over `filename`. - `filename` is a string. - `options` extends Node.js `WritableOptions` and file-stream options. - The result is a `WriteStreamAtomic` instance. - Calling with or without `new` is equivalent. ```js const output = createWriteStreamAtomic('database.bin', { encoding: 'binary', flags: 'w', highWaterMark: 1024 * 1024, mode: 0o600 }) ``` ## `new WriteStreamAtomic(filename[, options])` The named constructor extends the core Node.js `Writable`. Standard methods and properties such as `write`, `end`, `destroy`, `cork`, `uncork`, `writableNeedDrain`, and `destroyed` follow the Node stream contract. The implementation exposes three diagnostic readonly properties in its type surface: - `__atomicTarget`: the requested target filename; - `__atomicTmp`: the adjacent randomized temporary filename; - `__atomicClosed`: whether the atomic lifecycle has closed. Treat these as observations, not mutation hooks. ## Options | Option | Contract | | --- | --- | | `encoding` | Default string encoding passed to the Writable and file stream. | | `highWaterMark` | Writable backpressure threshold. | | `mode` | Mode used when creating the temporary file. | | `flags` | File open flags. `w`, `w+`, `a`, and `a+` are opened exclusively on the new temporary path. | | `chown` | Optional `{ uid, gid }`; ownership is applied to the temporary file before rename. | | other `WritableOptions` | Standard supported core Writable behavior. | The path contract is deliberately string-only. File descriptors, URL objects, Buffer paths, custom temporary directories, and disabling physical auto-close are outside the supported atomic contract. Append flags retain the upstream replacement behavior. Because the temporary file begins empty, `flags: 'a'` writes the newly streamed value and replaces the target; it does not append to the target's previous bytes. ## Writes and backpressure `write(chunk[, encoding][, callback])` accepts data through the outer Writable. When it returns `false`, wait for `drain` before producing more. The callback reports acceptance or an underlying write error. ```js const { once } = require('stream') async function writeChunk(stream, chunk) { let accepted const writeComplete = new Promise((resolve, reject) => { accepted = stream.write(chunk, (error) => { if (error) reject(error) else resolve() }) }) if (!accepted) await once(stream, 'drain') await writeComplete } ``` Use `pipeline(source, destination, callback)` for a source stream. Bare `source.pipe(destination)` does not forward source errors into destination cleanup. ## Events and publication order | Event | Meaning | | --- | --- | | `open` | The adjacent temporary file opened; the descriptor is forwarded. | | `drain` | Buffered writes have fallen below the high-water mark. | | `error` | Write, open, chown, rename, or cleanup failed. | | `finish` | The physical file closed and the replacement rename completed. | | `close` | The outer Writable closed after success or destruction. | On success the relevant order is `open`, writes and possible `drain`, physical temporary-file close, optional `chown`, rename, `finish`, then `close`. The old target remains visible until rename. A successful terminal event therefore observes the complete accepted value at the target. Concurrent writers do not serialize one another. Each publishes a complete candidate; one complete value wins, without byte interleaving. ## Errors and cleanup Explicit `destroy()`, ordinary physical stream errors, rename/chown failures, and errors forwarded by `pipeline()` remove the sibling temporary file. Abrupt process termination can still leave it because JavaScript cleanup is not guaranteed after exit. On Windows, a rename `EPERM` is treated as success only when the existing target and temporary file have identical SHA-512 content. Different content remains an error. ## TypeScript The package ships TypeScript 3.9-compatible CommonJS declarations and modern ESM declarations. ```ts import createWriteStreamAtomic = require('@stackline/fs-write-stream-atomic') const options: createWriteStreamAtomic.Options = { highWaterMark: 64 * 1024, chown: { uid: 1000, gid: 1000 } } const output: createWriteStreamAtomic.WriteStreamAtomic = createWriteStreamAtomic('output.bin', options) ``` See [COMPATIBILITY_CONTRACT.md](./COMPATIBILITY_CONTRACT.md) for the exact preserved and corrected behavior and [SECURITY.md](./SECURITY.md) for the filesystem trust boundary.