node-hp-scan-to 1.0.1 → 1.2.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 (68) hide show
  1. package/README.md +92 -11
  2. package/dist/Destination.d.ts +8 -7
  3. package/dist/Destination.js +115 -84
  4. package/dist/Destination.js.map +1 -1
  5. package/dist/Event.d.ts +21 -17
  6. package/dist/Event.js +46 -30
  7. package/dist/Event.js.map +1 -1
  8. package/dist/EventTable.d.ts +11 -11
  9. package/dist/EventTable.js +26 -26
  10. package/dist/EventTable.js.map +1 -1
  11. package/dist/HPApi.d.ts +42 -29
  12. package/dist/HPApi.js +528 -333
  13. package/dist/HPApi.js.map +1 -1
  14. package/dist/Job.d.ts +36 -24
  15. package/dist/Job.js +94 -62
  16. package/dist/Job.js.map +1 -1
  17. package/dist/JpegUtil.d.ts +26 -0
  18. package/dist/JpegUtil.js +238 -0
  19. package/dist/JpegUtil.js.map +1 -0
  20. package/dist/PathHelper.d.ts +5 -0
  21. package/dist/PathHelper.js +79 -0
  22. package/dist/PathHelper.js.map +1 -0
  23. package/dist/ScanContent.d.ts +12 -0
  24. package/dist/ScanContent.js +82 -0
  25. package/dist/ScanContent.js.map +1 -0
  26. package/dist/ScanJobSettings.d.ts +6 -6
  27. package/dist/ScanJobSettings.js +95 -94
  28. package/dist/ScanJobSettings.js.map +1 -1
  29. package/dist/ScanStatus.d.ts +18 -18
  30. package/dist/ScanStatus.js +35 -29
  31. package/dist/ScanStatus.js.map +1 -1
  32. package/dist/WalkupScanDestination.d.ts +24 -24
  33. package/dist/WalkupScanDestination.js +40 -40
  34. package/dist/WalkupScanDestination.js.map +1 -1
  35. package/dist/WalkupScanDestinations.d.ts +11 -11
  36. package/dist/WalkupScanDestinations.js +26 -26
  37. package/dist/WalkupScanDestinations.js.map +1 -1
  38. package/dist/WalkupScanToCompDestination.d.ts +26 -0
  39. package/dist/WalkupScanToCompDestination.js +44 -0
  40. package/dist/WalkupScanToCompDestination.js.map +1 -0
  41. package/dist/WalkupScanToCompDestinations.d.ts +11 -0
  42. package/dist/WalkupScanToCompDestinations.js +27 -0
  43. package/dist/WalkupScanToCompDestinations.js.map +1 -0
  44. package/dist/WalkupScanToCompEvent.d.ts +10 -0
  45. package/dist/WalkupScanToCompEvent.js +17 -0
  46. package/dist/WalkupScanToCompEvent.js.map +1 -0
  47. package/dist/index.d.ts +2 -2
  48. package/dist/index.js +630 -292
  49. package/dist/index.js.map +1 -1
  50. package/nodemon.json +5 -5
  51. package/package.json +72 -57
  52. package/src/Destination.ts +63 -45
  53. package/src/Event.ts +45 -31
  54. package/src/EventTable.ts +25 -25
  55. package/src/HPApi.ts +365 -222
  56. package/src/Job.ts +100 -62
  57. package/src/JpegUtil.ts +319 -0
  58. package/src/PathHelper.ts +44 -0
  59. package/src/ScanContent.ts +34 -0
  60. package/src/ScanJobSettings.ts +55 -55
  61. package/src/ScanStatus.ts +36 -31
  62. package/src/WalkupScanDestination.ts +46 -44
  63. package/src/WalkupScanDestinations.ts +29 -27
  64. package/src/WalkupScanToCompDestination.ts +55 -0
  65. package/src/WalkupScanToCompDestinations.ts +34 -0
  66. package/src/WalkupScanToCompEvent.ts +18 -0
  67. package/src/index.ts +555 -205
  68. package/tsconfig.json +34 -0
package/src/HPApi.ts CHANGED
@@ -1,222 +1,365 @@
1
- "use strict";
2
-
3
- import WalkupScanDestination, {WalkupScanDestinationData} from "./WalkupScanDestination";
4
-
5
- import util from "util";
6
- import fs from "fs";
7
- import axios from "axios";
8
- import url from "url";
9
- import xml2js from "xml2js";
10
- import EventTable, {EventTableData} from "./EventTable";
11
- import Job, {JobData} from "./Job";
12
- import ScanStatus, {ScanStatusData} from "./ScanStatus";
13
- import WalkupScanDestinations, {WalkupScanDestinationsData} from "./WalkupScanDestinations";
14
- import ScanJobSettings from "./ScanJobSettings";
15
- import Destination from "./Destination";
16
-
17
- const parser = new xml2js.Parser();
18
- const parseString = util.promisify(parser.parseString);
19
- let printerIP = "192.168.1.11";
20
-
21
- export default class HPApi {
22
- static setPrinterIP(ip: string) {
23
- printerIP = ip;
24
- }
25
-
26
-
27
- static async getWalkupScanDestinations(): Promise<WalkupScanDestinations> {
28
- const response = await axios({
29
- baseURL: `http://${printerIP}`,
30
- url: "/WalkupScan/WalkupScanDestinations",
31
- method: "GET",
32
- responseType: "text"
33
- });
34
-
35
- if (response.status !== 200) {
36
- throw new Error(response.statusText);
37
- } else {
38
- const parsed = await parseString(response.data) as WalkupScanDestinationsData;
39
- return new WalkupScanDestinations(parsed);
40
- }
41
- }
42
-
43
- static async removeDestination(walkupScanDestination : WalkupScanDestination) {
44
- let urlInfo = url.parse(walkupScanDestination.resourceURI);
45
-
46
- const response = await axios({
47
- baseURL: `http://${printerIP}`,
48
- url: urlInfo.pathname,
49
- method: "DELETE",
50
- responseType: "text"
51
- });
52
- if (response.status === 204) {
53
- return true;
54
- } else {
55
- throw response;
56
- }
57
- }
58
-
59
- static async registerDestination(destination: Destination) {
60
- const xml = await destination.toXML();
61
- const response = await axios({
62
- baseURL: `http://${printerIP}`,
63
- url: "/WalkupScan/WalkupScanDestinations",
64
- method: "POST",
65
- headers: { "Content-Type": "text/xml" },
66
- data: xml,
67
- responseType: "text"
68
- });
69
-
70
- if (response.status === 201) {
71
- return response.headers.location;
72
- } else {
73
- throw response;
74
- }
75
- }
76
-
77
- static async getEvents(etag = "", timeout = 0): Promise<{etag: string, eventTable: EventTable}> {
78
- let url = this.appendTimeout(timeout, "/EventMgmt/EventTable");
79
-
80
- let headers = this.placeETagHeader(etag, {});
81
-
82
- let response;
83
- try {
84
- response = await axios({
85
- baseURL: `http://${printerIP}`,
86
- url: url,
87
- method: "GET",
88
- responseType: "text",
89
- headers: headers
90
- });
91
- } catch (error) {
92
- response = error.response;
93
- if (response.status === 304) {
94
- return {
95
- etag: etag,
96
- eventTable: new EventTable({})
97
- };
98
- }
99
- throw error;
100
- }
101
-
102
- const parsed = await parseString(response.data);
103
- return {
104
- etag: response.headers["etag"],
105
- eventTable: new EventTable(parsed as EventTableData)
106
- };
107
- }
108
-
109
- static placeETagHeader(etag: string, headers: object) {
110
- if (etag !== "") {
111
- headers = {
112
- "If-None-Match": etag
113
- };
114
- }
115
- return headers;
116
- }
117
-
118
- static appendTimeout(
119
- timeout: number | null = null,
120
- url: string
121
- ) : string {
122
- if (timeout == null) {
123
- timeout = 1200;
124
- }
125
- if (timeout > 0) {
126
- url += "?timeout=" + timeout;
127
- }
128
- return url;
129
- }
130
-
131
- static async getDestination(destinationURL : string) {
132
- const response = await axios({
133
- url: destinationURL,
134
- method: "GET",
135
- responseType: "text"
136
- });
137
-
138
- if (response.status !== 200) {
139
- throw response;
140
- } else {
141
- const parsed = await parseString(response.data) as WalkupScanDestinationData;
142
- return new WalkupScanDestination(parsed);
143
- }
144
- }
145
-
146
- static async getScanStatus() {
147
- const response = await axios({
148
- baseURL: `http://${printerIP}`,
149
- url: "/Scan/Status",
150
- method: "GET",
151
- responseType: "text"
152
- });
153
-
154
- if (response.status !== 200) {
155
- throw response;
156
- } else {
157
- const parsed = await parseString(response.data) as ScanStatusData;
158
- return new ScanStatus(parsed);
159
- }
160
- }
161
-
162
- static delay(t: number) {
163
- return new Promise(function(resolve) {
164
- setTimeout(resolve, t);
165
- });
166
- }
167
-
168
- static async postJob(job : ScanJobSettings) {
169
- await HPApi.delay(500);
170
- const xml = await job.toXML();
171
- const response = await axios({
172
- baseURL: `http://${printerIP}:8080`,
173
- url: "/Scan/Jobs",
174
- method: "POST",
175
- headers: { "Content-Type": "text/xml" },
176
- data: xml,
177
- responseType: "text"
178
- });
179
-
180
- if (response.status === 201) {
181
- return response.headers.location;
182
- } else {
183
- throw response;
184
- }
185
- }
186
-
187
- /**
188
- * @param jobURL
189
- * @return {Promise<Job|*>}
190
- */
191
- static async getJob(jobURL :string) {
192
- const response = await axios({
193
- url: jobURL,
194
- method: "GET",
195
- responseType: "text"
196
- });
197
-
198
- if (response.status !== 200) {
199
- throw response;
200
- } else {
201
- const parsed = await parseString(response.data) as JobData;
202
- return new Job(parsed);
203
- }
204
- }
205
-
206
- static async downloadPage(binaryURL: string, destination: string) {
207
- const response = await axios({
208
- baseURL: `http://${printerIP}:8080`,
209
- url: binaryURL,
210
- method: "GET",
211
- responseType: "stream"
212
- });
213
-
214
- response.data.pipe(fs.createWriteStream(destination));
215
-
216
- return new Promise((resolve, reject) => {
217
- response.data
218
- .on("end", () => resolve(destination))
219
- .on("error", (error: Error) => reject(error));
220
- });
221
- }
222
- }
1
+ "use strict";
2
+
3
+ import WalkupScanDestination, {
4
+ WalkupScanDestinationData,
5
+ } from "./WalkupScanDestination";
6
+ import WalkupScanToCompDestination, {
7
+ WalkupScanToCompDestinationData,
8
+ } from "./WalkupScanToCompDestination";
9
+ import { promisify } from "util";
10
+ import fs from "fs";
11
+ import axios, {
12
+ AxiosError,
13
+ AxiosRequestConfig,
14
+ AxiosRequestHeaders,
15
+ AxiosResponse,
16
+ } from "axios";
17
+ import { URL } from "url";
18
+ import { Parser } from "xml2js";
19
+ import * as stream from 'stream/promises';
20
+ import EventTable, { EventTableData } from "./EventTable";
21
+ import Job, { JobData } from "./Job";
22
+ import ScanStatus, { ScanStatusData } from "./ScanStatus";
23
+ import WalkupScanDestinations, {
24
+ WalkupScanDestinationsData,
25
+ } from "./WalkupScanDestinations";
26
+ import WalkupScanToCompDestinations, {
27
+ WalkupScanToCompDestinationsData,
28
+ } from "./WalkupScanToCompDestinations";
29
+ import ScanJobSettings from "./ScanJobSettings";
30
+ import Destination from "./Destination";
31
+ import { Stream } from "stream";
32
+ import WalkupScanToCompEvent, {
33
+ WalkupScanToCompEventData,
34
+ } from "./WalkupScanToCompEvent";
35
+
36
+ const parser = new Parser();
37
+ const parseString = promisify<string, any>(parser.parseString);
38
+ let printerIP = "192.168.1.11";
39
+ let debug = false;
40
+ let callCount = 0;
41
+
42
+ export default class HPApi {
43
+ static setPrinterIP(ip: string) {
44
+ printerIP = ip;
45
+ }
46
+
47
+ static setDebug(dbg: boolean) {
48
+ debug = dbg;
49
+ }
50
+
51
+ private static logDebug(callId: number, isRequest: boolean, msg: any) {
52
+ if (debug) {
53
+ const id = String(callId).padStart(4, "0");
54
+ const content = typeof msg === "string" ? msg : JSON.stringify(msg);
55
+ console.log(id + (isRequest ? " -> " : " <- ") + content);
56
+ }
57
+ }
58
+
59
+ private static async callAxios(request: AxiosRequestConfig) {
60
+ callCount++;
61
+ HPApi.logDebug(callCount, true, request);
62
+ try {
63
+ const response = (await axios(request)) as AxiosResponse<string>;
64
+ HPApi.logDebug(callCount, false, {
65
+ status: response.status,
66
+ data: response.data,
67
+ headers: response.headers,
68
+ statusText: response.statusText,
69
+ });
70
+ return response;
71
+ } catch (error) {
72
+ const axiosError = error as AxiosError;
73
+
74
+ if (axiosError.isAxiosError) {
75
+ HPApi.logDebug(callCount, false, {
76
+ status: axiosError.response?.status,
77
+ data: axiosError.response?.data,
78
+ headers: axiosError.response?.headers,
79
+ statusText: axiosError.response?.statusText,
80
+ });
81
+ }
82
+ throw error;
83
+ }
84
+ }
85
+
86
+ static async getWalkupScanDestinations(): Promise<WalkupScanDestinations> {
87
+ const response = await HPApi.callAxios({
88
+ baseURL: `http://${printerIP}`,
89
+ url: "/WalkupScan/WalkupScanDestinations",
90
+ method: "GET",
91
+ responseType: "text",
92
+ });
93
+
94
+ if (response.status !== 200) {
95
+ throw new Error(response.statusText);
96
+ } else {
97
+ const parsed = (await parseString(
98
+ response.data
99
+ )) as WalkupScanDestinationsData;
100
+ return new WalkupScanDestinations(parsed);
101
+ }
102
+ }
103
+
104
+ static async getWalkupScanToCompDestinations(): Promise<WalkupScanToCompDestinations> {
105
+ const response = await HPApi.callAxios({
106
+ baseURL: `http://${printerIP}`,
107
+ url: "/WalkupScanToComp/WalkupScanToCompDestinations",
108
+ method: "GET",
109
+ responseType: "text",
110
+ });
111
+
112
+ if (response.status !== 200) {
113
+ throw new Error(response.statusText);
114
+ } else {
115
+ const parsed = (await parseString(
116
+ response.data
117
+ )) as WalkupScanToCompDestinationsData;
118
+ return new WalkupScanToCompDestinations(parsed);
119
+ }
120
+ }
121
+
122
+ static async getWalkupScanToCompCaps(): Promise<boolean> {
123
+ return HPApi.callAxios({
124
+ baseURL: `http://${printerIP}`,
125
+ url: "/WalkupScanToComp/WalkupScanToCompCaps",
126
+ method: "GET",
127
+ responseType: "text",
128
+ }).then(
129
+ (response) => response.status == 200,
130
+ () => false
131
+ );
132
+ }
133
+
134
+ static async getWalkupScanToCompEvent(compEventURI: string): Promise<WalkupScanToCompEvent> {
135
+ const response = await HPApi.callAxios({
136
+ baseURL: `http://${printerIP}`,
137
+ url: compEventURI,
138
+ method: "GET",
139
+ responseType: "text",
140
+ });
141
+
142
+ if (response.status !== 200) {
143
+ throw response;
144
+ } else {
145
+ return HPApi.createWalkupScanToCompEvent(response.data);
146
+ }
147
+ }
148
+
149
+ static async removeDestination(walkupScanDestination: WalkupScanDestination) {
150
+ let urlInfo = new URL(walkupScanDestination.resourceURI);
151
+
152
+ if (urlInfo.pathname === null) {
153
+ throw new Error(
154
+ `invalid walkupScanDestination.resourceURI: ${walkupScanDestination.resourceURI}`
155
+ );
156
+ }
157
+
158
+ const response = await HPApi.callAxios({
159
+ baseURL: `http://${printerIP}`,
160
+ url: urlInfo.pathname,
161
+ method: "DELETE",
162
+ responseType: "text",
163
+ });
164
+ if (response.status === 204) {
165
+ return true;
166
+ } else {
167
+ throw response;
168
+ }
169
+ }
170
+
171
+ static async registerDestination(destination: Destination, toComp: boolean) {
172
+ let xml = await destination.toXML();
173
+ let url = "/WalkupScan/WalkupScanDestinations";
174
+ if (toComp) {
175
+ url = "/WalkupScanToComp/WalkupScanToCompDestinations";
176
+ }
177
+ const response = await HPApi.callAxios({
178
+ baseURL: `http://${printerIP}`,
179
+ url: url,
180
+ method: "POST",
181
+ headers: { "Content-Type": "text/xml" },
182
+ data: xml,
183
+ responseType: "text",
184
+ });
185
+
186
+ if (response.status === 201) {
187
+ return new URL(response.headers.location).pathname;
188
+ } else {
189
+ throw response;
190
+ }
191
+ }
192
+
193
+ static async getEvents(
194
+ etag = "",
195
+ timeout = 0
196
+ ): Promise<{ etag: string; eventTable: EventTable }> {
197
+ let url = this.appendTimeout("/EventMgmt/EventTable", timeout);
198
+
199
+ let headers = this.placeETagHeader(etag, {});
200
+
201
+ let response: AxiosResponse<string>;
202
+ try {
203
+ response = await HPApi.callAxios({
204
+ baseURL: `http://${printerIP}`,
205
+ url: url,
206
+ method: "GET",
207
+ responseType: "text",
208
+ headers: headers,
209
+ });
210
+ } catch (error) {
211
+ const axiosError = error as AxiosError;
212
+
213
+ if (!axiosError.isAxiosError) throw error;
214
+
215
+ if (axiosError.response?.status === 304) {
216
+ return {
217
+ etag: etag,
218
+ eventTable: new EventTable({}),
219
+ };
220
+ }
221
+ throw error;
222
+ }
223
+
224
+ const parsed = await parseString(response.data);
225
+ return {
226
+ etag: response.headers["etag"],
227
+ eventTable: new EventTable(parsed as EventTableData),
228
+ };
229
+ }
230
+
231
+ static placeETagHeader(etag: string, headers: AxiosRequestHeaders) {
232
+ if (etag !== "") {
233
+ headers = {
234
+ "If-None-Match": etag,
235
+ };
236
+ }
237
+ return headers;
238
+ }
239
+
240
+ static appendTimeout(url: string, timeout: number | null = null): string {
241
+ if (timeout == null) {
242
+ timeout = 1200;
243
+ }
244
+ if (timeout > 0) {
245
+ url += "?timeout=" + timeout;
246
+ }
247
+ return url;
248
+ }
249
+
250
+ static async getDestination(destinationURL: string) {
251
+ const response = await HPApi.callAxios({
252
+ baseURL: `http://${printerIP}`,
253
+ url: destinationURL,
254
+ method: "GET",
255
+ responseType: "text",
256
+ });
257
+
258
+ if (response.status !== 200) {
259
+ throw response;
260
+ } else {
261
+ const content = response.data;
262
+ if (destinationURL.includes("WalkupScanToComp")) {
263
+ return this.createWalkupScanToCompDestination(content);
264
+ } else {
265
+ return this.createWalkupScanDestination(content);
266
+ }
267
+ }
268
+ }
269
+
270
+ static async createWalkupScanDestination(content: string) {
271
+ const parsed = (await parseString(content)) as WalkupScanDestinationData;
272
+ return new WalkupScanDestination(parsed);
273
+ }
274
+
275
+ static async createWalkupScanToCompDestination(content: string) {
276
+ const parsed = (await parseString(
277
+ content
278
+ )) as WalkupScanToCompDestinationData;
279
+ return new WalkupScanToCompDestination(parsed);
280
+ }
281
+
282
+ static async createWalkupScanToCompEvent(content: string) {
283
+ const parsed = (await parseString(content)) as WalkupScanToCompEventData;
284
+ return new WalkupScanToCompEvent(parsed);
285
+ }
286
+
287
+ static async getScanStatus() {
288
+ const response = await HPApi.callAxios({
289
+ baseURL: `http://${printerIP}`,
290
+ url: "/Scan/Status",
291
+ method: "GET",
292
+ responseType: "text",
293
+ });
294
+
295
+ if (response.status !== 200) {
296
+ throw response;
297
+ } else {
298
+ const parsed = (await parseString(response.data)) as ScanStatusData;
299
+ return new ScanStatus(parsed);
300
+ }
301
+ }
302
+
303
+ static delay(t: number) {
304
+ return new Promise(function (resolve) {
305
+ setTimeout(resolve, t);
306
+ });
307
+ }
308
+
309
+ static async postJob(job: ScanJobSettings) {
310
+ await HPApi.delay(500);
311
+ const xml = await job.toXML();
312
+ const response = await HPApi.callAxios({
313
+ baseURL: `http://${printerIP}:8080`,
314
+ url: "/Scan/Jobs",
315
+ method: "POST",
316
+ headers: { "Content-Type": "text/xml" },
317
+ data: xml,
318
+ responseType: "text",
319
+ });
320
+
321
+ if (response.status === 201) {
322
+ return response.headers.location;
323
+ } else {
324
+ throw response;
325
+ }
326
+ }
327
+
328
+ /**
329
+ * @param jobURL
330
+ * @return {Promise<Job|*>}
331
+ */
332
+ static async getJob(jobURL: string) {
333
+ const response = await HPApi.callAxios({
334
+ url: jobURL,
335
+ method: "GET",
336
+ responseType: "text",
337
+ });
338
+
339
+ if (response.status !== 200) {
340
+ throw response;
341
+ } else {
342
+ const parsed = (await parseString(response.data)) as JobData;
343
+ return new Job(parsed);
344
+ }
345
+ }
346
+
347
+ static async downloadPage(
348
+ binaryURL: string,
349
+ destination: string
350
+ ): Promise<string> {
351
+ const { data }: AxiosResponse<Stream> = await axios.request<Stream>({
352
+ baseURL: `http://${printerIP}:8080`,
353
+ url: binaryURL,
354
+ method: "GET",
355
+ responseType: "stream",
356
+ });
357
+
358
+ const destinationFileStream = fs.createWriteStream(destination);
359
+ data.pipe(destinationFileStream);
360
+
361
+ await stream.finished(destinationFileStream);
362
+
363
+ return destination;
364
+ }
365
+ }