@reportwright/engine 0.12.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +133 -1
- package/README.md +133 -12
- package/THIRD-PARTY-NOTICES.md +52 -0
- package/dist/index.js +6066 -4454
- package/dist/pdfstreamworker.js +2 -2
- package/dist/types/packages/engine/entry.d.ts +87 -5
- package/dist/types/src/engine/data/guard.d.ts +4 -1
- package/dist/types/src/engine/data/index.d.ts +14 -1
- package/dist/types/src/engine/expr/evaluate.d.ts +1 -0
- package/dist/types/src/engine/index.d.ts +11 -3
- package/dist/types/src/engine/items/chart-kit.d.ts +6 -0
- package/dist/types/src/engine/lazylibs.d.ts +46 -0
- package/dist/types/src/engine/notices.d.ts +1 -0
- package/dist/types/src/engine/options.d.ts +10 -0
- package/dist/types/src/engine/schema/report.schema.d.ts +3 -0
- package/dist/types/src/engine/stream.d.ts +32 -35
- package/dist/types/src/engine/text/fonts.d.ts +30 -5
- package/dist/types/src/engine/text/measure.d.ts +6 -0
- package/dist/types/src/engine/text/standard.d.ts +42 -0
- package/dist/types/src/exporters/docx.d.ts +19 -1
- package/dist/types/src/exporters/html.d.ts +9 -5
- package/dist/types/src/exporters/officestream.d.ts +27 -0
- package/dist/types/src/exporters/pdf.d.ts +5 -3
- package/dist/types/src/exporters/pdfpaint.d.ts +3 -11
- package/dist/types/src/exporters/pdfstandard.d.ts +23 -0
- package/dist/types/src/exporters/pdfstream.d.ts +16 -8
- package/dist/types/src/exporters/pdfstreamtags.d.ts +8 -1
- package/dist/types/src/exporters/spill.d.ts +20 -0
- package/dist/types/src/exporters/subset.d.ts +15 -0
- package/dist/types/src/exporters/xlsxstream.d.ts +22 -0
- package/examples/stream-1m.mjs +21 -8
- package/package.json +5 -3
- package/pool/worker.js +1 -1
- package/report.d.ts +1 -0
- package/schema.json +3 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Report definition → .docx written to sink as its pages are laid out.
|
|
3
|
+
* @param {any} def @param {any} opts render()'s options and exportDocx's (fontStore, fetchImage, figures, rasterize, lang,
|
|
4
|
+
* title), plus timeoutMs or deadline, signal, window (rows laid out at once), maxRows, sorter, sqlRows as exportPdfStream
|
|
5
|
+
* @param {Sink} sink not closed
|
|
6
|
+
* @returns {Promise<StreamResult>}
|
|
7
|
+
*/
|
|
8
|
+
export function exportDocxStream(def: any, opts: any, sink: Sink): Promise<StreamResult>;
|
|
9
|
+
/**
|
|
10
|
+
* Report definition → .xlsx written to sink as its rows come.
|
|
11
|
+
* @param {any} def @param {any} opts render()'s options and exportXlsx's (currency, title, formulas, fontStore,
|
|
12
|
+
* fetchImage), plus timeoutMs or deadline, signal, maxRows, sorter, sqlRows as exportPdfStream
|
|
13
|
+
* @param {Sink} sink not closed
|
|
14
|
+
* @returns {Promise<StreamResult>}
|
|
15
|
+
*/
|
|
16
|
+
export function exportXlsxStream(def: any, opts: any, sink: Sink): Promise<StreamResult>;
|
|
17
|
+
export type Sink = {
|
|
18
|
+
write(u8: Uint8Array): any;
|
|
19
|
+
once?: (ev: string, cb: () => void) => any;
|
|
20
|
+
};
|
|
21
|
+
export type StreamResult = {
|
|
22
|
+
streamed: boolean;
|
|
23
|
+
pages?: number;
|
|
24
|
+
rows?: number;
|
|
25
|
+
warnings: string[];
|
|
26
|
+
why?: string;
|
|
27
|
+
};
|
|
@@ -9,8 +9,10 @@
|
|
|
9
9
|
* tagged?: { lang?: string }, drillBase?: string, onWarning?: (message: string) => void, timeoutMs?: number,
|
|
10
10
|
* creationDate?: Date }} [opt]
|
|
11
11
|
* subset: a HarfBuzz subsetter (see subset.js). Without it, fonts embed in full.
|
|
12
|
-
* pdfa:
|
|
13
|
-
*
|
|
12
|
+
* pdfa: a PDF/A-2b file (2a with tagged): true uses the sRGB profile of @reportwright/fonts, or pass { icc } (this
|
|
13
|
+
* function itself needs icc; the engine package fills it in). prepare: last change to the pdf-lib PDFDocument before
|
|
14
|
+
* saving (the server adds a signature placeholder there). save: pdf-lib save options. These, encrypt and PDF/A without
|
|
15
|
+
* a profile take the whole-model path in exportPdfStream; a PDF/A file with a profile streams.
|
|
14
16
|
* encrypt: { userPassword, ownerPassword, permissions } — AES-256 (see encrypt.js); not with pdfa or prepare.
|
|
15
17
|
* tagged: an accessible PDF (PDF/UA-1, see pdfua.js): structure tree, marked content, artifacts, language, title
|
|
16
18
|
* shown; with pdfa it is PDF/A-2a. Off, the file is exactly what it was.
|
|
@@ -42,4 +44,4 @@ export function exportPdf(model: any, fontStore: import("../engine/text/fonts.js
|
|
|
42
44
|
timeoutMs?: number;
|
|
43
45
|
creationDate?: Date;
|
|
44
46
|
}): any;
|
|
45
|
-
import { PDFDocument } from '
|
|
47
|
+
import { PDFDocument } from '../engine/lazylibs.js';
|
|
@@ -1,14 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* Draw one run of shaped glyphs by ID, where the engine placed them: a TJ array whose numbers move each
|
|
3
|
-
* glyph from where the font's own advance (the W array) leaves it to the shaper's position; marks that sit
|
|
4
|
-
* higher or lower use the text rise. /ActualText gives copy and search the characters: for a left-to-right
|
|
5
|
-
* run the whole run in reading order; a right-to-left run (drawn in visual order, which readers reorder
|
|
6
|
-
* themselves) reads through ToUnicode, glyph by glyph, and only a cluster ToUnicode cannot spell gets a span
|
|
7
|
-
* (`spans`, from glyphText); glyphs that stand for nothing (`texts`: '') go last. A span per joined letter, and
|
|
8
|
-
* the dots of joined letters drawn among the letters, made pdftotext split words ("الج ميل", "الت قن ية").
|
|
9
|
-
* @param {Content} c @param {Set<number>} [spans] @param {Map<number, string>} [texts]
|
|
10
|
-
*/
|
|
11
|
-
export function drawRun(c: Content, run: any, x: any, y: any, size: any, pf: any, color: any, spans?: Set<number>, texts?: Map<number, string>): void;
|
|
1
|
+
export function drawRun(c: any, run: any, x: any, y: any, size: any, pf: any, color: any, spans: any, texts: any): void;
|
|
12
2
|
/**
|
|
13
3
|
* The text each shaped glyph stands for, for the font's ToUnicode map: the character whose own (character-map)
|
|
14
4
|
* glyph it is; the characters of its cluster that have no glyph of their own there (a conjunct, a joined
|
|
@@ -69,6 +59,8 @@ export class Content {
|
|
|
69
59
|
/** straight lines waiting to be drawn after the text around them: { key, stroke, w, dash, segs: [x1, y1, x2, y2][] } */
|
|
70
60
|
lines: any;
|
|
71
61
|
tagged: boolean;
|
|
62
|
+
/** tagged, lines wait all the same and are drawn as one artifact (the streamed PDF's painter sets it) */
|
|
63
|
+
artLines: boolean;
|
|
72
64
|
set s(v: string);
|
|
73
65
|
/**
|
|
74
66
|
* The operators so far. Any other drawing reads or appends to it, so the lines waiting are drawn first: the text
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** The font dictionary's entries (pdf-lib's context.obj takes them as they are: strings become names). @param {any} f a standard font */
|
|
2
|
+
export function standardFontEntries(f: any): {
|
|
3
|
+
FirstChar: number;
|
|
4
|
+
LastChar: number;
|
|
5
|
+
Widths: any;
|
|
6
|
+
Encoding?: string;
|
|
7
|
+
Type: string;
|
|
8
|
+
Subtype: string;
|
|
9
|
+
BaseFont: any;
|
|
10
|
+
};
|
|
11
|
+
/** The same dictionary as PDF syntax. @param {any} f */
|
|
12
|
+
export function standardFontDict(f: any): string;
|
|
13
|
+
/** A literal string's body: one byte per character, escaped. @param {any} f a standard font @param {string} text */
|
|
14
|
+
export function standardLiteral(f: any, text: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* A page whose standard-font text is redrawn in the embedded stand-ins (PDF/A, PDF/UA), at the standard font's glyph
|
|
17
|
+
* positions. The page and the items it changes are copies; families gets the standard families it found.
|
|
18
|
+
* @param {any} pg @param {(key: string) => any} fontOf the loaded fonts by key @param {Set<string>} families
|
|
19
|
+
*/
|
|
20
|
+
export function embeddedPage(pg: any, fontOf: (key: string) => any, families: Set<string>): any;
|
|
21
|
+
/** The warnings for the standard families a PDF/A or PDF/UA file drew in their stand-ins (a family's name is its regular face's key). @param {Set<string>} families */
|
|
22
|
+
export function embeddedWarnings(families: Set<string>): string[];
|
|
23
|
+
export function standIns(store: import("../engine/text/fonts.js").FontStore): string[];
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* @typedef {{ title: string, page: number, top?: number, level?: number }} OutlineEntry
|
|
5
|
-
* page: 1-based; top: the destination's y in PDF space (from the bottom), else the page fits the window.
|
|
2
|
+
* p, or signal's reason as soon as it aborts (p goes on, unwatched).
|
|
3
|
+
* @template T @param {Promise<T>} p @param {AbortSignal} [signal] @returns {Promise<T>}
|
|
6
4
|
*/
|
|
5
|
+
export function raced<T>(p: Promise<T>, signal?: AbortSignal): Promise<T>;
|
|
7
6
|
/**
|
|
8
7
|
* @param {Sink} sink
|
|
9
8
|
* @param {{ fontStore: import('../engine/text/fonts.js').FontStore, fonts?: string[],
|
|
10
9
|
* subset?: (font: Uint8Array, codePoints: Iterable<number>, opt?: { glyphs?: Iterable<number> }) => Promise<Uint8Array>,
|
|
11
|
-
* id?: string }} opt
|
|
10
|
+
* id?: string, signal?: AbortSignal }} opt
|
|
12
11
|
* fonts: font keys to name now (F1, F2… in this order); any other font is named on first use.
|
|
13
12
|
* subset: subset.js's subsetter; without it fonts embed in full. id: the file ID (32 hex digits), else random.
|
|
13
|
+
* signal: stops a wait for the sink (back-pressure) when it aborts.
|
|
14
14
|
*/
|
|
15
15
|
export function createPdfStream(sink: Sink, opt: {
|
|
16
16
|
fontStore: import("../engine/text/fonts.js").FontStore;
|
|
@@ -19,6 +19,7 @@ export function createPdfStream(sink: Sink, opt: {
|
|
|
19
19
|
glyphs?: Iterable<number>;
|
|
20
20
|
}) => Promise<Uint8Array>;
|
|
21
21
|
id?: string;
|
|
22
|
+
signal?: AbortSignal;
|
|
22
23
|
}): {
|
|
23
24
|
/** @param {string} key @returns {string} the font's resource name (F1…) */
|
|
24
25
|
fontName: (key: string) => string;
|
|
@@ -124,8 +125,12 @@ export function createPdfStream(sink: Sink, opt: {
|
|
|
124
125
|
/**
|
|
125
126
|
* A report to PDF bytes written to sink as its pages are laid out (planPaged: a flowing table, one window of rows at a
|
|
126
127
|
* time), else rendered whole and exported by exportPdf, the same file it always was, written to sink in one piece.
|
|
127
|
-
* opts: render()'s options and exportPdf's (fontStore, subset, title, author, creationDate, drillBase…). Tagged
|
|
128
|
-
* PDF/A
|
|
128
|
+
* opts: render()'s options and exportPdf's (fontStore, subset, title, author, creationDate, drillBase…). Tagged
|
|
129
|
+
* (PDF/UA-1) and PDF/A files stream too; encrypted and signed files, save options and PDF/A without a colour profile
|
|
130
|
+
* take the whole-model path (the result's why says which).
|
|
131
|
+
* timeoutMs (or deadline) bounds the whole export, waits for the sink included; signal (an AbortSignal) stops it at its
|
|
132
|
+
* next wait (a row batch, the sink, a sort, a page). Stopped or failed: it rejects (the signal's reason, an AbortError;
|
|
133
|
+
* a timeout: status 504, code 'ETIMEDOUT'), the rows' cursors are closed, a sort's temporary files removed.
|
|
129
134
|
* @param {any} def @param {any} opts @param {Sink} sink
|
|
130
135
|
* @returns {Promise<{ streamed: boolean, pages: number, warnings: string[], why?: string }>}
|
|
131
136
|
*/
|
|
@@ -157,12 +162,13 @@ export function paintPage(pg: any, H: number, env: any): {
|
|
|
157
162
|
};
|
|
158
163
|
/**
|
|
159
164
|
* What paintPage draws with: a writer's resource names and glyph records (w), the fonts, shaped glyphs' texts.
|
|
160
|
-
* @param {any} w @param {any} fontStore @param {{ drillBase?: string, pageRef?: (i: number) => any, tags?: any }} [o]
|
|
165
|
+
* @param {any} w @param {any} fontStore @param {{ drillBase?: string, pageRef?: (i: number) => any, tags?: any, embedAll?: boolean }} [o]
|
|
161
166
|
*/
|
|
162
167
|
export function paintEnv(w: any, fontStore: any, o?: {
|
|
163
168
|
drillBase?: string;
|
|
164
169
|
pageRef?: (i: number) => any;
|
|
165
170
|
tags?: any;
|
|
171
|
+
embedAll?: boolean;
|
|
166
172
|
}): {
|
|
167
173
|
shared: {
|
|
168
174
|
font: (f: any) => any;
|
|
@@ -179,6 +185,8 @@ export function paintEnv(w: any, fontStore: any, o?: {
|
|
|
179
185
|
reserve: () => any;
|
|
180
186
|
drillBase: string;
|
|
181
187
|
tags: any;
|
|
188
|
+
/** PDF/A, PDF/UA: standard fonts drawn in embedded stand-ins; the families that were @type {Set<string>|null} */
|
|
189
|
+
embedded: Set<string> | null;
|
|
182
190
|
};
|
|
183
191
|
/**
|
|
184
192
|
* write may return a promise (awaited: back-pressure), or false with a 'drain' event to wait for (a Node Writable).
|
|
@@ -5,11 +5,18 @@
|
|
|
5
5
|
* ColSpan), Link > OBJR inside the element whose text it covers; page header and footer, borders and boxes artifacts.
|
|
6
6
|
* Each page's rows (TR, TD), its parent-tree array and its links' elements are written when the page ends; what stays
|
|
7
7
|
* is one number per row (the Table's kids) and two per page and link (the parent tree), written at the end.
|
|
8
|
+
* A cell's element is a few dozen bytes in an object stream (no /Type, which is optional; no /A on a plain TD): a
|
|
9
|
+
* million-row table has some 8 million of them, the most of the file's objects.
|
|
8
10
|
*/
|
|
9
11
|
/**
|
|
10
12
|
* @param {any} w the PDF writer (pdfstream.js createPdfStream)
|
|
13
|
+
* @param {{ maxElements?: number }} [o] maxElements: past it the export stops (413)
|
|
11
14
|
*/
|
|
12
|
-
export function createStreamTagger(w: any
|
|
15
|
+
export function createStreamTagger(w: any, { maxElements }?: {
|
|
16
|
+
maxElements?: number;
|
|
17
|
+
}): {
|
|
18
|
+
/** structure elements so far */
|
|
19
|
+
readonly count: number;
|
|
13
20
|
/** a new page (window: the paged window it came from; row ids are its own) @param {number} window */
|
|
14
21
|
page(window: number): void;
|
|
15
22
|
/**
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** At the server's start: remove the spill folders of processes that are gone (pw-spill-<pid>-…) and old-style ones. */
|
|
2
|
+
export function sweepAtBoot(root?: any): void;
|
|
3
|
+
export function spillSorter({ run, runBytes, frame, maxMB, totalMB, dir: root, staleMs }?: {
|
|
4
|
+
run?: number;
|
|
5
|
+
runBytes?: number;
|
|
6
|
+
frame?: number;
|
|
7
|
+
maxMB?: number;
|
|
8
|
+
totalMB?: number;
|
|
9
|
+
dir?: any;
|
|
10
|
+
staleMs?: number;
|
|
11
|
+
}): (cmp: (a: any, b: any) => number) => {
|
|
12
|
+
/** @param {any} r */
|
|
13
|
+
push(r: any): Promise<void>;
|
|
14
|
+
drain(): AsyncGenerator<any, void, unknown>;
|
|
15
|
+
close(): Promise<void>;
|
|
16
|
+
/** Tests: the runs written so far. */
|
|
17
|
+
readonly runs: number;
|
|
18
|
+
};
|
|
19
|
+
export function canSpill(): boolean;
|
|
20
|
+
export function spillShared(): any;
|
|
@@ -1,5 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The tables of a single-face sfnt (TrueType or CFF) as a Map of tag to bytes. A collection (ttcf) gives an empty map.
|
|
3
|
+
* @param {Uint8Array} bytes
|
|
4
|
+
*/
|
|
5
|
+
export function sfntTables(bytes: Uint8Array): Map<any, any>;
|
|
6
|
+
/** A sfnt from its tables: directory, 4-byte padding, table checksums and the head checkSumAdjustment. */
|
|
7
|
+
export function buildSfnt(version: any, tables: any): Uint8Array<ArrayBuffer>;
|
|
8
|
+
/**
|
|
9
|
+
* The name table with the given strings replaced (nameID to text). Each replaced string is written in its record's own
|
|
10
|
+
* encoding: UTF-16BE for Windows and Unicode, one byte per character for Macintosh.
|
|
11
|
+
* @param {Uint8Array} name
|
|
12
|
+
* @param {Map<number, string>} strings
|
|
13
|
+
*/
|
|
14
|
+
export function setNameStrings(name: Uint8Array, strings: Map<number, string>): Uint8Array<ArrayBuffer>;
|
|
1
15
|
/** @param {() => Promise<ArrayBuffer|Uint8Array>} loadWasm */
|
|
2
16
|
export function createSubsetter(loadWasm: () => Promise<ArrayBuffer | Uint8Array>): (font: Uint8Array, codePoints: Iterable<number>, opt?: {
|
|
3
17
|
glyphs?: Iterable<number>;
|
|
4
18
|
layout?: boolean;
|
|
19
|
+
weight?: number;
|
|
5
20
|
}) => Promise<Uint8Array>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {{ name: string, title: string, columns: number[], timeZone: string|null, locale: string|null, currency: string|null, rows: () => AsyncGenerator<any> }} plan
|
|
3
|
+
* @param {(bytes: Uint8Array) => any} put the zip's bytes as they come (awaited: back-pressure)
|
|
4
|
+
* @param {{ currency?: string, title?: string, formulas?: boolean, maxRows?: number, timeZone?: string }} [opt]
|
|
5
|
+
*/
|
|
6
|
+
export function writeXlsxStream(plan: {
|
|
7
|
+
name: string;
|
|
8
|
+
title: string;
|
|
9
|
+
columns: number[];
|
|
10
|
+
timeZone: string | null;
|
|
11
|
+
locale: string | null;
|
|
12
|
+
currency: string | null;
|
|
13
|
+
rows: () => AsyncGenerator<any>;
|
|
14
|
+
}, put: (bytes: Uint8Array) => any, opt?: {
|
|
15
|
+
currency?: string;
|
|
16
|
+
title?: string;
|
|
17
|
+
formulas?: boolean;
|
|
18
|
+
maxRows?: number;
|
|
19
|
+
timeZone?: string;
|
|
20
|
+
}): Promise<void>;
|
|
21
|
+
export const EXCEL_ROWS: 1048576;
|
|
22
|
+
export const EXCEL_COLS: 16384;
|
package/examples/stream-1m.mjs
CHANGED
|
@@ -4,13 +4,15 @@
|
|
|
4
4
|
// cursor), so nothing holds them all.
|
|
5
5
|
//
|
|
6
6
|
// npm i @reportwright/engine @reportwright/fonts
|
|
7
|
-
// node node_modules/@reportwright/engine/examples/stream-1m.mjs [rows=1000000] [out=ledger.pdf] [--plain] [--grouped] [--tagged] [--parallel=
|
|
7
|
+
// node node_modules/@reportwright/engine/examples/stream-1m.mjs [rows=1000000] [out=ledger.pdf] [--plain] [--grouped] [--presorted] [--tagged] [--array[=text]] [--parallel=N]
|
|
8
8
|
//
|
|
9
9
|
// Prints one JSON line: { rows, pages, streamed, peakRssMB, ms, bytes, ... }. "Page N of M" is in the page footer
|
|
10
10
|
// (the rows are read twice: once to count the pages); --plain leaves M out (one pass). --grouped adds two group levels
|
|
11
|
-
// with subtotals
|
|
12
|
-
//
|
|
13
|
-
//
|
|
11
|
+
// with subtotals (sorted through a disk spill; --presorted: the rows come in group order and are only checked); --tagged
|
|
12
|
+
// makes an accessible PDF/A (PDF/UA-1 + PDF/A-2a); --array: the rows as one array in the definition (--array=text: as
|
|
13
|
+
// JSON text); --parallel=N lays out and paints with N worker threads (serial by default: each thread costs 150-300 MB).
|
|
14
|
+
// RW_ENGINE: import the engine from another path (a checkout: packages/engine/entry.js); RW_PUBLIC: a folder with fonts/
|
|
15
|
+
// and harfbuzz-subset.wasm instead of @reportwright/fonts.
|
|
14
16
|
import fs from 'node:fs';
|
|
15
17
|
import path from 'node:path';
|
|
16
18
|
import { pathToFileURL } from 'node:url';
|
|
@@ -33,13 +35,16 @@ if (process.env.RW_PUBLIC) {
|
|
|
33
35
|
icc = fs.readFileSync(path.join(dir, 'icc', 'sRGB-v2-magic.icc'));
|
|
34
36
|
}
|
|
35
37
|
|
|
38
|
+
const presorted = flag('presorted');
|
|
36
39
|
const REGIONS = ['North', 'South', 'East', 'West'], TYPES = ['Deposit', 'Withdrawal', 'Transfer', 'Fee', 'Interest'];
|
|
37
40
|
/** the rows, a thousand at a time, made as they are asked for */
|
|
38
41
|
async function* rows() {
|
|
39
42
|
for (let i = 0; i < N; i += 1000) {
|
|
40
43
|
const batch = [];
|
|
41
44
|
for (let j = i; j < Math.min(N, i + 1000); j++) {
|
|
42
|
-
|
|
45
|
+
// --presorted: the rows come in group order (as a query ordered by region, type gives them)
|
|
46
|
+
const region = presorted ? REGIONS[Math.floor(j * 4 / N)] : REGIONS[(j >> 9) % 4], type = presorted ? TYPES[Math.floor(j * 20 / N) % 5] : TYPES[(j >> 6) % 5];
|
|
47
|
+
batch.push({ id: j + 1, account: `AC${String(10000 + (j * 7) % 9000)}`, region, type,
|
|
43
48
|
date: new Date(Date.UTC(2025, j % 12, 1 + (j % 28))), amount: Math.round(((j * 7919) % 200000 - 100000) * 1.37) / 100,
|
|
44
49
|
reference: j % 37 === 0 ? `Reversal of an earlier transfer between linked accounts, batch ${j}` : `REF-${j * 31}` });
|
|
45
50
|
}
|
|
@@ -78,10 +83,18 @@ const base = peak;
|
|
|
78
83
|
const timer = setInterval(rss, 20);
|
|
79
84
|
const t0 = Date.now();
|
|
80
85
|
const out = fs.createWriteStream(file);
|
|
81
|
-
|
|
86
|
+
// --array: the rows made first, one array in the report's JSON source (how a library caller often has them)
|
|
87
|
+
let arrayRssMB;
|
|
88
|
+
if (flag('array') || opt('array')) {
|
|
89
|
+
const all = [];
|
|
90
|
+
for await (const b of rows()) for (const x of b) all.push(x);
|
|
91
|
+
def.dataSources = [{ name: 'db', type: 'json', data: opt('array') === 'text' ? JSON.stringify(all) : all }];
|
|
92
|
+
rss(); arrayRssMB = Math.round(process.memoryUsage.rss() / 1048576);
|
|
93
|
+
}
|
|
94
|
+
const r = await exportPdfStream(def, { fonts, subset, title: 'Ledger', window: Number(opt('window')) || undefined, presorted, ...(flag('memsort') ? { spill: false } : {}), sqlRows: () => rows(), maxRows: Math.max(N, 5_000_000), timeoutMs: 24 * 3600e3,
|
|
82
95
|
...(flag('tagged') ? { tagged: { lang: 'en-IN' }, pdfa: icc ? { icc } : true } : {}), ...(opt('parallel') ? { parallel: Number(opt('parallel')) } : {}) }, out);
|
|
83
96
|
await new Promise((ok, fail) => out.end((e) => (e ? fail(e) : ok())));
|
|
84
97
|
clearInterval(timer);
|
|
85
98
|
rss();
|
|
86
|
-
console.log(JSON.stringify({ rows: N, pages: r.pages, streamed: r.streamed, ...(r.why ? { why: r.why } : {}), peakRssMB: Math.round(peak), startRssMB: Math.round(base), ms: Date.now() - t0,
|
|
87
|
-
bytes: fs.statSync(file).size, file, node: process.version, grouped, tagged: flag('tagged'), parallel: Number(opt('parallel')) || 1 }));
|
|
99
|
+
console.log(JSON.stringify({ rows: N, pages: r.pages, streamed: r.streamed, ...(r.why ? { why: r.why } : {}), peakRssMB: Math.round(peak), startRssMB: Math.round(base), ...(arrayRssMB ? { arrayRssMB } : {}), ms: Date.now() - t0,
|
|
100
|
+
bytes: fs.statSync(file).size, file, node: process.version, grouped, presorted, tagged: flag('tagged'), parallel: Number(opt('parallel')) || 1 }));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reportwright/engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -57,7 +57,8 @@
|
|
|
57
57
|
"schema.json",
|
|
58
58
|
"README.md",
|
|
59
59
|
"CHANGELOG.md",
|
|
60
|
-
"LICENSE"
|
|
60
|
+
"LICENSE",
|
|
61
|
+
"THIRD-PARTY-NOTICES.md"
|
|
61
62
|
],
|
|
62
63
|
"engines": {
|
|
63
64
|
"node": ">=20.9"
|
|
@@ -66,12 +67,13 @@
|
|
|
66
67
|
"dependencies": {
|
|
67
68
|
"pdf-lib": "1.17.1",
|
|
68
69
|
"@pdf-lib/fontkit": "1.1.1",
|
|
70
|
+
"@pdf-lib/standard-fonts": "1.0.0",
|
|
69
71
|
"bwip-js": "4.11.4",
|
|
70
72
|
"fflate": "0.8.3",
|
|
71
73
|
"bidi-js": "1.0.3"
|
|
72
74
|
},
|
|
73
75
|
"peerDependencies": {
|
|
74
|
-
"@reportwright/fonts": "0.
|
|
76
|
+
"@reportwright/fonts": "0.13.0"
|
|
75
77
|
},
|
|
76
78
|
"peerDependenciesMeta": {
|
|
77
79
|
"@reportwright/fonts": {
|
package/pool/worker.js
CHANGED
|
@@ -10,7 +10,7 @@ const EXPORT = {
|
|
|
10
10
|
xlsx: (m, o) => exportXlsx(m, { fonts, ...o }),
|
|
11
11
|
docx: (m, o) => exportDocx(m, { fonts, ...o }),
|
|
12
12
|
pptx: (m, o) => exportPptx(m, { fonts, ...o }),
|
|
13
|
-
html: async (m, o) => new TextEncoder().encode(await exportHtml(m,
|
|
13
|
+
html: async (m, o) => new TextEncoder().encode(await exportHtml(m, { ...o, fonts })),
|
|
14
14
|
csv: async (m, o) => new TextEncoder().encode(exportCsv(m, o)),
|
|
15
15
|
};
|
|
16
16
|
/** @type {import('node:worker_threads').MessagePort} */ (parentPort).on('message', async ({ def, opts }) => {
|
package/report.d.ts
CHANGED