@carlonicora/nestjs-neo4jsonapi 1.72.0 → 1.74.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/dist/core/blocknote/blocknote.module.d.ts +1 -0
- package/dist/core/blocknote/blocknote.module.d.ts.map +1 -1
- package/dist/core/blocknote/blocknote.module.js +4 -2
- package/dist/core/blocknote/blocknote.module.js.map +1 -1
- package/dist/core/blocknote/index.d.ts +1 -0
- package/dist/core/blocknote/index.d.ts.map +1 -1
- package/dist/core/blocknote/index.js +1 -0
- package/dist/core/blocknote/index.js.map +1 -1
- package/dist/core/blocknote/services/blocknote-to-docx.service.d.ts +55 -0
- package/dist/core/blocknote/services/blocknote-to-docx.service.d.ts.map +1 -0
- package/dist/core/blocknote/services/blocknote-to-docx.service.js +903 -0
- package/dist/core/blocknote/services/blocknote-to-docx.service.js.map +1 -0
- package/dist/core/blocknote/services/blocknote.service.d.ts.map +1 -1
- package/dist/core/blocknote/services/blocknote.service.js +25 -0
- package/dist/core/blocknote/services/blocknote.service.js.map +1 -1
- package/dist/core/document/document.module.d.ts +25 -0
- package/dist/core/document/document.module.d.ts.map +1 -0
- package/dist/core/document/document.module.js +46 -0
- package/dist/core/document/document.module.js.map +1 -0
- package/dist/core/document/index.d.ts +6 -0
- package/dist/core/document/index.d.ts.map +1 -0
- package/dist/core/document/index.js +22 -0
- package/dist/core/document/index.js.map +1 -0
- package/dist/core/document/services/abstract-document-generator.service.d.ts +90 -0
- package/dist/core/document/services/abstract-document-generator.service.d.ts.map +1 -0
- package/dist/core/document/services/abstract-document-generator.service.js +120 -0
- package/dist/core/document/services/abstract-document-generator.service.js.map +1 -0
- package/dist/core/document/services/docx-template.service.d.ts +36 -0
- package/dist/core/document/services/docx-template.service.d.ts.map +1 -0
- package/dist/core/document/services/docx-template.service.js +58 -0
- package/dist/core/document/services/docx-template.service.js.map +1 -0
- package/dist/core/document/utils/inject-draft-watermark.d.ts +24 -0
- package/dist/core/document/utils/inject-draft-watermark.d.ts.map +1 -0
- package/dist/core/document/utils/inject-draft-watermark.js +182 -0
- package/dist/core/document/utils/inject-draft-watermark.js.map +1 -0
- package/dist/core/document/utils/inject-xml.d.ts +15 -0
- package/dist/core/document/utils/inject-xml.d.ts.map +1 -0
- package/dist/core/document/utils/inject-xml.js +35 -0
- package/dist/core/document/utils/inject-xml.js.map +1 -0
- package/dist/core/pdf/index.d.ts +3 -0
- package/dist/core/pdf/index.d.ts.map +1 -0
- package/dist/core/pdf/index.js +19 -0
- package/dist/core/pdf/index.js.map +1 -0
- package/dist/core/pdf/pdf.module.d.ts +21 -0
- package/dist/core/pdf/pdf.module.d.ts.map +1 -0
- package/dist/core/pdf/pdf.module.js +39 -0
- package/dist/core/pdf/pdf.module.js.map +1 -0
- package/dist/core/pdf/services/docx-to-pdf.service.d.ts +28 -0
- package/dist/core/pdf/services/docx-to-pdf.service.d.ts.map +1 -0
- package/dist/core/pdf/services/docx-to-pdf.service.js +86 -0
- package/dist/core/pdf/services/docx-to-pdf.service.js.map +1 -0
- package/dist/foundations/stripe/__tests__/mocks/stripe.mock.d.ts +62 -62
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +4 -1
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic "BOZZA" (draft) watermark injection for DOCX files.
|
|
3
|
+
*
|
|
4
|
+
* Ported from apps/api/src/features/finance/invoice/document/inject-draft-watermark.ts
|
|
5
|
+
* and adapted to accept/return a Buffer instead of a JSZip instance, so it
|
|
6
|
+
* can be used as a standalone utility without the caller needing to manage
|
|
7
|
+
* the JSZip lifecycle.
|
|
8
|
+
*
|
|
9
|
+
* The original file remains in place until T5/T6 migration work (it will be
|
|
10
|
+
* deleted once the invoice generator is refactored to use this library util).
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Inject an idempotent "BOZZA" watermark into the document's default header.
|
|
14
|
+
*
|
|
15
|
+
* Accepts a DOCX as a Buffer and returns a new DOCX Buffer with the watermark
|
|
16
|
+
* applied. Re-running on the same document is safe — the SENTINEL marker is
|
|
17
|
+
* checked first so the watermark is never double-injected.
|
|
18
|
+
*
|
|
19
|
+
* @param docxBuffer - A valid DOCX file as a Buffer.
|
|
20
|
+
* @param text - Watermark text (defaults to "BOZZA").
|
|
21
|
+
* @returns A new DOCX Buffer with the watermark injected.
|
|
22
|
+
*/
|
|
23
|
+
export declare function injectDraftWatermark(docxBuffer: Buffer, text?: string): Promise<Buffer>;
|
|
24
|
+
//# sourceMappingURL=inject-draft-watermark.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inject-draft-watermark.d.ts","sourceRoot":"","sources":["../../../../src/core/document/utils/inject-draft-watermark.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH;;;;;;;;;;GAUG;AACH,wBAAsB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,SAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAI9F"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Generic "BOZZA" (draft) watermark injection for DOCX files.
|
|
4
|
+
*
|
|
5
|
+
* Ported from apps/api/src/features/finance/invoice/document/inject-draft-watermark.ts
|
|
6
|
+
* and adapted to accept/return a Buffer instead of a JSZip instance, so it
|
|
7
|
+
* can be used as a standalone utility without the caller needing to manage
|
|
8
|
+
* the JSZip lifecycle.
|
|
9
|
+
*
|
|
10
|
+
* The original file remains in place until T5/T6 migration work (it will be
|
|
11
|
+
* deleted once the invoice generator is refactored to use this library util).
|
|
12
|
+
*/
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.injectDraftWatermark = injectDraftWatermark;
|
|
18
|
+
const jszip_1 = __importDefault(require("jszip"));
|
|
19
|
+
const SENTINEL = "___NEURAL_ERP_DRAFT_WATERMARK___";
|
|
20
|
+
const DEFAULT_HEADER_PATH = "word/header1.xml";
|
|
21
|
+
const INJECTED_FLAG = "__neuralErpDraftWatermarkInjected";
|
|
22
|
+
/**
|
|
23
|
+
* Inject an idempotent "BOZZA" watermark into the document's default header.
|
|
24
|
+
*
|
|
25
|
+
* Accepts a DOCX as a Buffer and returns a new DOCX Buffer with the watermark
|
|
26
|
+
* applied. Re-running on the same document is safe — the SENTINEL marker is
|
|
27
|
+
* checked first so the watermark is never double-injected.
|
|
28
|
+
*
|
|
29
|
+
* @param docxBuffer - A valid DOCX file as a Buffer.
|
|
30
|
+
* @param text - Watermark text (defaults to "BOZZA").
|
|
31
|
+
* @returns A new DOCX Buffer with the watermark injected.
|
|
32
|
+
*/
|
|
33
|
+
async function injectDraftWatermark(docxBuffer, text = "BOZZA") {
|
|
34
|
+
const zip = await jszip_1.default.loadAsync(docxBuffer);
|
|
35
|
+
await _injectWatermarkIntoZip(zip, text);
|
|
36
|
+
return zip.generateAsync({ type: "nodebuffer" });
|
|
37
|
+
}
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// Internal implementation (operates on a JSZip instance)
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
async function _injectWatermarkIntoZip(zip, text) {
|
|
42
|
+
const zipWithFlag = zip;
|
|
43
|
+
if (zipWithFlag[INJECTED_FLAG])
|
|
44
|
+
return;
|
|
45
|
+
zipWithFlag[INJECTED_FLAG] = true;
|
|
46
|
+
const existingHeaderFile = zip.file(DEFAULT_HEADER_PATH);
|
|
47
|
+
// Branch 1: template already has its own header (the common case for real
|
|
48
|
+
// templates with company logo / fiscal data in the header band). Inject the
|
|
49
|
+
// watermark paragraph INTO the existing header before its closing `</w:hdr>`.
|
|
50
|
+
if (existingHeaderFile) {
|
|
51
|
+
let headerXml = await existingHeaderFile.async("string");
|
|
52
|
+
// Idempotency: skip if our SENTINEL bookmark is already present.
|
|
53
|
+
if (headerXml.includes(SENTINEL))
|
|
54
|
+
return;
|
|
55
|
+
headerXml = headerXml.replace("</w:hdr>", `${_watermarkParagraph(text)}</w:hdr>`);
|
|
56
|
+
zip.file(DEFAULT_HEADER_PATH, headerXml);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
// Branch 2: no header in the template — create one from scratch and wire up
|
|
60
|
+
// the relationship + content-type + sectPr reference.
|
|
61
|
+
const documentXmlFile = zip.file("word/document.xml");
|
|
62
|
+
if (!documentXmlFile)
|
|
63
|
+
return;
|
|
64
|
+
let documentXml = await documentXmlFile.async("string");
|
|
65
|
+
const headerXml = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
66
|
+
<w:hdr xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
|
|
67
|
+
xmlns:v="urn:schemas-microsoft-com:vml"
|
|
68
|
+
xmlns:o="urn:schemas-microsoft-com:office:office"
|
|
69
|
+
xmlns:w10="urn:schemas-microsoft-com:office:word"
|
|
70
|
+
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
|
|
71
|
+
${_watermarkParagraph(text)}
|
|
72
|
+
</w:hdr>`;
|
|
73
|
+
zip.file(DEFAULT_HEADER_PATH, headerXml);
|
|
74
|
+
const relsPath = "word/_rels/document.xml.rels";
|
|
75
|
+
const relsFile = zip.file(relsPath);
|
|
76
|
+
let relsXml = relsFile
|
|
77
|
+
? await relsFile.async("string")
|
|
78
|
+
: `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
79
|
+
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
|
|
80
|
+
</Relationships>`;
|
|
81
|
+
const relId = "rIdNeuralErpDraftHeader";
|
|
82
|
+
if (!relsXml.includes(relId)) {
|
|
83
|
+
relsXml = relsXml.replace("</Relationships>", `<Relationship Id="${relId}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/header" Target="header1.xml"/></Relationships>`);
|
|
84
|
+
zip.file(relsPath, relsXml);
|
|
85
|
+
}
|
|
86
|
+
const ctPath = "[Content_Types].xml";
|
|
87
|
+
const ctFile = zip.file(ctPath);
|
|
88
|
+
if (ctFile) {
|
|
89
|
+
let ctXml = await ctFile.async("string");
|
|
90
|
+
if (!ctXml.includes("/word/header1.xml")) {
|
|
91
|
+
ctXml = ctXml.replace("</Types>", `<Override PartName="/word/header1.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml"/></Types>`);
|
|
92
|
+
zip.file(ctPath, ctXml);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (documentXml.includes("<w:sectPr")) {
|
|
96
|
+
documentXml = documentXml.replace(/<w:sectPr\b([^>]*)>/, `<w:sectPr$1><w:headerReference w:type="default" r:id="${relId}"/>`);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
documentXml = documentXml.replace("</w:body>", `<w:sectPr><w:headerReference w:type="default" r:id="${relId}"/></w:sectPr></w:body>`);
|
|
100
|
+
}
|
|
101
|
+
zip.file("word/document.xml", documentXml);
|
|
102
|
+
}
|
|
103
|
+
function _watermarkParagraph(text) {
|
|
104
|
+
// Build a watermark using DrawingML (`<w:drawing>` inside `<mc:AlternateContent>`)
|
|
105
|
+
// with a VML fallback. DrawingML is rendered correctly by both Microsoft Word
|
|
106
|
+
// AND LibreOffice (which produces the PDF). The VML path is kept as a
|
|
107
|
+
// legacy fallback for older renderers via `<mc:Fallback>`.
|
|
108
|
+
//
|
|
109
|
+
// Size: ~7620000 EMU wide × ~1524000 EMU tall (≈ 21cm × 4cm).
|
|
110
|
+
// Rotation: -2700000 (60ths of a degree → -45°, i.e. bottom-left to top-right).
|
|
111
|
+
return `<w:p>
|
|
112
|
+
<w:bookmarkStart w:id="9999" w:name="${SENTINEL}"/>
|
|
113
|
+
<w:r>
|
|
114
|
+
<w:rPr><w:noProof/></w:rPr>
|
|
115
|
+
<mc:AlternateContent xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
|
|
116
|
+
<mc:Choice xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" Requires="wps">
|
|
117
|
+
<w:drawing>
|
|
118
|
+
<wp:anchor distT="0" distB="0" distL="114300" distR="114300" simplePos="0" relativeHeight="251658240" behindDoc="1" locked="0" layoutInCell="1" allowOverlap="1">
|
|
119
|
+
<wp:simplePos x="0" y="0"/>
|
|
120
|
+
<wp:positionH relativeFrom="page"><wp:align>center</wp:align></wp:positionH>
|
|
121
|
+
<wp:positionV relativeFrom="page"><wp:align>center</wp:align></wp:positionV>
|
|
122
|
+
<wp:extent cx="7620000" cy="1524000"/>
|
|
123
|
+
<wp:effectExtent l="0" t="0" r="0" b="0"/>
|
|
124
|
+
<wp:wrapNone/>
|
|
125
|
+
<wp:docPr id="1" name="DraftWatermark"/>
|
|
126
|
+
<wp:cNvGraphicFramePr/>
|
|
127
|
+
<a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
|
|
128
|
+
<a:graphicData uri="http://schemas.microsoft.com/office/word/2010/wordprocessingShape">
|
|
129
|
+
<wps:wsp>
|
|
130
|
+
<wps:cNvSpPr txBox="1"/>
|
|
131
|
+
<wps:spPr>
|
|
132
|
+
<a:xfrm rot="-2700000">
|
|
133
|
+
<a:off x="0" y="0"/>
|
|
134
|
+
<a:ext cx="7620000" cy="1524000"/>
|
|
135
|
+
</a:xfrm>
|
|
136
|
+
<a:prstGeom prst="rect"><a:avLst/></a:prstGeom>
|
|
137
|
+
<a:noFill/>
|
|
138
|
+
<a:ln><a:noFill/></a:ln>
|
|
139
|
+
</wps:spPr>
|
|
140
|
+
<wps:txbx>
|
|
141
|
+
<w:txbxContent>
|
|
142
|
+
<w:p>
|
|
143
|
+
<w:pPr>
|
|
144
|
+
<w:jc w:val="center"/>
|
|
145
|
+
<w:rPr>
|
|
146
|
+
<w:rFonts w:ascii="Calibri" w:hAnsi="Calibri"/>
|
|
147
|
+
<w:color w:val="D3D3D3"/>
|
|
148
|
+
<w:sz w:val="200"/>
|
|
149
|
+
</w:rPr>
|
|
150
|
+
</w:pPr>
|
|
151
|
+
<w:r>
|
|
152
|
+
<w:rPr>
|
|
153
|
+
<w:rFonts w:ascii="Calibri" w:hAnsi="Calibri"/>
|
|
154
|
+
<w:color w:val="D3D3D3"/>
|
|
155
|
+
<w:sz w:val="200"/>
|
|
156
|
+
</w:rPr>
|
|
157
|
+
<w:t>${text}</w:t>
|
|
158
|
+
</w:r>
|
|
159
|
+
</w:p>
|
|
160
|
+
</w:txbxContent>
|
|
161
|
+
</wps:txbx>
|
|
162
|
+
<wps:bodyPr wrap="none" rtlCol="0" anchor="ctr"/>
|
|
163
|
+
</wps:wsp>
|
|
164
|
+
</a:graphicData>
|
|
165
|
+
</a:graphic>
|
|
166
|
+
</wp:anchor>
|
|
167
|
+
</w:drawing>
|
|
168
|
+
</mc:Choice>
|
|
169
|
+
<mc:Fallback>
|
|
170
|
+
<w:pict>
|
|
171
|
+
<v:shape id="DraftWatermarkFallback" type="#_x0000_t136" style="position:absolute;margin-left:0;margin-top:0;width:600pt;height:120pt;rotation:-45;z-index:-251658240;mso-position-horizontal:center;mso-position-horizontal-relative:margin;mso-position-vertical:center;mso-position-vertical-relative:margin" fillcolor="#D3D3D3" stroked="f">
|
|
172
|
+
<v:fill opacity=".5"/>
|
|
173
|
+
<v:textpath style="font-family:"Calibri";font-size:1pt" string="${text}"/>
|
|
174
|
+
</v:shape>
|
|
175
|
+
</w:pict>
|
|
176
|
+
</mc:Fallback>
|
|
177
|
+
</mc:AlternateContent>
|
|
178
|
+
</w:r>
|
|
179
|
+
<w:bookmarkEnd w:id="9999"/>
|
|
180
|
+
</w:p>`;
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=inject-draft-watermark.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inject-draft-watermark.js","sourceRoot":"","sources":["../../../../src/core/document/utils/inject-draft-watermark.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Replace a placeholder string in word/document.xml with a raw XML fragment.
|
|
3
|
+
*
|
|
4
|
+
* The placeholder must already be present in the document's XML. Both
|
|
5
|
+
* placeholder and xmlFragment are inserted verbatim — caller is responsible
|
|
6
|
+
* for producing well-formed WordprocessingML.
|
|
7
|
+
*
|
|
8
|
+
* @param docxBuffer - A valid DOCX file as a Buffer.
|
|
9
|
+
* @param placeholder - The exact string to find and replace in word/document.xml.
|
|
10
|
+
* @param xmlFragment - The raw XML string that replaces the placeholder.
|
|
11
|
+
* @returns A new DOCX Buffer with the substitution applied.
|
|
12
|
+
* @throws If word/document.xml is missing or the placeholder is not found.
|
|
13
|
+
*/
|
|
14
|
+
export declare function injectXml(docxBuffer: Buffer, placeholder: string, xmlFragment: string): Promise<Buffer>;
|
|
15
|
+
//# sourceMappingURL=inject-xml.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inject-xml.d.ts","sourceRoot":"","sources":["../../../../src/core/document/utils/inject-xml.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,wBAAsB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAiB7G"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.injectXml = injectXml;
|
|
7
|
+
const jszip_1 = __importDefault(require("jszip"));
|
|
8
|
+
/**
|
|
9
|
+
* Replace a placeholder string in word/document.xml with a raw XML fragment.
|
|
10
|
+
*
|
|
11
|
+
* The placeholder must already be present in the document's XML. Both
|
|
12
|
+
* placeholder and xmlFragment are inserted verbatim — caller is responsible
|
|
13
|
+
* for producing well-formed WordprocessingML.
|
|
14
|
+
*
|
|
15
|
+
* @param docxBuffer - A valid DOCX file as a Buffer.
|
|
16
|
+
* @param placeholder - The exact string to find and replace in word/document.xml.
|
|
17
|
+
* @param xmlFragment - The raw XML string that replaces the placeholder.
|
|
18
|
+
* @returns A new DOCX Buffer with the substitution applied.
|
|
19
|
+
* @throws If word/document.xml is missing or the placeholder is not found.
|
|
20
|
+
*/
|
|
21
|
+
async function injectXml(docxBuffer, placeholder, xmlFragment) {
|
|
22
|
+
const zip = await jszip_1.default.loadAsync(docxBuffer);
|
|
23
|
+
const documentXmlFile = zip.file("word/document.xml");
|
|
24
|
+
if (!documentXmlFile) {
|
|
25
|
+
throw new Error("DOCX is missing word/document.xml");
|
|
26
|
+
}
|
|
27
|
+
const documentXml = await documentXmlFile.async("text");
|
|
28
|
+
if (!documentXml.includes(placeholder)) {
|
|
29
|
+
throw new Error(`Placeholder not found in DOCX: ${placeholder}`);
|
|
30
|
+
}
|
|
31
|
+
const replaced = documentXml.replace(placeholder, xmlFragment);
|
|
32
|
+
zip.file("word/document.xml", replaced);
|
|
33
|
+
return zip.generateAsync({ type: "nodebuffer" });
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=inject-xml.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inject-xml.js","sourceRoot":"","sources":["../../../../src/core/document/utils/inject-xml.ts"],"names":[],"mappings":";;;;;AAeA,8BAiBC;AAhCD,kDAA0B;AAE1B;;;;;;;;;;;;GAYG;AACI,KAAK,UAAU,SAAS,CAAC,UAAkB,EAAE,WAAmB,EAAE,WAAmB;IAC1F,MAAM,GAAG,GAAG,MAAM,eAAK,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAE9C,MAAM,eAAe,GAAG,GAAG,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IACtD,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACvD,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACxD,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,kCAAkC,WAAW,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IAC/D,GAAG,CAAC,IAAI,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAC;IAExC,OAAO,GAAG,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/pdf/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,gCAAgC,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./pdf.module"), exports);
|
|
18
|
+
__exportStar(require("./services/docx-to-pdf.service"), exports);
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/pdf/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+CAA6B;AAC7B,iEAA+C"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PdfModule
|
|
3
|
+
*
|
|
4
|
+
* Provides DOCX → PDF conversion via LibreOffice headless.
|
|
5
|
+
*
|
|
6
|
+
* Import this module wherever `DocxToPdfService` is needed. For the full
|
|
7
|
+
* document-generation workflow (template rendering + DOCX post-processing +
|
|
8
|
+
* S3 upload + PDF conversion), import `DocumentModule` instead — it re-exports
|
|
9
|
+
* `PdfModule` transitively.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* @Module({
|
|
14
|
+
* imports: [PdfModule],
|
|
15
|
+
* })
|
|
16
|
+
* export class MyFeatureModule {}
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export declare class PdfModule {
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=pdf.module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pdf.module.d.ts","sourceRoot":"","sources":["../../../src/core/pdf/pdf.module.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAIa,SAAS;CAAG"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.PdfModule = void 0;
|
|
10
|
+
const common_1 = require("@nestjs/common");
|
|
11
|
+
const docx_to_pdf_service_1 = require("./services/docx-to-pdf.service");
|
|
12
|
+
/**
|
|
13
|
+
* PdfModule
|
|
14
|
+
*
|
|
15
|
+
* Provides DOCX → PDF conversion via LibreOffice headless.
|
|
16
|
+
*
|
|
17
|
+
* Import this module wherever `DocxToPdfService` is needed. For the full
|
|
18
|
+
* document-generation workflow (template rendering + DOCX post-processing +
|
|
19
|
+
* S3 upload + PDF conversion), import `DocumentModule` instead — it re-exports
|
|
20
|
+
* `PdfModule` transitively.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* @Module({
|
|
25
|
+
* imports: [PdfModule],
|
|
26
|
+
* })
|
|
27
|
+
* export class MyFeatureModule {}
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
let PdfModule = class PdfModule {
|
|
31
|
+
};
|
|
32
|
+
exports.PdfModule = PdfModule;
|
|
33
|
+
exports.PdfModule = PdfModule = __decorate([
|
|
34
|
+
(0, common_1.Module)({
|
|
35
|
+
providers: [docx_to_pdf_service_1.DocxToPdfService],
|
|
36
|
+
exports: [docx_to_pdf_service_1.DocxToPdfService],
|
|
37
|
+
})
|
|
38
|
+
], PdfModule);
|
|
39
|
+
//# sourceMappingURL=pdf.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pdf.module.js","sourceRoot":"","sources":["../../../src/core/pdf/pdf.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,wEAAkE;AAElE;;;;;;;;;;;;;;;;;GAiBG;AAKI,IAAM,SAAS,GAAf,MAAM,SAAS;CAAG,CAAA;AAAZ,8BAAS;oBAAT,SAAS;IAJrB,IAAA,eAAM,EAAC;QACN,SAAS,EAAE,CAAC,sCAAgB,CAAC;QAC7B,OAAO,EAAE,CAAC,sCAAgB,CAAC;KAC5B,CAAC;GACW,SAAS,CAAG"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a DOCX buffer to a PDF buffer by shelling out to LibreOffice
|
|
3
|
+
* headless via the `libreoffice-convert` wrapper.
|
|
4
|
+
*
|
|
5
|
+
* The system must have `libreoffice` (libreoffice-core + libreoffice-writer)
|
|
6
|
+
* on $PATH. See the api Dockerfile and the api CLAUDE.md for local-dev install
|
|
7
|
+
* instructions.
|
|
8
|
+
*
|
|
9
|
+
* - macOS: `brew install --cask libreoffice`
|
|
10
|
+
* - Linux: `apt-get install libreoffice-core libreoffice-writer`
|
|
11
|
+
*
|
|
12
|
+
* The service is intentionally stateless — no subprocess pooling, no lifecycle
|
|
13
|
+
* hooks. Each call spawns a fresh LibreOffice subprocess (~2–5 s). The
|
|
14
|
+
* `Buffer → Buffer` interface is stable so a future switch to Gotenberg (HTTP)
|
|
15
|
+
* or another engine only requires changing this file's body.
|
|
16
|
+
*
|
|
17
|
+
* Implementation note: `libreoffice-convert@^1.8` is a hybrid function — it
|
|
18
|
+
* takes a callback AND returns a Promise (because it uses `async.auto().then()`
|
|
19
|
+
* internally). Node's `util.promisify` emits DEP0174 ("Calling promisify on a
|
|
20
|
+
* function that returns a Promise is likely a mistake") on hybrid functions,
|
|
21
|
+
* so we wrap the callback directly with `new Promise(...)` instead of
|
|
22
|
+
* `promisify`.
|
|
23
|
+
*/
|
|
24
|
+
export declare class DocxToPdfService {
|
|
25
|
+
/** Convert a DOCX buffer to a PDF buffer. Throws on conversion failure. */
|
|
26
|
+
convert(docxBuffer: Buffer): Promise<Buffer>;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=docx-to-pdf.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docx-to-pdf.service.d.ts","sourceRoot":"","sources":["../../../../src/core/pdf/services/docx-to-pdf.service.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBACa,gBAAgB;IAC3B,2EAA2E;IAC3E,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAW7C"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
19
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
20
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
21
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
22
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
23
|
+
};
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.DocxToPdfService = void 0;
|
|
43
|
+
const common_1 = require("@nestjs/common");
|
|
44
|
+
const libre = __importStar(require("libreoffice-convert"));
|
|
45
|
+
/**
|
|
46
|
+
* Converts a DOCX buffer to a PDF buffer by shelling out to LibreOffice
|
|
47
|
+
* headless via the `libreoffice-convert` wrapper.
|
|
48
|
+
*
|
|
49
|
+
* The system must have `libreoffice` (libreoffice-core + libreoffice-writer)
|
|
50
|
+
* on $PATH. See the api Dockerfile and the api CLAUDE.md for local-dev install
|
|
51
|
+
* instructions.
|
|
52
|
+
*
|
|
53
|
+
* - macOS: `brew install --cask libreoffice`
|
|
54
|
+
* - Linux: `apt-get install libreoffice-core libreoffice-writer`
|
|
55
|
+
*
|
|
56
|
+
* The service is intentionally stateless — no subprocess pooling, no lifecycle
|
|
57
|
+
* hooks. Each call spawns a fresh LibreOffice subprocess (~2–5 s). The
|
|
58
|
+
* `Buffer → Buffer` interface is stable so a future switch to Gotenberg (HTTP)
|
|
59
|
+
* or another engine only requires changing this file's body.
|
|
60
|
+
*
|
|
61
|
+
* Implementation note: `libreoffice-convert@^1.8` is a hybrid function — it
|
|
62
|
+
* takes a callback AND returns a Promise (because it uses `async.auto().then()`
|
|
63
|
+
* internally). Node's `util.promisify` emits DEP0174 ("Calling promisify on a
|
|
64
|
+
* function that returns a Promise is likely a mistake") on hybrid functions,
|
|
65
|
+
* so we wrap the callback directly with `new Promise(...)` instead of
|
|
66
|
+
* `promisify`.
|
|
67
|
+
*/
|
|
68
|
+
let DocxToPdfService = class DocxToPdfService {
|
|
69
|
+
/** Convert a DOCX buffer to a PDF buffer. Throws on conversion failure. */
|
|
70
|
+
convert(docxBuffer) {
|
|
71
|
+
return new Promise((resolve, reject) => {
|
|
72
|
+
libre.convert(docxBuffer, ".pdf", undefined, (err, pdfBuffer) => {
|
|
73
|
+
if (err) {
|
|
74
|
+
reject(err);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
resolve(pdfBuffer);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
exports.DocxToPdfService = DocxToPdfService;
|
|
83
|
+
exports.DocxToPdfService = DocxToPdfService = __decorate([
|
|
84
|
+
(0, common_1.Injectable)()
|
|
85
|
+
], DocxToPdfService);
|
|
86
|
+
//# sourceMappingURL=docx-to-pdf.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docx-to-pdf.service.js","sourceRoot":"","sources":["../../../../src/core/pdf/services/docx-to-pdf.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAA4C;AAC5C,2DAA6C;AAE7C;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEI,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;IAC3B,2EAA2E;IAC3E,OAAO,CAAC,UAAkB;QACxB,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC7C,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE;gBAC9D,IAAI,GAAG,EAAE,CAAC;oBACR,MAAM,CAAC,GAAG,CAAC,CAAC;oBACZ,OAAO;gBACT,CAAC;gBACD,OAAO,CAAC,SAAS,CAAC,CAAC;YACrB,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;CACF,CAAA;AAbY,4CAAgB;2BAAhB,gBAAgB;IAD5B,IAAA,mBAAU,GAAE;GACA,gBAAgB,CAa5B"}
|