flat-file-creator
v3.0.3
Published
Generate a flat positional text file of your dataset
Maintainers
Readme
flat-file-creator
Read and write fixed-width flat files from typed TypeScript data — the boring format your bank still loves, made painless.
Version support
- v3.x — current stable version (
npm install flat-file-creator), see Migration Guide- v2.x — maintenance, security fixes only (
npm install flat-file-creator@v2)
Install
npm install flat-file-creatorRequirements: Node.js ≥ 20, ESM project ("type": "module" or .mjs files).
Quick start
import { getAsyncFlatFileCreator, getAsyncFlatFileReader } from 'flat-file-creator'
// 1. Describe the row layout
const fields = [
{ name: 'firstName', type: 'string', size: 20 },
{ name: 'lastName', type: 'string', size: 20 },
{ name: 'dob', type: 'date', size: 24, format: { utc: true } },
{ name: 'score', type: 'float', size: 8, precision: 2 },
]
// 2. Create writer and reader from the same definition
const writeFile = getAsyncFlatFileCreator(fields)
const readFile = getAsyncFlatFileReader<Person>(fields)
// 3. Write
await writeFile(
[
{ firstName: 'Jo', lastName: 'Revelo', dob: new Date('1986-01-01'), score: 9.75 },
{ firstName: 'Ricky', lastName: 'Springfield', dob: new Date('1975-06-15'), score: 8.50 },
],
'/tmp/people.txt',
)
// 4. Read back — `rows` is fully typed as Person[]
const rows = await readFile('/tmp/people.txt')
console.log(rows[0].dob.getFullYear()) // 1986Field types
Every field needs at minimum name and size. The type defaults to 'string' when omitted.
string
{ name: 'city', type: 'string', size: 30 }| Option | Type | Default | Description |
|---|---|---|---|
| paddingPosition | 'start' \| 'end' | 'end' | Where to add padding |
| paddingSymbol | string | ' ' | Character used for padding |
| preserveEmptySpace | boolean | false | Skip trimming whitespace |
| straight | boolean | false | Throw if value is numeric |
| enum | { [key: string]: string } | — | Serialize/deserialize a set of values |
| default | string \| null | — | Fallback when value is missing |
integer
{ name: 'age', type: 'integer', size: 5 }Integers are left-padded with spaces by default. All standard CommonSpec options apply.
float
{ name: 'score', type: 'float', size: 8, precision: 2 }| Option | Type | Default | Description |
|---|---|---|---|
| precision | number | 0 | Decimal places |
| dotNotation | boolean | false | When false, value is stored as integer × 10^precision |
Example — 9.75 with precision: 2, dotNotation: false → " 975", and back to 9.75 on read.
date
{ name: 'dob', type: 'date', size: 24, format: { utc: true, dateFormat: 'yyyy-MM-dd' } }| Option | Type | Default | Description |
|---|---|---|---|
| format.dateFormat | string | ISO 8601 | date-fns format tokens |
| format.utc | boolean | false | Format in UTC |
| default | Date \| string \| null | — | Fallback when value is missing |
On read, date fields are always returned as native Date objects.
API
function getAsyncFlatFileCreator(
maps: Array<FieldSpec>,
options?: Partial<WriteOptions>
): (dataRows: Array<RowData>, filePath: string) => Promise<void>
function getAsyncFlatFileReader<T>(
maps: Array<FieldSpec>,
options?: Partial<ReadOptions>
): (filePath: string) => Promise<Array<T>>Note: rows are always written in the same order as the input array. Each call to the returned writer opens the file, streams all rows sequentially, then closes it.
Options
Both getAsyncFlatFileCreator and getAsyncFlatFileReader accept an optional second argument:
interface ReadOptions {
rowEnd?: string // line terminator, default ''
encoding?: BufferEncoding // default 'utf8'
throwErrors?: boolean // throw on structural errors, default true
}
interface WriteOptions extends ReadOptions {
mode?: number // file mode, default 0o666
flag?: string // fs flag, default 'a' (append)
}Type definitions
type RowData = { [fieldName: string]: string | number | boolean | Date | null | undefined }
type CommonSpec = {
name: string
size: number
paddingPosition?: 'start' | 'end'
paddingSymbol?: string
desc?: string
}
type StringFieldSpec = CommonSpec & {
type?: 'string'
enum?: { [serializedKey: string]: string }
preserveEmptySpace?: boolean
straight?: boolean
default?: string | null
}
type IntegerFieldSpec = CommonSpec & {
type: 'integer'
default?: number | null
}
type FloatFieldSpec = CommonSpec & {
type: 'float'
precision?: number
dotNotation?: boolean
default?: number | null
}
type DateFieldSpec = CommonSpec & {
type: 'date'
format?: { utc?: boolean; dateFormat?: string }
default?: Date | string | null
}
type FieldSpec = StringFieldSpec | IntegerFieldSpec | FloatFieldSpec | DateFieldSpecWorking with lines directly
If you prefer to work with strings instead of files, two lower-level helpers are available:
import { dataToLines, linesToData } from 'flat-file-creator'
const lines = dataToLines(rows, fields) // string[]
const rows = linesToData(lines.join('\n'), fields) // T[]Migrating from v2 to v3
v3 is a clean break. If you can't migrate yet, v2.x stays available and receives security fixes.
npm install flat-file-creator # v3, current stable
npm install flat-file-creator@v2 # stay on v21. Node.js ≥ 20 required
v2 supports Node.js 10+. v3 requires Node.js 20 or later.
2. Pure ESM — no CommonJS support
v3 is a pure ESM package and cannot be require()'d. If your project is still on CommonJS
and cannot migrate, stay on v2.
// v3 — ESM only
import { getAsyncFlatFileCreator } from 'flat-file-creator'3. moment removed — date format tokens changed
v3 replaces moment with date-fns. Update your dateFormat tokens:
| v2 (moment) | v3 (date-fns) |
|---|---|
| YYYY | yyyy |
| DD | dd |
| HH, mm, ss | unchanged |
// v2
{ type: 'date', format: { dateFormat: 'DD/MM/YYYY' } }
// v3
{ type: 'date', format: { dateFormat: 'dd/MM/yyyy' } }4. Moment type removed from DateFieldValue
DateFieldValue no longer accepts moment objects:
// v2
import moment from 'moment'
const dob = moment('1986-01-01')
// v3
const dob = new Date('1986-01-01') // or just '1986-01-01'5. Date fields return Date instead of Moment
// v2
rows[0].dob.year() // moment API
// v3
rows[0].dob.getFullYear() // native Date API6. getAsyncFlatFileCreator return type changed
The writer now returns Promise<void> instead of Promise<string[]>. The previous return value
was an array of file paths (one per row) with no practical use. If your code consumed it, remove it:
// before
const result = await writeFile(rows, '/tmp/out.txt') // result was string[]
// after
await writeFile(rows, '/tmp/out.txt')Row ordering is now guaranteed — rows are always written in the same order as the input array. If your code worked around the previous non-deterministic ordering, that workaround can be removed.
