@aibrains/pdf-renderer 0.9.0 → 0.10.1

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.
@@ -8,7 +8,10 @@
8
8
  * Both are sourced from @fontsource/* at build time and copied to ./fonts/ at the
9
9
  * package root (see scripts/copy-fonts.js). At runtime, paths resolve identically
10
10
  * from `src/core/fonts.ts` and `dist/core/fonts.js` because both live two
11
- * directories below the package root (../../fonts/).
11
+ * directories below the package root (../../fonts/). A consumer that bundles
12
+ * this module into a single file (esbuild for AWS Lambda) loses that layout:
13
+ * `__dirname` is then the bundle's own directory. Such a consumer ships the
14
+ * `fonts/` directory beside its bundle and names it in `PDF_FONT_DIR`.
12
15
  *
13
16
  * Devanagari rendering uses Yoga + Fontkit + Harfbuzz inside @react-pdf/renderer v4
14
17
  * to handle complex script shaping (conjuncts, vowel marks). This is the canary for
@@ -23,6 +26,9 @@
23
26
  * pick them up via the relative path. URL-based registration for CDN deployments
24
27
  * is a Sprint C.2 concern.
25
28
  */
29
+ /** Environment variable naming the font directory when the package-relative default cannot apply. */
30
+ export declare const FONT_DIR_ENV = "PDF_FONT_DIR";
31
+ export declare function resolveFontDir(env?: NodeJS.ProcessEnv): string;
26
32
  /** Latin font family registered by `registerFonts()`. */
27
33
  export declare const FONT_FAMILY_LATIN: "Noto Sans";
28
34
  /** Devanagari (Nepali) font family registered by `registerFonts()`. */
@@ -1 +1 @@
1
- {"version":3,"file":"fonts.d.ts","sourceRoot":"","sources":["../../src/core/fonts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAQH,yDAAyD;AACzD,eAAO,MAAM,iBAAiB,EAAG,WAAoB,CAAC;AACtD,uEAAuE;AACvE,eAAO,MAAM,sBAAsB,EAAG,sBAA+B,CAAC;AAStE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GACvC,OAAO,iBAAiB,GAAG,OAAO,sBAAsB,CAI1D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC;AAI1C;;;;;;;GAOG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAoCpC;AAED,wFAAwF;AACxF,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}
1
+ {"version":3,"file":"fonts.d.ts","sourceRoot":"","sources":["../../src/core/fonts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAOH,qGAAqG;AACrG,eAAO,MAAM,YAAY,iBAAiB,CAAC;AAE3C,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAG3E;AAED,yDAAyD;AACzD,eAAO,MAAM,iBAAiB,EAAG,WAAoB,CAAC;AACtD,uEAAuE;AACvE,eAAO,MAAM,sBAAsB,EAAG,sBAA+B,CAAC;AAStE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GACvC,OAAO,iBAAiB,GAAG,OAAO,sBAAsB,CAI1D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC;AAI1C;;;;;;;GAOG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAqCpC;AAED,wFAAwF;AACxF,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}
@@ -9,7 +9,10 @@
9
9
  * Both are sourced from @fontsource/* at build time and copied to ./fonts/ at the
10
10
  * package root (see scripts/copy-fonts.js). At runtime, paths resolve identically
11
11
  * from `src/core/fonts.ts` and `dist/core/fonts.js` because both live two
12
- * directories below the package root (../../fonts/).
12
+ * directories below the package root (../../fonts/). A consumer that bundles
13
+ * this module into a single file (esbuild for AWS Lambda) loses that layout:
14
+ * `__dirname` is then the bundle's own directory. Such a consumer ships the
15
+ * `fonts/` directory beside its bundle and names it in `PDF_FONT_DIR`.
13
16
  *
14
17
  * Devanagari rendering uses Yoga + Fontkit + Harfbuzz inside @react-pdf/renderer v4
15
18
  * to handle complex script shaping (conjuncts, vowel marks). This is the canary for
@@ -58,14 +61,21 @@ var __importStar = (this && this.__importStar) || (function () {
58
61
  };
59
62
  })();
60
63
  Object.defineProperty(exports, "__esModule", { value: true });
61
- exports.FONT_FAMILY_DEVANAGARI = exports.FONT_FAMILY_LATIN = void 0;
64
+ exports.FONT_FAMILY_DEVANAGARI = exports.FONT_FAMILY_LATIN = exports.FONT_DIR_ENV = void 0;
65
+ exports.resolveFontDir = resolveFontDir;
62
66
  exports.pickFontFamily = pickFontFamily;
63
67
  exports.registerFonts = registerFonts;
64
68
  exports._resetFontsForTest = _resetFontsForTest;
65
69
  const path = __importStar(require("node:path"));
66
70
  const renderer_1 = require("@react-pdf/renderer");
67
71
  const PACKAGE_ROOT = path.resolve(__dirname, '..', '..');
68
- const FONT_DIR = path.join(PACKAGE_ROOT, 'fonts');
72
+ /** Environment variable naming the font directory when the package-relative default cannot apply. */
73
+ exports.FONT_DIR_ENV = 'PDF_FONT_DIR';
74
+ function resolveFontDir(env = process.env) {
75
+ var _a;
76
+ const override = (_a = env[exports.FONT_DIR_ENV]) === null || _a === void 0 ? void 0 : _a.trim();
77
+ return override ? path.resolve(override) : path.join(PACKAGE_ROOT, 'fonts');
78
+ }
69
79
  /** Latin font family registered by `registerFonts()`. */
70
80
  exports.FONT_FAMILY_LATIN = 'Noto Sans';
71
81
  /** Devanagari (Nepali) font family registered by `registerFonts()`. */
@@ -120,6 +130,7 @@ let registered = false;
120
130
  function registerFonts() {
121
131
  if (registered)
122
132
  return;
133
+ const FONT_DIR = resolveFontDir();
123
134
  // @react-pdf/renderer uses NUMERIC fontWeight internally (400 for normal,
124
135
  // 700 for bold). Passing the string 'normal'/'bold' to Font.register stores
125
136
  // them as strings but the resolver looks up numerics, so the registration
@@ -1 +1 @@
1
- {"version":3,"file":"fonts.js","sourceRoot":"","sources":["../../src/core/fonts.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8CH,wCAMC;AAgCD,sCAoCC;AAGD,gDAEC;AA3HD,gDAAkC;AAClC,kDAA2C;AAE3C,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACzD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;AAElD,yDAAyD;AAC5C,QAAA,iBAAiB,GAAG,WAAoB,CAAC;AACtD,uEAAuE;AAC1D,QAAA,sBAAsB,GAAG,sBAA+B,CAAC;AAEtE,+EAA+E;AAC/E,uEAAuE;AACvE,0EAA0E;AAC1E,6EAA6E;AAC7E,wDAAwD;AACxD,MAAM,gBAAgB,GAAG,OAAO,CAAC;AAEjC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,SAAgB,cAAc,CAC5B,IAAwC;IAExC,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,EAAE;QAAE,OAAO,yBAAiB,CAAC;IACjF,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IACzB,OAAO,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,8BAAsB,CAAC,CAAC,CAAC,yBAAiB,CAAC;AACjF,CAAC;AAsBD,IAAI,UAAU,GAAG,KAAK,CAAC;AAEvB;;;;;;;GAOG;AACH,SAAgB,aAAa;IAC3B,IAAI,UAAU;QAAE,OAAO;IAEvB,0EAA0E;IAC1E,4EAA4E;IAC5E,0EAA0E;IAC1E,8EAA8E;IAC9E,eAAI,CAAC,QAAQ,CAAC;QACZ,MAAM,EAAE,yBAAiB;QACzB,KAAK,EAAE;YACL;gBACE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,uBAAuB,CAAC;gBACjD,UAAU,EAAE,GAAG;aAChB;YACD;gBACE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,oBAAoB,CAAC;gBAC9C,UAAU,EAAE,GAAG;aAChB;SACF;KACF,CAAC,CAAC;IAEH,eAAI,CAAC,QAAQ,CAAC;QACZ,MAAM,EAAE,8BAAsB;QAC9B,KAAK,EAAE;YACL;gBACE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,iCAAiC,CAAC;gBAC3D,UAAU,EAAE,GAAG;aAChB;YACD;gBACE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,8BAA8B,CAAC;gBACxD,UAAU,EAAE,GAAG;aAChB;SACF;KACF,CAAC,CAAC;IAEH,UAAU,GAAG,IAAI,CAAC;AACpB,CAAC;AAED,wFAAwF;AACxF,SAAgB,kBAAkB;IAChC,UAAU,GAAG,KAAK,CAAC;AACrB,CAAC"}
1
+ {"version":3,"file":"fonts.js","sourceRoot":"","sources":["../../src/core/fonts.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUH,wCAGC;AAwCD,wCAMC;AAgCD,sCAqCC;AAGD,gDAEC;AAnID,gDAAkC;AAClC,kDAA2C;AAE3C,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAEzD,qGAAqG;AACxF,QAAA,YAAY,GAAG,cAAc,CAAC;AAE3C,SAAgB,cAAc,CAAC,MAAyB,OAAO,CAAC,GAAG;;IACjE,MAAM,QAAQ,GAAG,MAAA,GAAG,CAAC,oBAAY,CAAC,0CAAE,IAAI,EAAE,CAAC;IAC3C,OAAO,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;AAC9E,CAAC;AAED,yDAAyD;AAC5C,QAAA,iBAAiB,GAAG,WAAoB,CAAC;AACtD,uEAAuE;AAC1D,QAAA,sBAAsB,GAAG,sBAA+B,CAAC;AAEtE,+EAA+E;AAC/E,uEAAuE;AACvE,0EAA0E;AAC1E,6EAA6E;AAC7E,wDAAwD;AACxD,MAAM,gBAAgB,GAAG,OAAO,CAAC;AAEjC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,SAAgB,cAAc,CAC5B,IAAwC;IAExC,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,EAAE;QAAE,OAAO,yBAAiB,CAAC;IACjF,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IACzB,OAAO,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,8BAAsB,CAAC,CAAC,CAAC,yBAAiB,CAAC;AACjF,CAAC;AAsBD,IAAI,UAAU,GAAG,KAAK,CAAC;AAEvB;;;;;;;GAOG;AACH,SAAgB,aAAa;IAC3B,IAAI,UAAU;QAAE,OAAO;IACvB,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAC;IAElC,0EAA0E;IAC1E,4EAA4E;IAC5E,0EAA0E;IAC1E,8EAA8E;IAC9E,eAAI,CAAC,QAAQ,CAAC;QACZ,MAAM,EAAE,yBAAiB;QACzB,KAAK,EAAE;YACL;gBACE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,uBAAuB,CAAC;gBACjD,UAAU,EAAE,GAAG;aAChB;YACD;gBACE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,oBAAoB,CAAC;gBAC9C,UAAU,EAAE,GAAG;aAChB;SACF;KACF,CAAC,CAAC;IAEH,eAAI,CAAC,QAAQ,CAAC;QACZ,MAAM,EAAE,8BAAsB;QAC9B,KAAK,EAAE;YACL;gBACE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,iCAAiC,CAAC;gBAC3D,UAAU,EAAE,GAAG;aAChB;YACD;gBACE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,8BAA8B,CAAC;gBACxD,UAAU,EAAE,GAAG;aAChB;SACF;KACF,CAAC,CAAC;IAEH,UAAU,GAAG,IAAI,CAAC;AACpB,CAAC;AAED,wFAAwF;AACxF,SAAgB,kBAAkB;IAChC,UAAU,GAAG,KAAK,CAAC;AACrB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -29,4 +29,6 @@ import './descriptors/receipt';
29
29
  export { ReceiptPdf } from './documents/ReceiptPdf';
30
30
  export type { ReceiptTemplateConfig, ReceiptDocumentData } from './documents/ReceiptPdf';
31
31
  export { receiptDescriptor } from './descriptors/receipt';
32
+ export { mergePdfBuffers } from './merge-pdfs';
33
+ export type { MergePdfBuffersOptions } from './merge-pdfs';
32
34
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,eAAO,MAAM,4BAA4B,UAAU,CAAC;AAGpD,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAM9B,OAAO,uBAAuB,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,YAAY,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AACzF,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAM1D,OAAO,uBAAuB,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,YAAY,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AACzF,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,eAAO,MAAM,4BAA4B,UAAU,CAAC;AAGpD,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAM9B,OAAO,uBAAuB,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,YAAY,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AACzF,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAM1D,OAAO,uBAAuB,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,YAAY,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AACzF,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAM1D,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,YAAY,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC"}
package/dist/index.js CHANGED
@@ -32,7 +32,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
32
32
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
33
33
  };
34
34
  Object.defineProperty(exports, "__esModule", { value: true });
35
- exports.receiptDescriptor = exports.ReceiptPdf = exports.invoiceDescriptor = exports.InvoicePdf = exports.PDF_RENDERER_PACKAGE_VERSION = void 0;
35
+ exports.mergePdfBuffers = exports.receiptDescriptor = exports.ReceiptPdf = exports.invoiceDescriptor = exports.InvoicePdf = exports.PDF_RENDERER_PACKAGE_VERSION = void 0;
36
36
  exports.PDF_RENDERER_PACKAGE_VERSION = '0.6.0';
37
37
  // Core + primitives + components + descriptor registry from Sprint C.0.
38
38
  __exportStar(require("./core"), exports);
@@ -57,4 +57,10 @@ var ReceiptPdf_1 = require("./documents/ReceiptPdf");
57
57
  Object.defineProperty(exports, "ReceiptPdf", { enumerable: true, get: function () { return ReceiptPdf_1.ReceiptPdf; } });
58
58
  var receipt_1 = require("./descriptors/receipt");
59
59
  Object.defineProperty(exports, "receiptDescriptor", { enumerable: true, get: function () { return receipt_1.receiptDescriptor; } });
60
+ // Sprint H.1 — pdf-lib-based helper for concatenating rendered PDF buffers
61
+ // into a single merged output. Consumed by the finance bulk-invoice-pdf-export
62
+ // and bulk-receipt-pdf-export workers when the operator picks
63
+ // `outputFormat: 'merged_pdf'`.
64
+ var merge_pdfs_1 = require("./merge-pdfs");
65
+ Object.defineProperty(exports, "mergePdfBuffers", { enumerable: true, get: function () { return merge_pdfs_1.mergePdfBuffers; } });
60
66
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;GAiBG;;;;;;;;;;;;;;;;;AAEU,QAAA,4BAA4B,GAAG,OAAO,CAAC;AAEpD,wEAAwE;AACxE,yCAAuB;AACvB,+CAA6B;AAC7B,+CAA6B;AAC7B,gDAA8B;AAE9B,2EAA2E;AAC3E,0EAA0E;AAC1E,qEAAqE;AACrE,mDAAmD;AACnD,iCAA+B;AAC/B,qDAAoD;AAA3C,wGAAA,UAAU,OAAA;AAEnB,iDAA0D;AAAjD,4GAAA,iBAAiB,OAAA;AAE1B,0EAA0E;AAC1E,0EAA0E;AAC1E,yEAAyE;AACzE,yEAAyE;AACzE,iCAA+B;AAC/B,qDAAoD;AAA3C,wGAAA,UAAU,OAAA;AAEnB,iDAA0D;AAAjD,4GAAA,iBAAiB,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;GAiBG;;;;;;;;;;;;;;;;;AAEU,QAAA,4BAA4B,GAAG,OAAO,CAAC;AAEpD,wEAAwE;AACxE,yCAAuB;AACvB,+CAA6B;AAC7B,+CAA6B;AAC7B,gDAA8B;AAE9B,2EAA2E;AAC3E,0EAA0E;AAC1E,qEAAqE;AACrE,mDAAmD;AACnD,iCAA+B;AAC/B,qDAAoD;AAA3C,wGAAA,UAAU,OAAA;AAEnB,iDAA0D;AAAjD,4GAAA,iBAAiB,OAAA;AAE1B,0EAA0E;AAC1E,0EAA0E;AAC1E,yEAAyE;AACzE,yEAAyE;AACzE,iCAA+B;AAC/B,qDAAoD;AAA3C,wGAAA,UAAU,OAAA;AAEnB,iDAA0D;AAAjD,4GAAA,iBAAiB,OAAA;AAE1B,2EAA2E;AAC3E,+EAA+E;AAC/E,8DAA8D;AAC9D,gCAAgC;AAChC,2CAA+C;AAAtC,6GAAA,eAAe,OAAA"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * mergePdfBuffers — Sprint H.1
3
+ *
4
+ * Concatenate multiple PDF buffers into a single merged PDF, preserving the
5
+ * page order of the input list. The output PDF's pages appear in the same
6
+ * order as the input buffers; each source PDF's pages appear in the same
7
+ * order they were in the source.
8
+ *
9
+ * First step of the merged-PDF output variant for the bulk finance export
10
+ * (Sprint H). The bulk-invoice-pdf-export and bulk-receipt-pdf-export
11
+ * workers call this helper after rendering the individual PDFs when the
12
+ * operator picks `outputFormat: 'merged_pdf'` (see Sprint H.3 for the
13
+ * worker wiring).
14
+ *
15
+ * Determinism:
16
+ * pdf-lib's `save()` does NOT auto-refresh ModDate — the only source of
17
+ * run-to-run drift is what we set on the document ourselves (CreationDate,
18
+ * ModificationDate, Producer, Creator). This function fixes all four to
19
+ * known values so identical input yields identical output — required for
20
+ * the audit-trail invariant in the worker (a re-run of the same job MUST
21
+ * produce byte-identical artifacts so a downstream signature/hash gate is
22
+ * stable). `useObjectStreams: false` on save is a secondary belt-and-
23
+ * -braces for the same guarantee (see save() call for the rationale).
24
+ *
25
+ * Memory profile:
26
+ * Peak RSS ≈ Σ(input bytes) + Σ(merged bytes). pdf-lib holds every
27
+ * parsed source document + the merged output in memory at once. At the
28
+ * Sprint H cap of 1000 documents and typical ~20 kB per invoice PDF,
29
+ * that's ~20 MB peak — well within the finance ECS task's 2 GB budget.
30
+ * For the 100-invoice pilot case, peak is ~2 MB.
31
+ */
32
+ export interface MergePdfBuffersOptions {
33
+ /**
34
+ * The PDF `/Title` metadata field written into the merged output.
35
+ * Optional; when omitted, no title is set. Useful for operator-facing
36
+ * artifacts that show up in the browser's tab title.
37
+ */
38
+ title?: string;
39
+ }
40
+ /**
41
+ * Merge PDF byte buffers into a single output buffer.
42
+ *
43
+ * @param buffers - Non-empty list of PDF byte buffers to concatenate.
44
+ * @param options - Optional metadata overrides.
45
+ * @returns The merged PDF as a Node Buffer.
46
+ * @throws When `buffers` is empty.
47
+ */
48
+ export declare function mergePdfBuffers(buffers: Buffer[], options?: MergePdfBuffersOptions): Promise<Buffer>;
49
+ //# sourceMappingURL=merge-pdfs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-pdfs.d.ts","sourceRoot":"","sources":["../src/merge-pdfs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAIH,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAID;;;;;;;GAOG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,MAAM,CAAC,CAwCjB"}
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ /**
3
+ * mergePdfBuffers — Sprint H.1
4
+ *
5
+ * Concatenate multiple PDF buffers into a single merged PDF, preserving the
6
+ * page order of the input list. The output PDF's pages appear in the same
7
+ * order as the input buffers; each source PDF's pages appear in the same
8
+ * order they were in the source.
9
+ *
10
+ * First step of the merged-PDF output variant for the bulk finance export
11
+ * (Sprint H). The bulk-invoice-pdf-export and bulk-receipt-pdf-export
12
+ * workers call this helper after rendering the individual PDFs when the
13
+ * operator picks `outputFormat: 'merged_pdf'` (see Sprint H.3 for the
14
+ * worker wiring).
15
+ *
16
+ * Determinism:
17
+ * pdf-lib's `save()` does NOT auto-refresh ModDate — the only source of
18
+ * run-to-run drift is what we set on the document ourselves (CreationDate,
19
+ * ModificationDate, Producer, Creator). This function fixes all four to
20
+ * known values so identical input yields identical output — required for
21
+ * the audit-trail invariant in the worker (a re-run of the same job MUST
22
+ * produce byte-identical artifacts so a downstream signature/hash gate is
23
+ * stable). `useObjectStreams: false` on save is a secondary belt-and-
24
+ * -braces for the same guarantee (see save() call for the rationale).
25
+ *
26
+ * Memory profile:
27
+ * Peak RSS ≈ Σ(input bytes) + Σ(merged bytes). pdf-lib holds every
28
+ * parsed source document + the merged output in memory at once. At the
29
+ * Sprint H cap of 1000 documents and typical ~20 kB per invoice PDF,
30
+ * that's ~20 MB peak — well within the finance ECS task's 2 GB budget.
31
+ * For the 100-invoice pilot case, peak is ~2 MB.
32
+ */
33
+ Object.defineProperty(exports, "__esModule", { value: true });
34
+ exports.mergePdfBuffers = mergePdfBuffers;
35
+ const pdf_lib_1 = require("pdf-lib");
36
+ const EPOCH = new Date(0);
37
+ /**
38
+ * Merge PDF byte buffers into a single output buffer.
39
+ *
40
+ * @param buffers - Non-empty list of PDF byte buffers to concatenate.
41
+ * @param options - Optional metadata overrides.
42
+ * @returns The merged PDF as a Node Buffer.
43
+ * @throws When `buffers` is empty.
44
+ */
45
+ async function mergePdfBuffers(buffers, options = {}) {
46
+ if (buffers.length === 0) {
47
+ throw new Error('mergePdfBuffers: refusing to merge an empty buffer list');
48
+ }
49
+ const merged = await pdf_lib_1.PDFDocument.create();
50
+ for (const buf of buffers) {
51
+ // Trusted-input fast path: sources come from our own worker in the same
52
+ // process, so we can skip pdf-lib's default object-graph validation.
53
+ // ParseSpeeds.Fastest tells pdf-lib to defer optional integrity checks.
54
+ const src = await pdf_lib_1.PDFDocument.load(buf, {
55
+ parseSpeed: pdf_lib_1.ParseSpeeds.Fastest,
56
+ });
57
+ const pages = await merged.copyPages(src, src.getPageIndices());
58
+ for (const page of pages) {
59
+ merged.addPage(page);
60
+ }
61
+ }
62
+ // Byte-determinism: pdf-lib's save() does NOT auto-refresh ModDate — the
63
+ // only source of run-to-run drift is the values we set here. Fixing them
64
+ // to a known epoch is what makes identical input produce identical output.
65
+ merged.setCreationDate(EPOCH);
66
+ merged.setModificationDate(EPOCH);
67
+ merged.setProducer('@aibrains/pdf-renderer mergePdfBuffers');
68
+ merged.setCreator('@aibrains/pdf-renderer');
69
+ if (options.title !== undefined) {
70
+ merged.setTitle(options.title);
71
+ }
72
+ const bytes = await merged.save({
73
+ // useObjectStreams: false emits the classic xref table format instead of
74
+ // xref streams. Slightly larger output, but byte-stable across pdf-lib
75
+ // minor upgrades that might change stream-compression heuristics — worth
76
+ // the size trade for the audit-hash guarantee.
77
+ useObjectStreams: false,
78
+ });
79
+ return Buffer.from(bytes);
80
+ }
81
+ //# sourceMappingURL=merge-pdfs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-pdfs.js","sourceRoot":"","sources":["../src/merge-pdfs.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;;AAuBH,0CA2CC;AAhED,qCAAmD;AAWnD,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;AAE1B;;;;;;;GAOG;AACI,KAAK,UAAU,eAAe,CACnC,OAAiB,EACjB,UAAkC,EAAE;IAEpC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC7E,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,qBAAW,CAAC,MAAM,EAAE,CAAC;IAE1C,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,wEAAwE;QACxE,qEAAqE;QACrE,wEAAwE;QACxE,MAAM,GAAG,GAAG,MAAM,qBAAW,CAAC,IAAI,CAAC,GAAG,EAAE;YACtC,UAAU,EAAE,qBAAW,CAAC,OAAO;SAChC,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC;QAChE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,yEAAyE;IACzE,yEAAyE;IACzE,2EAA2E;IAC3E,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IAC9B,MAAM,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;IAClC,MAAM,CAAC,WAAW,CAAC,wCAAwC,CAAC,CAAC;IAC7D,MAAM,CAAC,UAAU,CAAC,wBAAwB,CAAC,CAAC;IAC5C,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAChC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC;QAC9B,yEAAyE;QACzE,uEAAuE;QACvE,yEAAyE;QACzE,+CAA+C;QAC/C,gBAAgB,EAAE,KAAK;KACxB,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC"}
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@aibrains/pdf-renderer",
3
- "version": "0.9.0",
3
+ "version": "0.10.1",
4
4
  "description": "EdForge PDF rendering library. JSX-based document templates built on @react-pdf/renderer, with localization (EN + NE), Bikram Sambat date support, and a TemplateDescriptor registry for cross-domain doc types (invoice, receipt, report card, admit card, etc.).",
5
- "license": "BUSL-1.1",
6
- "author": "Edforge Technologies LLC",
5
+ "license": "MIT",
6
+ "author": "Shoaib Rain",
7
7
  "main": "dist/index.js",
8
8
  "types": "dist/index.d.ts",
9
9
  "exports": {
@@ -49,7 +49,8 @@
49
49
  },
50
50
  "dependencies": {
51
51
  "@aibrains/shared-types": "^0.65.0",
52
- "@react-pdf/renderer": "^3.4.5"
52
+ "@react-pdf/renderer": "^3.4.5",
53
+ "pdf-lib": "^1.17.1"
53
54
  },
54
55
  "peerDependencies": {
55
56
  "react": ">=18.0.0 <20.0.0"