node-hp-scan-to 1.4.3 → 1.5.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.
Files changed (95) hide show
  1. package/README.md +76 -29
  2. package/dist/Destination.js +2 -2
  3. package/dist/Destination.js.map +1 -1
  4. package/dist/DiscoveryTree.js.map +1 -1
  5. package/dist/Event.js.map +1 -1
  6. package/dist/EventTable.js +1 -1
  7. package/dist/EventTable.js.map +1 -1
  8. package/dist/HPApi.js +4 -4
  9. package/dist/HPApi.js.map +1 -1
  10. package/dist/InputSource.js +1 -1
  11. package/dist/InputSource.js.map +1 -1
  12. package/dist/Job.js +2 -2
  13. package/dist/Job.js.map +1 -1
  14. package/dist/JpegUtil.d.ts +1 -0
  15. package/dist/JpegUtil.js.map +1 -1
  16. package/dist/PaperlessCOnfig.d.ts +7 -0
  17. package/dist/PaperlessCOnfig.js +3 -0
  18. package/dist/PaperlessCOnfig.js.map +1 -0
  19. package/dist/PaperlessConfig.d.ts +7 -0
  20. package/dist/PaperlessConfig.js +3 -0
  21. package/dist/PaperlessConfig.js.map +1 -0
  22. package/dist/PathHelper.js.map +1 -1
  23. package/dist/ScanCaps.js +12 -2
  24. package/dist/ScanCaps.js.map +1 -1
  25. package/dist/ScanContent.d.ts +0 -1
  26. package/dist/ScanContent.js +0 -24
  27. package/dist/ScanContent.js.map +1 -1
  28. package/dist/ScanJobManifest.js.map +1 -1
  29. package/dist/ScanJobSettings.js +2 -2
  30. package/dist/ScanJobSettings.js.map +1 -1
  31. package/dist/ScanStatus.js.map +1 -1
  32. package/dist/WalkupScanDestination.js.map +1 -1
  33. package/dist/WalkupScanDestinations.js +1 -1
  34. package/dist/WalkupScanDestinations.js.map +1 -1
  35. package/dist/WalkupScanManifest.js.map +1 -1
  36. package/dist/WalkupScanToCompDestination.js.map +1 -1
  37. package/dist/WalkupScanToCompDestinations.js +1 -1
  38. package/dist/WalkupScanToCompDestinations.js.map +1 -1
  39. package/dist/WalkupScanToCompManifest.js.map +1 -1
  40. package/dist/commitInfo.json +3 -0
  41. package/dist/healthcheck.d.ts +1 -0
  42. package/dist/healthcheck.js +24 -0
  43. package/dist/healthcheck.js.map +1 -0
  44. package/dist/index.js +106 -19
  45. package/dist/index.js.map +1 -1
  46. package/dist/listening.js +2 -2
  47. package/dist/listening.js.map +1 -1
  48. package/dist/paperless/PaperlessConfig.d.ts +7 -0
  49. package/dist/paperless/PaperlessConfig.js +3 -0
  50. package/dist/paperless/PaperlessConfig.js.map +1 -0
  51. package/dist/paperless/paperless.d.ts +7 -0
  52. package/dist/paperless/paperless.js +83 -0
  53. package/dist/paperless/paperless.js.map +1 -0
  54. package/dist/paperless.d.ts +7 -0
  55. package/dist/paperless.js +83 -0
  56. package/dist/paperless.js.map +1 -0
  57. package/dist/pdfProcessing.d.ts +4 -0
  58. package/dist/pdfProcessing.js +52 -0
  59. package/dist/pdfProcessing.js.map +1 -0
  60. package/dist/postProcessing.d.ts +3 -0
  61. package/dist/postProcessing.js +44 -0
  62. package/dist/postProcessing.js.map +1 -0
  63. package/dist/readDeviceCapabilities.js.map +1 -1
  64. package/dist/scanProcessing.d.ts +7 -1
  65. package/dist/scanProcessing.js +20 -49
  66. package/dist/scanProcessing.js.map +1 -1
  67. package/dist/test/PathHelper.test.js +2 -2
  68. package/dist/test/PathHelper.test.js.map +1 -1
  69. package/dist/test/ScanCaps.test.js +20 -0
  70. package/dist/test/ScanCaps.test.js.map +1 -1
  71. package/dist/test/clean.js.map +1 -1
  72. package/dist/test/scanProcessing.test.js +1 -0
  73. package/dist/test/scanProcessing.test.js.map +1 -1
  74. package/dist/test-bonjour.d.ts +1 -0
  75. package/dist/test-bonjour.js +20 -0
  76. package/dist/test-bonjour.js.map +1 -0
  77. package/package.json +12 -9
  78. package/src/Destination.ts +2 -2
  79. package/src/EventTable.ts +1 -1
  80. package/src/HPApi.ts +4 -4
  81. package/src/Job.ts +2 -2
  82. package/src/ScanCaps.ts +18 -8
  83. package/src/ScanContent.ts +0 -22
  84. package/src/ScanJobSettings.ts +2 -2
  85. package/src/WalkupScanDestinations.ts +1 -1
  86. package/src/WalkupScanToCompDestinations.ts +1 -1
  87. package/src/commitInfo.json +3 -0
  88. package/src/healthcheck.ts +17 -0
  89. package/src/index.ts +132 -24
  90. package/src/listening.ts +2 -2
  91. package/src/paperless/PaperlessConfig.ts +7 -0
  92. package/src/paperless/paperless.ts +122 -0
  93. package/src/pdfProcessing.ts +67 -0
  94. package/src/postProcessing.ts +91 -0
  95. package/src/scanProcessing.ts +46 -93
package/src/index.ts CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  import os from "os";
7
7
  import { Command, Option, OptionValues, program } from "commander";
8
- import Bonjour from "bonjour";
8
+ import { Bonjour } from "bonjour-service";
9
9
  import config from "config";
10
10
  import HPApi from "./HPApi";
11
11
  import PathHelper from "./PathHelper";
@@ -19,11 +19,15 @@ import {
19
19
  import {
20
20
  AdfAutoScanConfig,
21
21
  DirectoryConfig,
22
- saveScan,
22
+ saveScanFromEvent,
23
23
  ScanConfig,
24
24
  scanFromAdf,
25
25
  waitAdfLoaded,
26
26
  } from "./scanProcessing";
27
+ import * as commitInfo from "./commitInfo.json";
28
+ import { PaperlessConfig } from "./paperless/PaperlessConfig";
29
+ import { startHealthCheckServer } from "./healthcheck";
30
+
27
31
 
28
32
  let iteration = 0;
29
33
 
@@ -52,6 +56,7 @@ async function listenCmd(
52
56
  let keepActive = true;
53
57
  let errorCount = 0;
54
58
  while (keepActive) {
59
+ iteration++;
55
60
  console.log(`Running iteration: ${iteration} - errorCount: ${errorCount}`);
56
61
  try {
57
62
  const event = await waitScanEvent(deviceCapabilities, registrationConfig);
@@ -61,7 +66,7 @@ async function listenCmd(
61
66
  scanConfig.directoryConfig.filePattern,
62
67
  );
63
68
  console.log(`Scan event captured, saving scan #${scanCount}`);
64
- await saveScan(
69
+ await saveScanFromEvent(
65
70
  event,
66
71
  folder,
67
72
  tempFolder,
@@ -117,6 +122,7 @@ async function adfAutoscanCmd(
117
122
  let keepActive = true;
118
123
  let errorCount = 0;
119
124
  while (keepActive) {
125
+ iteration++;
120
126
  console.log(`Running iteration: ${iteration} - errorCount: ${errorCount}`);
121
127
  try {
122
128
  await waitAdfLoaded(
@@ -170,9 +176,9 @@ async function clearRegistrationsCmd(cmd: Command) {
170
176
 
171
177
  function findOfficejetIp(deviceNamePrefix: string): Promise<string> {
172
178
  return new Promise((resolve) => {
173
- const bonjour = Bonjour();
179
+ const bonjour = new Bonjour();
174
180
  console.log("Searching device...");
175
- let browser = bonjour.find(
181
+ const browser = bonjour.find(
176
182
  {
177
183
  type: "http",
178
184
  },
@@ -202,15 +208,15 @@ function getConfig<T>(name: string): T | undefined {
202
208
  function setupScanParameters(command: Command): Command {
203
209
  command.option(
204
210
  "-d, --directory <dir>",
205
- "Directory where scans are saved (default: /tmp/scan-to-pc<random>)",
211
+ "Directory where scans are saved (default: /tmp/scan-to-pcRANDOM)",
206
212
  );
207
213
  command.option(
208
214
  "-t, --temp-directory <dir>",
209
- "Temp directory used for processing (default: /tmp/scan-to-pc<random>)",
215
+ "Temp directory used for processing (default: /tmp/scan-to-pcRANDOM)",
210
216
  );
211
217
  command.option(
212
218
  "-p, --pattern <pattern>",
213
- 'Pattern for filename (i.e. "scan"_dd.mm.yyyy_hh:MM:ss, without this its scanPage<number>)',
219
+ 'Pattern for filename (i.e. "scan"_dd.mm.yyyy_hh:MM:ss, without this its scanPageNUMBER)',
214
220
  );
215
221
  command.option(
216
222
  "-r, --resolution <dpi>",
@@ -224,12 +230,33 @@ function setupScanParameters(command: Command): Command {
224
230
  "-h, --height <height>",
225
231
  "Height in pixel of the scans (default: 3507)",
226
232
  );
233
+ command.option(
234
+ "-s, --paperless-post-document-url <paperless_post_document_url>",
235
+ "The paperless post document url (example: https://domain.tld/api/documents/post_document/)",
236
+ );
237
+
238
+ command.option(
239
+ "-o, --paperless-token <paperless_token>",
240
+ "The paperless token",
241
+ );
242
+ command.option(
243
+ "--paperless-group-multi-page-scan-into-a-pdf",
244
+ "Combine multiple scanned images into a single PDF document",
245
+ );
246
+ command.option(
247
+ "--paperless-always-send-as-pdf-file",
248
+ "Always convert scan job to pdf before sending to paperless",
249
+ );
250
+ command.option(
251
+ "-k, --paperless-keep-files",
252
+ "Keep the scan files on the file system (default: false)",
253
+ );
227
254
  return command;
228
255
  }
229
256
 
230
257
  function setupParameterOpts(command: Command): Command {
231
258
  command.option(
232
- "-ip, --address <ip>",
259
+ "-a, --address <ip>",
233
260
  "IP address of the device (this overrides -p)",
234
261
  );
235
262
  command.option(
@@ -266,41 +293,93 @@ function getIsDebug(options: OptionValues) {
266
293
  return debug;
267
294
  }
268
295
 
269
- function getScanConfiguration(parentOption: OptionValues) {
296
+ function getPaperlessConfig(
297
+ parentOption: OptionValues,
298
+ ): PaperlessConfig | undefined {
299
+ const paperlessPostDocumentUrl: string =
300
+ parentOption.paperlessPostDocumentUrl ||
301
+ getConfig("paperless_post_document_url");
302
+ const configPaperlessToken: string =
303
+ parentOption.paperlessToken || getConfig("paperless_token");
304
+ const configPaperlessKeepFiles =
305
+ parentOption.paperlessKeepFiles ||
306
+ getConfig("paperless_keep_files") ||
307
+ false;
308
+
309
+ if (paperlessPostDocumentUrl && configPaperlessToken) {
310
+ const configPaperlessKeepFiles: boolean =
311
+ parentOption.paperlessKeepFiles ||
312
+ getConfig("paperless_keep_files") ||
313
+ false;
314
+ const groupMultiPageScanIntoAPdf: boolean =
315
+ parentOption.paperlessGroupMultiPageScanIntoAPdf ||
316
+ getConfig("paperless_group_multi_page_scan_into_a_pdf") ||
317
+ false;
318
+ const alwaysSendAsPdfFile: boolean =
319
+ parentOption.paperlessAlwaysSendAsPdfFile ||
320
+ getConfig("paperless_always_send_as_pdf_file") ||
321
+ false;
322
+
323
+ console.log(
324
+ `Paperless configuration provided, post document url: ${paperlessPostDocumentUrl}, the token length: ${configPaperlessToken.length}, keepFiles: ${configPaperlessKeepFiles}`,
325
+ );
326
+ return {
327
+ postDocumentUrl: paperlessPostDocumentUrl,
328
+ authToken: configPaperlessToken,
329
+ keepFiles: configPaperlessKeepFiles,
330
+ groupMultiPageScanIntoAPdf: groupMultiPageScanIntoAPdf,
331
+ alwaysSendAsPdfFile: alwaysSendAsPdfFile,
332
+ };
333
+ } else {
334
+ return undefined;
335
+ }
336
+ }
337
+
338
+ function getHealthCheckSetting(option: OptionValues) {
339
+ const healthCheckEnabled: boolean =
340
+ option.healthCheck || getConfig("enableHealthCheck") === true;
341
+ let healthCheckPort: number;
342
+ if (option.healthCheckPort) {
343
+ healthCheckPort = parseInt(option.healthCheckPort, 10);
344
+ } else {
345
+ healthCheckPort = getConfig<number>("healthCheckPort") || 3000;
346
+ }
347
+ return {
348
+ isHealthCheckEnabled: healthCheckEnabled,
349
+ healthCheckPort: healthCheckPort,
350
+ };
351
+ }
352
+
353
+ function getScanConfiguration(option: OptionValues) {
270
354
  const directoryConfig: DirectoryConfig = {
271
- directory: parentOption.directory || getConfig("directory"),
272
- tempDirectory: parentOption.tempDirectory || getConfig("tempDirectory"),
273
- filePattern: parentOption.pattern || getConfig("pattern"),
355
+ directory: option.directory || getConfig("directory"),
356
+ tempDirectory: option.tempDirectory || getConfig("tempDirectory"),
357
+ filePattern: option.pattern || getConfig("pattern"),
274
358
  };
275
359
 
276
- const configWidth = (
277
- parentOption.width ||
278
- getConfig("width") ||
279
- 0
280
- ).toString();
360
+ const configWidth = (option.width || getConfig("width") || 0).toString();
281
361
  const width =
282
362
  configWidth.toLowerCase() === "max"
283
363
  ? Number.MAX_SAFE_INTEGER
284
364
  : parseInt(configWidth, 10);
285
365
 
286
- const configHeight = (
287
- parentOption.width ||
288
- getConfig("height") ||
289
- "0"
290
- ).toString();
366
+ const configHeight = (option.width || getConfig("height") || "0").toString();
291
367
  const height =
292
368
  configWidth.toLowerCase() === "max"
293
369
  ? Number.MAX_SAFE_INTEGER
294
370
  : parseInt(configHeight, 10);
295
371
 
372
+ const paperlessConfig = getPaperlessConfig(option);
373
+
296
374
  const scanConfig: ScanConfig = {
297
375
  resolution: parseInt(
298
- parentOption.resolution || getConfig("resolution") || "200",
376
+ option.resolution || getConfig("resolution") || "200",
299
377
  10,
300
378
  ),
301
379
  width: width,
302
380
  height: height,
303
381
  directoryConfig,
382
+ paperlessConfig,
304
383
  };
305
384
  return scanConfig;
306
385
  }
@@ -322,6 +401,15 @@ async function main() {
322
401
  "-l, --label <label>",
323
402
  "The label to display on the device (the default is the hostname)",
324
403
  )
404
+ .addOption(
405
+ new Option("--health-check", "Start an http health check endpoint"),
406
+ )
407
+ .addOption(
408
+ new Option(
409
+ "--health-check-port <health-check-port>",
410
+ "Start an http health check endpoint",
411
+ ),
412
+ )
325
413
  .action(async (options, cmd) => {
326
414
  const parentOption = cmd.parent.opts();
327
415
 
@@ -337,6 +425,11 @@ async function main() {
337
425
 
338
426
  const deviceUpPollingInterval = getDeviceUpPollingInterval(parentOption);
339
427
 
428
+ const healthCheckSetting = getHealthCheckSetting(options);
429
+ if (healthCheckSetting.isHealthCheckEnabled) {
430
+ startHealthCheckServer(healthCheckSetting.healthCheckPort);
431
+ }
432
+
340
433
  const scanConfig = getScanConfiguration(options);
341
434
 
342
435
  await listenCmd(registrationConfig, scanConfig, deviceUpPollingInterval);
@@ -369,6 +462,15 @@ async function main() {
369
462
  "Once document are detected to be in the adf, this specify the wait delay in millisecond before triggering the scan",
370
463
  ),
371
464
  )
465
+ .addOption(
466
+ new Option("--health-check", "Start an http health check endpoint"),
467
+ )
468
+ .addOption(
469
+ new Option(
470
+ "--health-check-port <port>",
471
+ "Start an http health check endpoint",
472
+ ),
473
+ )
372
474
  .description(
373
475
  "Automatically trigger a new scan job to this target once paper is detected in the automatic document feeder (adf)",
374
476
  )
@@ -383,6 +485,11 @@ async function main() {
383
485
 
384
486
  const deviceUpPollingInterval = getDeviceUpPollingInterval(parentOption);
385
487
 
488
+ const healthCheckSetting = getHealthCheckSetting(options);
489
+ if (healthCheckSetting.isHealthCheckEnabled) {
490
+ startHealthCheckServer(healthCheckSetting.healthCheckPort);
491
+ }
492
+
386
493
  const scanConfig = getScanConfiguration(options);
387
494
 
388
495
  const adfScanConfig: AdfAutoScanConfig = {
@@ -414,4 +521,5 @@ async function main() {
414
521
  await program.parseAsync(process.argv);
415
522
  }
416
523
 
524
+ console.log(`Current commit ID: ${commitInfo.commitId}`);
417
525
  main().catch((err) => console.log(err));
package/src/listening.ts CHANGED
@@ -6,9 +6,9 @@ import { DeviceCapabilities } from "./DeviceCapabilities";
6
6
  export async function waitScanRequest(compEventURI: string): Promise<boolean> {
7
7
  const waitMax = 50;
8
8
  for (let i = 0; i < waitMax; i++) {
9
- let walkupScanToCompEvent =
9
+ const walkupScanToCompEvent =
10
10
  await HPApi.getWalkupScanToCompEvent(compEventURI);
11
- let message = walkupScanToCompEvent.eventType;
11
+ const message = walkupScanToCompEvent.eventType;
12
12
  if (message === "HostSelected") {
13
13
  // this ok to wait
14
14
  } else if (message === "ScanRequested") {
@@ -0,0 +1,7 @@
1
+ export type PaperlessConfig = {
2
+ postDocumentUrl: string;
3
+ authToken: string;
4
+ keepFiles: boolean;
5
+ groupMultiPageScanIntoAPdf: boolean;
6
+ alwaysSendAsPdfFile: boolean;
7
+ };
@@ -0,0 +1,122 @@
1
+ import fsSync from "fs";
2
+ import FormData from "form-data";
3
+ import axios from "axios";
4
+ import { ScanConfig } from "../scanProcessing";
5
+ import { ScanContent } from "../ScanContent";
6
+ import fs from "fs/promises";
7
+ import { convertToPdf, mergeToPdf } from "../pdfProcessing";
8
+ import { PaperlessConfig } from "./PaperlessConfig";
9
+
10
+ export async function uploadImagesAsSeparateDocumentsToPaperless(
11
+ scanJobContent: ScanContent,
12
+ paperlessConfig: PaperlessConfig,
13
+ ) {
14
+ for (let i = 0; i < scanJobContent.elements.length; ++i) {
15
+ const filePath = scanJobContent.elements[i].path;
16
+ await uploadToPaperless(filePath, paperlessConfig);
17
+ if (!paperlessConfig.keepFiles) {
18
+ await fs.unlink(filePath);
19
+ console.log(
20
+ `Image document ${filePath} has been removed from the filesystem`,
21
+ );
22
+ }
23
+ }
24
+ }
25
+
26
+ export async function convertImagesToPdfAndUploadAsSeparateDocumentsToPaperless(
27
+ scanJobContent: ScanContent,
28
+ paperlessConfig: PaperlessConfig,
29
+ ) {
30
+ for (let i = 0; i < scanJobContent.elements.length; ++i) {
31
+ const pdfFilePath = await convertToPdf(
32
+ scanJobContent.elements[i],
33
+ !paperlessConfig.keepFiles,
34
+ );
35
+ if (pdfFilePath) {
36
+ await uploadToPaperless(pdfFilePath, paperlessConfig);
37
+ await fs.unlink(pdfFilePath);
38
+ } else {
39
+ console.log(
40
+ "Pdf generation has failed, nothing is going to be uploaded to paperless for: " +
41
+ scanJobContent.elements[i].path,
42
+ );
43
+ }
44
+ }
45
+ }
46
+
47
+ export async function mergeToPdfAndUploadAsSingleDocumentToPaperless(
48
+ folder: string,
49
+ scanCount: number,
50
+ scanJobContent: ScanContent,
51
+ scanConfig: ScanConfig,
52
+ scanDate: Date,
53
+ paperlessConfig: PaperlessConfig,
54
+ ) {
55
+ const pdfFilePath = await mergeToPdf(
56
+ folder,
57
+ scanCount,
58
+ scanJobContent,
59
+ scanConfig.directoryConfig.filePattern,
60
+ scanDate,
61
+ !paperlessConfig.keepFiles,
62
+ );
63
+ if (pdfFilePath) {
64
+ await uploadToPaperless(pdfFilePath, paperlessConfig);
65
+ await fs.unlink(pdfFilePath);
66
+ console.log(
67
+ `Pdf document ${pdfFilePath} has been removed from the filesystem`,
68
+ );
69
+ } else {
70
+ console.log(
71
+ "Pdf generation has failed, nothing is going to be uploaded to paperless",
72
+ );
73
+ }
74
+ }
75
+
76
+ export async function uploadPdfToPaperless(
77
+ pdfFilePath: string | null,
78
+ paperlessConfig: PaperlessConfig,
79
+ ) {
80
+ if (pdfFilePath) {
81
+ await uploadToPaperless(pdfFilePath, paperlessConfig);
82
+ if (!paperlessConfig.keepFiles) {
83
+ await fs.unlink(pdfFilePath);
84
+ console.log(
85
+ `Pdf document ${pdfFilePath} has been removed from the filesystem`,
86
+ );
87
+ }
88
+ } else {
89
+ console.log(
90
+ "Pdf generation has failed, nothing is going to be uploaded to paperless",
91
+ );
92
+ }
93
+ }
94
+
95
+ async function uploadToPaperless(
96
+ filePath: string,
97
+ paperlessConfig: PaperlessConfig,
98
+ ): Promise<void> {
99
+ const url = paperlessConfig.postDocumentUrl;
100
+
101
+ const authToken = paperlessConfig.authToken;
102
+
103
+ const fileStream = fsSync.createReadStream(filePath);
104
+
105
+ const form = new FormData();
106
+ form.append("document", fileStream);
107
+
108
+ console.log(`Start uploading to paperless: ${filePath}`);
109
+ try {
110
+ const response = await axios.post(url, form, {
111
+ headers: {
112
+ ...form.getHeaders(),
113
+ Authorization: `Token ${authToken}`,
114
+ },
115
+ });
116
+
117
+ console.log("Document successfully uploaded to paperless:", response.data);
118
+ } catch (error) {
119
+ console.error("Fail to upload document:", error);
120
+ }
121
+ fileStream.close();
122
+ }
@@ -0,0 +1,67 @@
1
+ import { ScanContent, ScanPage } from "./ScanContent";
2
+ import PathHelper from "./PathHelper";
3
+ import fs from "fs/promises";
4
+ import path from "path";
5
+ import { jsPDF } from "jspdf";
6
+
7
+ export async function mergeToPdf(
8
+ folder: string,
9
+ scanCount: number,
10
+ scanJobContent: ScanContent,
11
+ filePattern: string | undefined,
12
+ date: Date,
13
+ deleteFiles: boolean,
14
+ ): Promise<string | null> {
15
+ if (scanJobContent.elements.length > 0) {
16
+ const pdfFilePath: string = PathHelper.getFileForScan(
17
+ folder,
18
+ scanCount,
19
+ filePattern,
20
+ "pdf",
21
+ date,
22
+ );
23
+ await createPdfFrom(scanJobContent, pdfFilePath);
24
+ if (deleteFiles) {
25
+ await Promise.all(scanJobContent.elements.map((e) => fs.unlink(e.path)));
26
+ }
27
+ return pdfFilePath;
28
+ }
29
+ console.log(`No page available to build a pdf file`);
30
+ return null;
31
+ }
32
+
33
+ export async function convertToPdf(
34
+ scanPage: ScanPage,
35
+ deleteFile: boolean,
36
+ ): Promise<string | null> {
37
+ const fileName = path.basename(scanPage.path, path.extname(scanPage.path));
38
+ const pdfFilePath = path.join(path.dirname(scanPage.path), `${fileName}.pdf`);
39
+
40
+ await createPdfFrom({ elements: [scanPage] }, pdfFilePath);
41
+ if (deleteFile) {
42
+ await fs.unlink(scanPage.path);
43
+ }
44
+ return pdfFilePath;
45
+ }
46
+
47
+ export async function createPdfFrom(
48
+ scanContent: ScanContent,
49
+ destination: string,
50
+ ) {
51
+ let doc: jsPDF | null = null;
52
+ for (const element of scanContent.elements) {
53
+ const widthInInches = element.width / element.xResolution;
54
+ const heightInInches = element.height / element.yResolution;
55
+ const format = [widthInInches, heightInInches];
56
+
57
+ if (doc == null) {
58
+ doc = new jsPDF({ unit: "in", floatPrecision: 3, format });
59
+ } else {
60
+ doc.addPage(format);
61
+ }
62
+
63
+ const imageByteBuffer = await fs.readFile(element.path);
64
+ doc.addImage(imageByteBuffer, "JPEG", 0, 0, widthInInches, heightInInches);
65
+ }
66
+ doc?.save(destination);
67
+ }
@@ -0,0 +1,91 @@
1
+ import { ScanContent } from "./ScanContent";
2
+ import { mergeToPdf } from "./pdfProcessing";
3
+ import {
4
+ convertImagesToPdfAndUploadAsSeparateDocumentsToPaperless,
5
+ mergeToPdfAndUploadAsSingleDocumentToPaperless,
6
+ uploadImagesAsSeparateDocumentsToPaperless,
7
+ uploadPdfToPaperless,
8
+ } from "./paperless/paperless";
9
+ import { ScanConfig } from "./scanProcessing";
10
+
11
+ export async function postProcessing(
12
+ scanConfig: ScanConfig,
13
+ folder: string,
14
+ tempFolder: string,
15
+ scanCount: number,
16
+ scanJobContent: ScanContent,
17
+ scanDate: Date,
18
+ toPdf: boolean,
19
+ ) {
20
+ const paperlessConfig = scanConfig.paperlessConfig;
21
+ if (toPdf) {
22
+ const pdfFilePath = await mergeToPdf(
23
+ paperlessConfig ? tempFolder : folder,
24
+ scanCount,
25
+ scanJobContent,
26
+ scanConfig.directoryConfig.filePattern,
27
+ scanDate,
28
+ true,
29
+ );
30
+ displayPdfScan(pdfFilePath, scanJobContent);
31
+ if (paperlessConfig) {
32
+ await uploadPdfToPaperless(pdfFilePath, paperlessConfig);
33
+ }
34
+ } else {
35
+ displayJpegScan(scanJobContent);
36
+ if (paperlessConfig) {
37
+ if (paperlessConfig.groupMultiPageScanIntoAPdf) {
38
+ await mergeToPdfAndUploadAsSingleDocumentToPaperless(
39
+ folder,
40
+ scanCount,
41
+ scanJobContent,
42
+ scanConfig,
43
+ scanDate,
44
+ paperlessConfig,
45
+ );
46
+ } else {
47
+ if (paperlessConfig.alwaysSendAsPdfFile) {
48
+ await convertImagesToPdfAndUploadAsSeparateDocumentsToPaperless(
49
+ scanJobContent,
50
+ paperlessConfig,
51
+ );
52
+ } else {
53
+ await uploadImagesAsSeparateDocumentsToPaperless(
54
+ scanJobContent,
55
+ paperlessConfig,
56
+ );
57
+ }
58
+ }
59
+ }
60
+ }
61
+ }
62
+
63
+ function displayPdfScan(
64
+ pdfFilePath: string | null,
65
+ scanJobContent: ScanContent,
66
+ ) {
67
+ if (pdfFilePath === null) {
68
+ console.log(`Pdf generated has not been generated`);
69
+ return;
70
+ }
71
+ console.log(
72
+ `The following page(s) have been rendered inside '${pdfFilePath}': `,
73
+ );
74
+ scanJobContent.elements.forEach((e) =>
75
+ console.log(
76
+ `\t- page ${e.pageNumber.toString().padStart(3, " ")} - ${e.width}x${
77
+ e.height
78
+ }`,
79
+ ),
80
+ );
81
+ }
82
+
83
+ function displayJpegScan(scanJobContent: ScanContent) {
84
+ scanJobContent.elements.forEach((e) =>
85
+ console.log(
86
+ `\t- page ${e.pageNumber.toString().padStart(3, " ")} - ${e.width}x${
87
+ e.height
88
+ } - ${e.path}`,
89
+ ),
90
+ );
91
+ }