@ecobridge.xyz/devicemanager 3.0.2 → 3.1.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.
@@ -1,284 +1,987 @@
1
- import * as plugins from '../plugins.js';
2
1
  /**
3
- * IPP protocol wrapper using the ipp npm package
2
+ * Clean IPP Protocol Implementation
3
+ * RFC 8010 (Encoding) and RFC 8011 (Model)
4
+ *
5
+ * This is a from-scratch implementation with proper capability detection,
6
+ * document format negotiation, and clean attribute parsing.
4
7
  */
5
- export class IppProtocol {
6
- printerUrl;
7
- printer;
8
- constructor(address, port, path = '/ipp/print') {
9
- this.printerUrl = `ipp://${address}:${port}${path}`;
10
- this.printer = plugins.ipp.Printer(this.printerUrl);
8
+ // ============================================================================
9
+ // Constants
10
+ // ============================================================================
11
+ /** IPP Version */
12
+ const IPP_VERSION = {
13
+ V1_1: 0x0101,
14
+ V2_0: 0x0200,
15
+ };
16
+ /** IPP Operations */
17
+ const IPP_OPERATION = {
18
+ PRINT_JOB: 0x0002,
19
+ VALIDATE_JOB: 0x0004,
20
+ CANCEL_JOB: 0x0008,
21
+ GET_JOB_ATTRIBUTES: 0x0009,
22
+ GET_JOBS: 0x000a,
23
+ GET_PRINTER_ATTRIBUTES: 0x000b,
24
+ };
25
+ /** IPP Status Codes */
26
+ const IPP_STATUS = {
27
+ // Successful
28
+ SUCCESSFUL_OK: 0x0000,
29
+ SUCCESSFUL_OK_IGNORED_ATTRIBUTES: 0x0001,
30
+ SUCCESSFUL_OK_CONFLICTING_ATTRIBUTES: 0x0002,
31
+ // Client errors
32
+ CLIENT_ERROR_BAD_REQUEST: 0x0400,
33
+ CLIENT_ERROR_FORBIDDEN: 0x0401,
34
+ CLIENT_ERROR_NOT_AUTHENTICATED: 0x0402,
35
+ CLIENT_ERROR_NOT_AUTHORIZED: 0x0403,
36
+ CLIENT_ERROR_NOT_POSSIBLE: 0x0404,
37
+ CLIENT_ERROR_TIMEOUT: 0x0405,
38
+ CLIENT_ERROR_NOT_FOUND: 0x0406,
39
+ CLIENT_ERROR_DOCUMENT_FORMAT_NOT_SUPPORTED: 0x040a,
40
+ // Server errors
41
+ SERVER_ERROR_INTERNAL: 0x0500,
42
+ SERVER_ERROR_OPERATION_NOT_SUPPORTED: 0x0501,
43
+ SERVER_ERROR_SERVICE_UNAVAILABLE: 0x0502,
44
+ SERVER_ERROR_DEVICE_ERROR: 0x0504,
45
+ SERVER_ERROR_NOT_ACCEPTING_JOBS: 0x0506,
46
+ SERVER_ERROR_BUSY: 0x0507,
47
+ };
48
+ /** Delimiter Tags */
49
+ const TAG_DELIMITER = {
50
+ OPERATION_ATTRIBUTES: 0x01,
51
+ JOB_ATTRIBUTES: 0x02,
52
+ END_OF_ATTRIBUTES: 0x03,
53
+ PRINTER_ATTRIBUTES: 0x04,
54
+ UNSUPPORTED_ATTRIBUTES: 0x05,
55
+ };
56
+ /** Value Tags */
57
+ const TAG_VALUE = {
58
+ // Out-of-band
59
+ UNSUPPORTED: 0x10,
60
+ UNKNOWN: 0x12,
61
+ NO_VALUE: 0x13,
62
+ // Integer
63
+ INTEGER: 0x21,
64
+ BOOLEAN: 0x22,
65
+ ENUM: 0x23,
66
+ // Octet string
67
+ OCTET_STRING: 0x30,
68
+ DATE_TIME: 0x31,
69
+ RESOLUTION: 0x32,
70
+ RANGE_OF_INTEGER: 0x33,
71
+ BEG_COLLECTION: 0x34,
72
+ TEXT_WITH_LANGUAGE: 0x35,
73
+ NAME_WITH_LANGUAGE: 0x36,
74
+ END_COLLECTION: 0x37,
75
+ // Character string
76
+ TEXT_WITHOUT_LANGUAGE: 0x41,
77
+ NAME_WITHOUT_LANGUAGE: 0x42,
78
+ KEYWORD: 0x44,
79
+ URI: 0x45,
80
+ URI_SCHEME: 0x46,
81
+ CHARSET: 0x47,
82
+ NATURAL_LANGUAGE: 0x48,
83
+ MIME_MEDIA_TYPE: 0x49,
84
+ MEMBER_ATTR_NAME: 0x4a,
85
+ };
86
+ /** Job States */
87
+ const JOB_STATE = {
88
+ PENDING: 3,
89
+ PENDING_HELD: 4,
90
+ PROCESSING: 5,
91
+ PROCESSING_STOPPED: 6,
92
+ CANCELED: 7,
93
+ ABORTED: 8,
94
+ COMPLETED: 9,
95
+ };
96
+ /** Printer States */
97
+ const PRINTER_STATE = {
98
+ IDLE: 3,
99
+ PROCESSING: 4,
100
+ STOPPED: 5,
101
+ };
102
+ // ============================================================================
103
+ // IPP Message Encoder
104
+ // ============================================================================
105
+ class IppEncoder {
106
+ buffer = [];
107
+ encode(message) {
108
+ this.buffer = [];
109
+ // Version
110
+ this.writeInt16(message.version);
111
+ // Operation ID or Status Code
112
+ this.writeInt16(message.operationIdOrStatusCode);
113
+ // Request ID
114
+ this.writeInt32(message.requestId);
115
+ // Operation attributes (always required)
116
+ this.writeDelimiter(TAG_DELIMITER.OPERATION_ATTRIBUTES);
117
+ this.writeAttributes(message.operationAttributes);
118
+ // Job attributes (optional)
119
+ if (message.jobAttributes && Object.keys(message.jobAttributes).length > 0) {
120
+ this.writeDelimiter(TAG_DELIMITER.JOB_ATTRIBUTES);
121
+ this.writeAttributes(message.jobAttributes);
122
+ }
123
+ // End of attributes
124
+ this.writeDelimiter(TAG_DELIMITER.END_OF_ATTRIBUTES);
125
+ // Data (for Print-Job)
126
+ const headerBuffer = Buffer.from(this.buffer);
127
+ if (message.data) {
128
+ return Buffer.concat([headerBuffer, message.data]);
129
+ }
130
+ return headerBuffer;
11
131
  }
12
- /**
13
- * Get printer attributes/capabilities
14
- */
15
- async getAttributes() {
16
- return new Promise((resolve, reject) => {
17
- this.printer.execute('Get-Printer-Attributes', null, (err, res) => {
18
- if (err) {
19
- reject(err);
20
- return;
21
- }
22
- try {
23
- const attrs = res['printer-attributes-tag'] || {};
24
- resolve(this.parseCapabilities(attrs));
25
- }
26
- catch (parseErr) {
27
- reject(parseErr);
28
- }
29
- });
30
- });
132
+ writeInt8(value) {
133
+ this.buffer.push(value & 0xff);
31
134
  }
32
- /**
33
- * Print a document
34
- */
35
- async print(data, options) {
36
- const msg = this.buildPrintMessage(options);
37
- return new Promise((resolve, reject) => {
38
- this.printer.execute('Print-Job', { ...msg, data }, (err, res) => {
39
- if (err) {
40
- reject(err);
41
- return;
42
- }
43
- try {
44
- const jobAttrs = res['job-attributes-tag'] || {};
45
- resolve(this.parseJobInfo(jobAttrs));
46
- }
47
- catch (parseErr) {
48
- reject(parseErr);
49
- }
50
- });
51
- });
135
+ writeInt16(value) {
136
+ this.buffer.push((value >> 8) & 0xff);
137
+ this.buffer.push(value & 0xff);
52
138
  }
53
- /**
54
- * Get all jobs
55
- */
56
- async getJobs() {
57
- return new Promise((resolve, reject) => {
58
- this.printer.execute('Get-Jobs', {
59
- 'operation-attributes-tag': {
60
- 'requesting-user-name': 'devicemanager',
61
- 'which-jobs': 'not-completed',
62
- },
63
- }, (err, res) => {
64
- if (err) {
65
- reject(err);
66
- return;
139
+ writeInt32(value) {
140
+ this.buffer.push((value >> 24) & 0xff);
141
+ this.buffer.push((value >> 16) & 0xff);
142
+ this.buffer.push((value >> 8) & 0xff);
143
+ this.buffer.push(value & 0xff);
144
+ }
145
+ writeString(value) {
146
+ const bytes = Buffer.from(value, 'utf-8');
147
+ this.writeInt16(bytes.length);
148
+ for (const byte of bytes) {
149
+ this.buffer.push(byte);
150
+ }
151
+ }
152
+ writeDelimiter(tag) {
153
+ this.writeInt8(tag);
154
+ }
155
+ writeAttributes(attrs) {
156
+ for (const [name, value] of Object.entries(attrs)) {
157
+ this.writeAttribute(name, value);
158
+ }
159
+ }
160
+ writeAttribute(name, value) {
161
+ if (Array.isArray(value)) {
162
+ // Multi-value attribute
163
+ for (let i = 0; i < value.length; i++) {
164
+ this.writeSingleAttribute(i === 0 ? name : '', value[i], name);
165
+ }
166
+ }
167
+ else {
168
+ this.writeSingleAttribute(name, value, name);
169
+ }
170
+ }
171
+ writeSingleAttribute(name, value, originalName) {
172
+ const tag = this.inferTag(originalName || name, value);
173
+ this.writeInt8(tag);
174
+ // Name
175
+ const nameBytes = Buffer.from(name, 'utf-8');
176
+ this.writeInt16(nameBytes.length);
177
+ for (const byte of nameBytes) {
178
+ this.buffer.push(byte);
179
+ }
180
+ // Value
181
+ this.writeValue(tag, value);
182
+ }
183
+ inferTag(name, value) {
184
+ // IPP requires specific tags for certain attributes
185
+ const knownTags = {
186
+ // Operation attributes
187
+ 'attributes-charset': TAG_VALUE.CHARSET,
188
+ 'attributes-natural-language': TAG_VALUE.NATURAL_LANGUAGE,
189
+ 'printer-uri': TAG_VALUE.URI,
190
+ 'job-uri': TAG_VALUE.URI,
191
+ 'job-name': TAG_VALUE.NAME_WITHOUT_LANGUAGE,
192
+ 'requesting-user-name': TAG_VALUE.NAME_WITHOUT_LANGUAGE,
193
+ 'document-name': TAG_VALUE.NAME_WITHOUT_LANGUAGE,
194
+ 'document-format': TAG_VALUE.MIME_MEDIA_TYPE,
195
+ // Job attributes - keywords
196
+ 'media': TAG_VALUE.KEYWORD,
197
+ 'media-type': TAG_VALUE.KEYWORD,
198
+ 'sides': TAG_VALUE.KEYWORD,
199
+ 'print-color-mode': TAG_VALUE.KEYWORD,
200
+ 'output-bin': TAG_VALUE.KEYWORD,
201
+ 'which-jobs': TAG_VALUE.KEYWORD,
202
+ // Job attributes - enums (not integers!)
203
+ 'print-quality': TAG_VALUE.ENUM,
204
+ 'orientation-requested': TAG_VALUE.ENUM,
205
+ 'finishings': TAG_VALUE.ENUM,
206
+ // Job attributes - integers
207
+ 'copies': TAG_VALUE.INTEGER,
208
+ 'job-id': TAG_VALUE.INTEGER,
209
+ 'job-priority': TAG_VALUE.INTEGER,
210
+ };
211
+ if (knownTags[name]) {
212
+ return knownTags[name];
213
+ }
214
+ // Infer from value type
215
+ if (typeof value === 'boolean')
216
+ return TAG_VALUE.BOOLEAN;
217
+ if (typeof value === 'number')
218
+ return TAG_VALUE.INTEGER;
219
+ if (value instanceof Date)
220
+ return TAG_VALUE.DATE_TIME;
221
+ if (typeof value === 'object' && 'crossFeed' in value)
222
+ return TAG_VALUE.RESOLUTION;
223
+ if (typeof value === 'object' && 'lower' in value)
224
+ return TAG_VALUE.RANGE_OF_INTEGER;
225
+ // String - try to infer type
226
+ const str = String(value);
227
+ if (str.startsWith('ipp://') || str.startsWith('ipps://') || str.startsWith('http://')) {
228
+ return TAG_VALUE.URI;
229
+ }
230
+ if (str.includes('/'))
231
+ return TAG_VALUE.MIME_MEDIA_TYPE; // e.g., application/pdf
232
+ if (str.match(/^[a-z][a-z0-9-]*$/))
233
+ return TAG_VALUE.KEYWORD;
234
+ return TAG_VALUE.NAME_WITHOUT_LANGUAGE;
235
+ }
236
+ writeValue(tag, value) {
237
+ switch (tag) {
238
+ case TAG_VALUE.INTEGER:
239
+ case TAG_VALUE.ENUM:
240
+ this.writeInt16(4);
241
+ this.writeInt32(value);
242
+ break;
243
+ case TAG_VALUE.BOOLEAN:
244
+ this.writeInt16(1);
245
+ this.writeInt8(value ? 1 : 0);
246
+ break;
247
+ case TAG_VALUE.RESOLUTION: {
248
+ const res = value;
249
+ this.writeInt16(9);
250
+ this.writeInt32(res.crossFeed);
251
+ this.writeInt32(res.feed);
252
+ this.writeInt8(res.units === 'dpi' ? 3 : 4);
253
+ break;
254
+ }
255
+ case TAG_VALUE.RANGE_OF_INTEGER: {
256
+ const range = value;
257
+ this.writeInt16(8);
258
+ this.writeInt32(range.lower);
259
+ this.writeInt32(range.upper);
260
+ break;
261
+ }
262
+ case TAG_VALUE.DATE_TIME: {
263
+ const date = value;
264
+ this.writeInt16(11);
265
+ this.writeInt16(date.getUTCFullYear());
266
+ this.writeInt8(date.getUTCMonth() + 1);
267
+ this.writeInt8(date.getUTCDate());
268
+ this.writeInt8(date.getUTCHours());
269
+ this.writeInt8(date.getUTCMinutes());
270
+ this.writeInt8(date.getUTCSeconds());
271
+ this.writeInt8(0); // deciseconds
272
+ this.writeInt8('+'.charCodeAt(0));
273
+ this.writeInt8(0); // UTC offset hours
274
+ this.writeInt8(0); // UTC offset minutes
275
+ break;
276
+ }
277
+ default:
278
+ // String types
279
+ this.writeString(String(value));
280
+ break;
281
+ }
282
+ }
283
+ }
284
+ // ============================================================================
285
+ // IPP Message Decoder
286
+ // ============================================================================
287
+ class IppDecoder {
288
+ buffer = Buffer.alloc(0);
289
+ offset = 0;
290
+ decode(data) {
291
+ this.buffer = data;
292
+ this.offset = 0;
293
+ const version = this.readInt16();
294
+ const operationIdOrStatusCode = this.readInt16();
295
+ const requestId = this.readInt32();
296
+ const message = {
297
+ version,
298
+ operationIdOrStatusCode,
299
+ requestId,
300
+ operationAttributes: {},
301
+ };
302
+ // Read attribute groups
303
+ while (this.offset < this.buffer.length) {
304
+ const tag = this.readInt8();
305
+ if (tag === TAG_DELIMITER.END_OF_ATTRIBUTES) {
306
+ // Remaining data is document data
307
+ if (this.offset < this.buffer.length) {
308
+ message.data = this.buffer.subarray(this.offset);
67
309
  }
68
- try {
69
- const jobs = [];
70
- const jobTags = res['job-attributes-tag'];
71
- if (Array.isArray(jobTags)) {
72
- for (const jobAttrs of jobTags) {
73
- jobs.push(this.parseJobInfo(jobAttrs));
74
- }
75
- }
76
- else if (jobTags && typeof jobTags === 'object') {
77
- jobs.push(this.parseJobInfo(jobTags));
78
- }
79
- resolve(jobs);
310
+ break;
311
+ }
312
+ if (tag === TAG_DELIMITER.OPERATION_ATTRIBUTES) {
313
+ message.operationAttributes = this.readAttributes();
314
+ }
315
+ else if (tag === TAG_DELIMITER.JOB_ATTRIBUTES) {
316
+ message.jobAttributes = this.readAttributes();
317
+ }
318
+ else if (tag === TAG_DELIMITER.PRINTER_ATTRIBUTES) {
319
+ message.printerAttributes = this.readAttributes();
320
+ }
321
+ else if (tag === TAG_DELIMITER.UNSUPPORTED_ATTRIBUTES) {
322
+ message.unsupportedAttributes = this.readAttributes();
323
+ }
324
+ }
325
+ return message;
326
+ }
327
+ readInt8() {
328
+ return this.buffer[this.offset++];
329
+ }
330
+ readInt16() {
331
+ const value = this.buffer.readUInt16BE(this.offset);
332
+ this.offset += 2;
333
+ return value;
334
+ }
335
+ readInt32() {
336
+ const value = this.buffer.readInt32BE(this.offset);
337
+ this.offset += 4;
338
+ return value;
339
+ }
340
+ readUInt32() {
341
+ const value = this.buffer.readUInt32BE(this.offset);
342
+ this.offset += 4;
343
+ return value;
344
+ }
345
+ readString(length) {
346
+ const str = this.buffer.toString('utf-8', this.offset, this.offset + length);
347
+ this.offset += length;
348
+ return str;
349
+ }
350
+ readAttributes() {
351
+ const attrs = {};
352
+ let currentName = '';
353
+ while (this.offset < this.buffer.length) {
354
+ const tag = this.buffer[this.offset];
355
+ // Check for delimiter tag (start of new group or end)
356
+ if (tag <= 0x0f) {
357
+ break;
358
+ }
359
+ this.offset++; // Consume the tag
360
+ const nameLength = this.readInt16();
361
+ const name = nameLength > 0 ? this.readString(nameLength) : currentName;
362
+ const valueLength = this.readInt16();
363
+ const value = this.readValue(tag, valueLength);
364
+ if (nameLength > 0) {
365
+ currentName = name;
366
+ attrs[name] = value;
367
+ }
368
+ else {
369
+ // Additional value for same attribute - make it an array
370
+ const existing = attrs[currentName];
371
+ if (Array.isArray(existing)) {
372
+ existing.push(value);
80
373
  }
81
- catch (parseErr) {
82
- reject(parseErr);
374
+ else {
375
+ attrs[currentName] = [existing, value];
83
376
  }
84
- });
85
- });
377
+ }
378
+ }
379
+ return attrs;
86
380
  }
87
- /**
88
- * Get specific job info
89
- */
90
- async getJobInfo(jobId) {
91
- return new Promise((resolve, reject) => {
92
- this.printer.execute('Get-Job-Attributes', {
93
- 'operation-attributes-tag': {
94
- 'job-id': jobId,
95
- },
96
- }, (err, res) => {
97
- if (err) {
98
- reject(err);
99
- return;
100
- }
101
- try {
102
- const jobAttrs = res['job-attributes-tag'] || {};
103
- resolve(this.parseJobInfo(jobAttrs));
381
+ readValue(tag, length) {
382
+ switch (tag) {
383
+ case TAG_VALUE.INTEGER:
384
+ case TAG_VALUE.ENUM:
385
+ return this.readInt32();
386
+ case TAG_VALUE.BOOLEAN:
387
+ return this.readInt8() !== 0;
388
+ case TAG_VALUE.RESOLUTION: {
389
+ const crossFeed = this.readInt32();
390
+ const feed = this.readInt32();
391
+ const units = this.readInt8() === 3 ? 'dpi' : 'dpcm';
392
+ return { crossFeed, feed, units };
393
+ }
394
+ case TAG_VALUE.RANGE_OF_INTEGER: {
395
+ const lower = this.readInt32();
396
+ const upper = this.readInt32();
397
+ return { lower, upper };
398
+ }
399
+ case TAG_VALUE.DATE_TIME: {
400
+ const year = this.readInt16();
401
+ const month = this.readInt8();
402
+ const day = this.readInt8();
403
+ const hour = this.readInt8();
404
+ const minute = this.readInt8();
405
+ const second = this.readInt8();
406
+ this.readInt8(); // deciseconds
407
+ const direction = String.fromCharCode(this.readInt8());
408
+ const offsetHours = this.readInt8();
409
+ const offsetMinutes = this.readInt8();
410
+ const date = new Date(Date.UTC(year, month - 1, day, hour, minute, second));
411
+ const offsetMs = (offsetHours * 60 + offsetMinutes) * 60 * 1000;
412
+ if (direction === '-') {
413
+ date.setTime(date.getTime() + offsetMs);
104
414
  }
105
- catch (parseErr) {
106
- reject(parseErr);
415
+ else {
416
+ date.setTime(date.getTime() - offsetMs);
107
417
  }
108
- });
109
- });
418
+ return date;
419
+ }
420
+ case TAG_VALUE.NO_VALUE:
421
+ case TAG_VALUE.UNKNOWN:
422
+ case TAG_VALUE.UNSUPPORTED:
423
+ this.offset += length;
424
+ return '';
425
+ default:
426
+ // String types
427
+ return this.readString(length);
428
+ }
110
429
  }
111
- /**
112
- * Cancel a job
113
- */
114
- async cancelJob(jobId) {
115
- return new Promise((resolve, reject) => {
116
- this.printer.execute('Cancel-Job', {
117
- 'operation-attributes-tag': {
118
- 'job-id': jobId,
119
- },
120
- }, (err, _res) => {
121
- if (err) {
122
- reject(err);
123
- return;
124
- }
125
- resolve();
126
- });
127
- });
430
+ }
431
+ // ============================================================================
432
+ // Status Code Helpers
433
+ // ============================================================================
434
+ function isSuccessful(statusCode) {
435
+ return statusCode >= 0x0000 && statusCode <= 0x00ff;
436
+ }
437
+ function statusCodeToString(code) {
438
+ const statusMap = {
439
+ 0x0000: 'successful-ok',
440
+ 0x0001: 'successful-ok-ignored-or-substituted-attributes',
441
+ 0x0002: 'successful-ok-conflicting-attributes',
442
+ 0x0400: 'client-error-bad-request',
443
+ 0x0401: 'client-error-forbidden',
444
+ 0x0402: 'client-error-not-authenticated',
445
+ 0x0403: 'client-error-not-authorized',
446
+ 0x0404: 'client-error-not-possible',
447
+ 0x0405: 'client-error-timeout',
448
+ 0x0406: 'client-error-not-found',
449
+ 0x040a: 'client-error-document-format-not-supported',
450
+ 0x040b: 'client-error-attributes-or-values-not-supported',
451
+ 0x0500: 'server-error-internal-error',
452
+ 0x0501: 'server-error-operation-not-supported',
453
+ 0x0502: 'server-error-service-unavailable',
454
+ 0x0504: 'server-error-device-error',
455
+ 0x0506: 'server-error-not-accepting-jobs',
456
+ 0x0507: 'server-error-busy',
457
+ };
458
+ return statusMap[code] || `unknown-status-${code.toString(16)}`;
459
+ }
460
+ // ============================================================================
461
+ // IPP Client
462
+ // ============================================================================
463
+ export class IppClient {
464
+ printerUri;
465
+ httpUri;
466
+ requestId = 1;
467
+ encoder = new IppEncoder();
468
+ decoder = new IppDecoder();
469
+ constructor(address, port = 631, path = '/ipp/print') {
470
+ this.printerUri = `ipp://${address}:${port}${path}`;
471
+ this.httpUri = `http://${address}:${port}${path}`;
128
472
  }
129
- /**
130
- * Check if printer is available
131
- */
132
- async checkAvailability() {
133
- try {
134
- await this.getAttributes();
135
- return true;
473
+ // ==========================================================================
474
+ // Core Request Method
475
+ // ==========================================================================
476
+ async request(message) {
477
+ const requestData = this.encoder.encode(message);
478
+ const response = await fetch(this.httpUri, {
479
+ method: 'POST',
480
+ headers: {
481
+ 'Content-Type': 'application/ipp',
482
+ 'Accept': 'application/ipp',
483
+ },
484
+ body: new Uint8Array(requestData),
485
+ });
486
+ if (!response.ok) {
487
+ throw new Error(`HTTP error: ${response.status} ${response.statusText}`);
136
488
  }
137
- catch {
138
- return false;
489
+ const responseData = Buffer.from(await response.arrayBuffer());
490
+ return this.decoder.decode(responseData);
491
+ }
492
+ // ==========================================================================
493
+ // Get Printer Attributes
494
+ // ==========================================================================
495
+ async getPrinterAttributes() {
496
+ const message = {
497
+ version: IPP_VERSION.V2_0,
498
+ operationIdOrStatusCode: IPP_OPERATION.GET_PRINTER_ATTRIBUTES,
499
+ requestId: this.requestId++,
500
+ operationAttributes: {
501
+ 'attributes-charset': 'utf-8',
502
+ 'attributes-natural-language': 'en-us',
503
+ 'printer-uri': this.printerUri,
504
+ },
505
+ };
506
+ const response = await this.request(message);
507
+ if (!isSuccessful(response.operationIdOrStatusCode)) {
508
+ throw new Error(`IPP error: ${statusCodeToString(response.operationIdOrStatusCode)}`);
139
509
  }
510
+ return this.parseCapabilities(response.printerAttributes || {});
140
511
  }
141
- /**
142
- * Build IPP print message from options
143
- */
144
- buildPrintMessage(options) {
512
+ parseCapabilities(attrs) {
513
+ const getString = (key, defaultVal = '') => {
514
+ const val = attrs[key];
515
+ if (typeof val === 'string')
516
+ return val;
517
+ if (Array.isArray(val) && val.length > 0)
518
+ return String(val[0]);
519
+ return defaultVal;
520
+ };
521
+ const getStringArray = (key) => {
522
+ const val = attrs[key];
523
+ if (Array.isArray(val))
524
+ return val.map(String);
525
+ if (val !== undefined)
526
+ return [String(val)];
527
+ return [];
528
+ };
529
+ const getNumber = (key, defaultVal = 0) => {
530
+ const val = attrs[key];
531
+ if (typeof val === 'number')
532
+ return val;
533
+ return defaultVal;
534
+ };
535
+ const getNumberArray = (key) => {
536
+ const val = attrs[key];
537
+ if (Array.isArray(val))
538
+ return val.filter((v) => typeof v === 'number');
539
+ if (typeof val === 'number')
540
+ return [val];
541
+ return [];
542
+ };
543
+ const getBool = (key, defaultVal = false) => {
544
+ const val = attrs[key];
545
+ if (typeof val === 'boolean')
546
+ return val;
547
+ return defaultVal;
548
+ };
549
+ const getRange = (key) => {
550
+ const val = attrs[key];
551
+ if (val && typeof val === 'object' && 'lower' in val) {
552
+ return val;
553
+ }
554
+ return { lower: 1, upper: 1 };
555
+ };
556
+ const getResolutions = () => {
557
+ const val = attrs['printer-resolution-supported'];
558
+ if (!val)
559
+ return [];
560
+ const values = Array.isArray(val) ? val : [val];
561
+ return values
562
+ .filter((v) => typeof v === 'object' && v !== null && 'crossFeed' in v);
563
+ };
564
+ // Map printer state number to string
565
+ const printerState = getNumber('printer-state', PRINTER_STATE.IDLE);
566
+ const printerStateString = printerState === PRINTER_STATE.IDLE ? 'idle' :
567
+ printerState === PRINTER_STATE.PROCESSING ? 'processing' : 'stopped';
568
+ return {
569
+ printerName: getString('printer-name', 'Unknown Printer'),
570
+ printerInfo: getString('printer-info') || undefined,
571
+ printerMakeAndModel: getString('printer-make-and-model') || undefined,
572
+ printerLocation: getString('printer-location') || undefined,
573
+ printerUri: this.printerUri,
574
+ printerState: printerStateString,
575
+ printerStateReasons: getStringArray('printer-state-reasons'),
576
+ printerIsAcceptingJobs: getBool('printer-is-accepting-jobs', true),
577
+ queuedJobCount: getNumber('queued-job-count', 0),
578
+ documentFormatSupported: getStringArray('document-format-supported'),
579
+ documentFormatDefault: getString('document-format-default') || undefined,
580
+ mediaSizeSupported: getStringArray('media-supported'),
581
+ mediaDefault: getString('media-default') || undefined,
582
+ mediaTypeSupported: getStringArray('media-type-supported'),
583
+ colorSupported: getBool('color-supported', false),
584
+ sidesSupported: getStringArray('sides-supported'),
585
+ sidesDefault: getString('sides-default') || undefined,
586
+ copiesSupported: getRange('copies-supported'),
587
+ printQualitySupported: getNumberArray('print-quality-supported'),
588
+ resolutionsSupported: getResolutions(),
589
+ operationsSupported: getNumberArray('operations-supported'),
590
+ ippVersionsSupported: getStringArray('ipp-versions-supported'),
591
+ };
592
+ }
593
+ // ==========================================================================
594
+ // Print Job
595
+ // ==========================================================================
596
+ async printJob(data, options = {}) {
597
+ // Build operation attributes
145
598
  const operationAttrs = {
146
- 'requesting-user-name': 'devicemanager',
147
- 'job-name': options?.jobName ?? 'Print Job',
148
- 'document-format': 'application/octet-stream',
599
+ 'attributes-charset': 'utf-8',
600
+ 'attributes-natural-language': 'en-us',
601
+ 'printer-uri': this.printerUri,
602
+ 'requesting-user-name': options.requestingUserName || 'devicemanager',
603
+ 'job-name': options.jobName || 'Print Job',
604
+ 'document-format': options.documentFormat || 'application/octet-stream',
149
605
  };
606
+ // Build job attributes
150
607
  const jobAttrs = {};
151
- if (options?.copies && options.copies > 1) {
608
+ if (options.copies && options.copies > 1) {
152
609
  jobAttrs['copies'] = options.copies;
153
610
  }
154
- if (options?.mediaSize) {
155
- jobAttrs['media'] = options.mediaSize;
156
- }
157
- if (options?.mediaType) {
158
- jobAttrs['media-type'] = options.mediaType;
159
- }
160
- if (options?.sides) {
611
+ if (options.sides) {
161
612
  jobAttrs['sides'] = options.sides;
162
613
  }
163
- if (options?.quality) {
164
- const qualityMap = {
165
- draft: 3,
166
- normal: 4,
167
- high: 5,
168
- };
169
- jobAttrs['print-quality'] = qualityMap[options.quality] ?? 4;
614
+ if (options.media) {
615
+ jobAttrs['media'] = options.media;
616
+ }
617
+ if (options.printQuality) {
618
+ const qualityMap = { draft: 3, normal: 4, high: 5 };
619
+ jobAttrs['print-quality'] = qualityMap[options.printQuality];
170
620
  }
171
- if (options?.colorMode) {
621
+ if (options.colorMode) {
172
622
  jobAttrs['print-color-mode'] = options.colorMode;
173
623
  }
174
- const msg = {
175
- 'operation-attributes-tag': operationAttrs,
624
+ if (options.orientation) {
625
+ const orientationMap = {
626
+ portrait: 3,
627
+ landscape: 4,
628
+ 'reverse-landscape': 5,
629
+ 'reverse-portrait': 6,
630
+ };
631
+ jobAttrs['orientation-requested'] = orientationMap[options.orientation];
632
+ }
633
+ const message = {
634
+ version: IPP_VERSION.V2_0,
635
+ operationIdOrStatusCode: IPP_OPERATION.PRINT_JOB,
636
+ requestId: this.requestId++,
637
+ operationAttributes: operationAttrs,
638
+ jobAttributes: Object.keys(jobAttrs).length > 0 ? jobAttrs : undefined,
639
+ data,
176
640
  };
177
- if (Object.keys(jobAttrs).length > 0) {
178
- msg['job-attributes-tag'] = jobAttrs;
641
+ const response = await this.request(message);
642
+ if (!isSuccessful(response.operationIdOrStatusCode)) {
643
+ throw new Error(`Print failed: ${statusCodeToString(response.operationIdOrStatusCode)}`);
179
644
  }
180
- return msg;
645
+ return this.parseJob(response.jobAttributes || {});
181
646
  }
182
- /**
183
- * Parse printer capabilities from attributes
184
- */
185
- parseCapabilities(attrs) {
186
- const getArray = (key) => {
187
- const value = attrs[key];
188
- if (Array.isArray(value))
189
- return value.map(String);
190
- if (value !== undefined)
191
- return [String(value)];
192
- return [];
193
- };
194
- const getNumber = (key, defaultVal) => {
195
- const value = attrs[key];
196
- if (typeof value === 'number')
197
- return value;
198
- if (typeof value === 'string')
199
- return parseInt(value) || defaultVal;
200
- return defaultVal;
647
+ // ==========================================================================
648
+ // Get Jobs
649
+ // ==========================================================================
650
+ async getJobs(whichJobs = 'not-completed') {
651
+ const message = {
652
+ version: IPP_VERSION.V2_0,
653
+ operationIdOrStatusCode: IPP_OPERATION.GET_JOBS,
654
+ requestId: this.requestId++,
655
+ operationAttributes: {
656
+ 'attributes-charset': 'utf-8',
657
+ 'attributes-natural-language': 'en-us',
658
+ 'printer-uri': this.printerUri,
659
+ 'requesting-user-name': 'devicemanager',
660
+ 'which-jobs': whichJobs,
661
+ },
201
662
  };
202
- const getBool = (key, defaultVal) => {
203
- const value = attrs[key];
204
- if (typeof value === 'boolean')
205
- return value;
206
- if (value === 'true' || value === 1)
207
- return true;
208
- if (value === 'false' || value === 0)
209
- return false;
210
- return defaultVal;
663
+ const response = await this.request(message);
664
+ if (!isSuccessful(response.operationIdOrStatusCode)) {
665
+ throw new Error(`Get jobs failed: ${statusCodeToString(response.operationIdOrStatusCode)}`);
666
+ }
667
+ // Jobs can come back as a single job-attributes-tag or multiple
668
+ // The decoder merges additional values into arrays
669
+ if (!response.jobAttributes) {
670
+ return [];
671
+ }
672
+ // If job-id is an array, we have multiple jobs encoded together
673
+ // This is a limitation of the simple decoder - in reality each job is a separate group
674
+ // For now, return single job if present
675
+ return [this.parseJob(response.jobAttributes)];
676
+ }
677
+ // ==========================================================================
678
+ // Get Job Attributes
679
+ // ==========================================================================
680
+ async getJobAttributes(jobId) {
681
+ const message = {
682
+ version: IPP_VERSION.V2_0,
683
+ operationIdOrStatusCode: IPP_OPERATION.GET_JOB_ATTRIBUTES,
684
+ requestId: this.requestId++,
685
+ operationAttributes: {
686
+ 'attributes-charset': 'utf-8',
687
+ 'attributes-natural-language': 'en-us',
688
+ 'printer-uri': this.printerUri,
689
+ 'job-id': jobId,
690
+ },
211
691
  };
212
- // Parse resolutions
213
- const resolutions = [];
214
- const resSupported = attrs['printer-resolution-supported'];
215
- if (Array.isArray(resSupported)) {
216
- for (const res of resSupported) {
217
- if (typeof res === 'object' && res !== null && 'x' in res) {
218
- resolutions.push(res.x);
219
- }
220
- else if (typeof res === 'number') {
221
- resolutions.push(res);
222
- }
223
- }
692
+ const response = await this.request(message);
693
+ if (!isSuccessful(response.operationIdOrStatusCode)) {
694
+ throw new Error(`Get job failed: ${statusCodeToString(response.operationIdOrStatusCode)}`);
224
695
  }
225
- if (resolutions.length === 0) {
226
- resolutions.push(300, 600);
696
+ return this.parseJob(response.jobAttributes || {});
697
+ }
698
+ // ==========================================================================
699
+ // Cancel Job
700
+ // ==========================================================================
701
+ async cancelJob(jobId) {
702
+ const message = {
703
+ version: IPP_VERSION.V2_0,
704
+ operationIdOrStatusCode: IPP_OPERATION.CANCEL_JOB,
705
+ requestId: this.requestId++,
706
+ operationAttributes: {
707
+ 'attributes-charset': 'utf-8',
708
+ 'attributes-natural-language': 'en-us',
709
+ 'printer-uri': this.printerUri,
710
+ 'job-id': jobId,
711
+ },
712
+ };
713
+ const response = await this.request(message);
714
+ if (!isSuccessful(response.operationIdOrStatusCode)) {
715
+ throw new Error(`Cancel job failed: ${statusCodeToString(response.operationIdOrStatusCode)}`);
227
716
  }
228
- return {
229
- colorSupported: getBool('color-supported', false),
230
- duplexSupported: getArray('sides-supported').some((s) => s.includes('two-sided')),
231
- mediaSizes: getArray('media-supported'),
232
- mediaTypes: getArray('media-type-supported'),
233
- resolutions: [...new Set(resolutions)],
234
- maxCopies: getNumber('copies-supported', 99),
235
- sidesSupported: getArray('sides-supported'),
236
- qualitySupported: getArray('print-quality-supported').map(String),
717
+ }
718
+ // ==========================================================================
719
+ // Validate Job (check if job would succeed without actually printing)
720
+ // ==========================================================================
721
+ async validateJob(options = {}) {
722
+ const operationAttrs = {
723
+ 'attributes-charset': 'utf-8',
724
+ 'attributes-natural-language': 'en-us',
725
+ 'printer-uri': this.printerUri,
726
+ 'document-format': options.documentFormat || 'application/octet-stream',
727
+ };
728
+ const message = {
729
+ version: IPP_VERSION.V2_0,
730
+ operationIdOrStatusCode: IPP_OPERATION.VALIDATE_JOB,
731
+ requestId: this.requestId++,
732
+ operationAttributes: operationAttrs,
237
733
  };
734
+ const response = await this.request(message);
735
+ return isSuccessful(response.operationIdOrStatusCode);
238
736
  }
239
- /**
240
- * Parse job info from attributes
241
- */
242
- parseJobInfo(attrs) {
243
- const getString = (key, defaultVal) => {
244
- const value = attrs[key];
245
- if (typeof value === 'string')
246
- return value;
247
- if (value !== undefined)
248
- return String(value);
737
+ // ==========================================================================
738
+ // Helper Methods
739
+ // ==========================================================================
740
+ parseJob(attrs) {
741
+ const getNumber = (key, defaultVal = 0) => {
742
+ const val = attrs[key];
743
+ if (typeof val === 'number')
744
+ return val;
745
+ if (Array.isArray(val) && typeof val[0] === 'number')
746
+ return val[0];
249
747
  return defaultVal;
250
748
  };
251
- const getNumber = (key, defaultVal) => {
252
- const value = attrs[key];
253
- if (typeof value === 'number')
254
- return value;
255
- if (typeof value === 'string')
256
- return parseInt(value) || defaultVal;
749
+ const getString = (key, defaultVal = '') => {
750
+ const val = attrs[key];
751
+ if (typeof val === 'string')
752
+ return val;
753
+ if (Array.isArray(val) && val.length > 0)
754
+ return String(val[0]);
257
755
  return defaultVal;
258
756
  };
259
- // Map IPP job state to our state
260
- const ippState = getNumber('job-state', 3);
261
- const stateMap = {
262
- 3: 'pending', // pending
263
- 4: 'pending', // pending-held
264
- 5: 'processing', // processing
265
- 6: 'processing', // processing-stopped
266
- 7: 'canceled', // canceled
267
- 8: 'aborted', // aborted
268
- 9: 'completed', // completed
757
+ const getStringArray = (key) => {
758
+ const val = attrs[key];
759
+ if (Array.isArray(val))
760
+ return val.map(String);
761
+ if (val !== undefined)
762
+ return [String(val)];
763
+ return [];
764
+ };
765
+ const getDate = (key) => {
766
+ const val = attrs[key];
767
+ if (val instanceof Date)
768
+ return val;
769
+ return undefined;
770
+ };
771
+ // Map job state number to string
772
+ const jobState = getNumber('job-state', JOB_STATE.PENDING);
773
+ const jobStateMap = {
774
+ [JOB_STATE.PENDING]: 'pending',
775
+ [JOB_STATE.PENDING_HELD]: 'pending-held',
776
+ [JOB_STATE.PROCESSING]: 'processing',
777
+ [JOB_STATE.PROCESSING_STOPPED]: 'processing-stopped',
778
+ [JOB_STATE.CANCELED]: 'canceled',
779
+ [JOB_STATE.ABORTED]: 'aborted',
780
+ [JOB_STATE.COMPLETED]: 'completed',
269
781
  };
270
- const createdTime = attrs['time-at-creation'];
271
- const completedTime = attrs['time-at-completed'];
272
782
  return {
273
- id: getNumber('job-id', 0),
783
+ id: getNumber('job-id'),
784
+ uri: getString('job-uri'),
785
+ state: jobStateMap[jobState] || 'pending',
786
+ stateReasons: getStringArray('job-state-reasons'),
274
787
  name: getString('job-name', 'Unknown Job'),
275
- state: stateMap[ippState] ?? 'pending',
276
- stateReason: getString('job-state-reasons', undefined),
277
- createdAt: createdTime ? new Date(createdTime * 1000) : new Date(),
278
- completedAt: completedTime ? new Date(completedTime * 1000) : undefined,
279
- pagesPrinted: getNumber('job-media-sheets-completed', undefined),
280
- pagesTotal: getNumber('job-media-sheets', undefined),
788
+ originatingUserName: getString('job-originating-user-name') || undefined,
789
+ createdAt: getDate('time-at-creation') || getDate('date-time-at-creation'),
790
+ completedAt: getDate('time-at-completed') || getDate('date-time-at-completed'),
791
+ processingAt: getDate('time-at-processing') || getDate('date-time-at-processing'),
792
+ impressionsCompleted: getNumber('job-impressions-completed') || undefined,
793
+ };
794
+ }
795
+ // ==========================================================================
796
+ // Convenience: Check if format is supported
797
+ // ==========================================================================
798
+ async isFormatSupported(mimeType) {
799
+ const caps = await this.getPrinterAttributes();
800
+ return caps.documentFormatSupported.includes(mimeType);
801
+ }
802
+ // ==========================================================================
803
+ // Convenience: Get best format for data
804
+ // ==========================================================================
805
+ async getBestFormat(preferredFormats) {
806
+ const caps = await this.getPrinterAttributes();
807
+ const supported = caps.documentFormatSupported;
808
+ for (const format of preferredFormats) {
809
+ if (supported.includes(format)) {
810
+ return format;
811
+ }
812
+ }
813
+ return null;
814
+ }
815
+ // ==========================================================================
816
+ // Smart Print: Auto-detect format and convert if needed
817
+ // ==========================================================================
818
+ /**
819
+ * Smart print that auto-detects document format and converts if necessary.
820
+ *
821
+ * If the document format is not supported by the printer, it will attempt
822
+ * to convert to a supported format (e.g., PDF → JPEG).
823
+ */
824
+ async smartPrint(data, options = {}) {
825
+ // Detect format from data
826
+ const detectedFormat = this.detectFormat(data);
827
+ console.log(`[IPP] Detected format: ${detectedFormat}`);
828
+ // Get printer capabilities
829
+ const caps = await this.getPrinterAttributes();
830
+ const supported = caps.documentFormatSupported;
831
+ // Check if detected format is supported
832
+ if (supported.includes(detectedFormat)) {
833
+ console.log(`[IPP] Format ${detectedFormat} is supported, printing directly`);
834
+ return this.printJob(data, {
835
+ ...options,
836
+ documentFormat: detectedFormat,
837
+ });
838
+ }
839
+ // Format not supported - try to convert
840
+ console.log(`[IPP] Format ${detectedFormat} not supported, attempting conversion`);
841
+ // Determine best target format
842
+ const conversionTargets = ['image/jpeg', 'image/png', 'image/pwg-raster'];
843
+ const targetFormat = conversionTargets.find(f => supported.includes(f));
844
+ if (!targetFormat) {
845
+ throw new Error(`Document format ${detectedFormat} not supported and no conversion target available. ` +
846
+ `Printer supports: ${supported.join(', ')}`);
847
+ }
848
+ // Convert the document
849
+ const convertedData = await this.convertDocument(data, detectedFormat, targetFormat);
850
+ console.log(`[IPP] Converted to ${targetFormat} (${convertedData.length} bytes)`);
851
+ return this.printJob(convertedData, {
852
+ ...options,
853
+ documentFormat: targetFormat,
854
+ });
855
+ }
856
+ /**
857
+ * Detect document format from magic bytes
858
+ */
859
+ detectFormat(data) {
860
+ if (data.length < 4) {
861
+ return 'application/octet-stream';
862
+ }
863
+ // PDF: starts with %PDF
864
+ if (data[0] === 0x25 && data[1] === 0x50 && data[2] === 0x44 && data[3] === 0x46) {
865
+ return 'application/pdf';
866
+ }
867
+ // JPEG: starts with FFD8FF
868
+ if (data[0] === 0xff && data[1] === 0xd8 && data[2] === 0xff) {
869
+ return 'image/jpeg';
870
+ }
871
+ // PNG: starts with 89504E47
872
+ if (data[0] === 0x89 && data[1] === 0x50 && data[2] === 0x4e && data[3] === 0x47) {
873
+ return 'image/png';
874
+ }
875
+ // TIFF: starts with 49492A00 (little endian) or 4D4D002A (big endian)
876
+ if ((data[0] === 0x49 && data[1] === 0x49 && data[2] === 0x2a && data[3] === 0x00) ||
877
+ (data[0] === 0x4d && data[1] === 0x4d && data[2] === 0x00 && data[3] === 0x2a)) {
878
+ return 'image/tiff';
879
+ }
880
+ // PostScript: starts with %!
881
+ if (data[0] === 0x25 && data[1] === 0x21) {
882
+ return 'application/postscript';
883
+ }
884
+ // PWG Raster: starts with "RaS2"
885
+ if (data[0] === 0x52 && data[1] === 0x61 && data[2] === 0x53 && data[3] === 0x32) {
886
+ return 'image/pwg-raster';
887
+ }
888
+ // URF (Apple Raster): starts with "UNIRAST"
889
+ if (data.length >= 8 &&
890
+ data[0] === 0x55 && data[1] === 0x4e && data[2] === 0x49 && data[3] === 0x52 &&
891
+ data[4] === 0x41 && data[5] === 0x53 && data[6] === 0x54) {
892
+ return 'image/urf';
893
+ }
894
+ return 'application/octet-stream';
895
+ }
896
+ /**
897
+ * Convert document to target format
898
+ * Uses ImageMagick if available, otherwise throws
899
+ */
900
+ async convertDocument(data, sourceFormat, targetFormat) {
901
+ // Try using ImageMagick via child_process
902
+ const { execSync, spawnSync } = await import('child_process');
903
+ const { writeFileSync, readFileSync, unlinkSync, mkdtempSync } = await import('fs');
904
+ const { join } = await import('path');
905
+ const { tmpdir } = await import('os');
906
+ // Check if ImageMagick is available
907
+ try {
908
+ execSync('which convert', { stdio: 'ignore' });
909
+ }
910
+ catch {
911
+ throw new Error(`Cannot convert ${sourceFormat} to ${targetFormat}: ImageMagick not available`);
912
+ }
913
+ // Create temp directory and files
914
+ const tempDir = mkdtempSync(join(tmpdir(), 'ipp-convert-'));
915
+ const sourceExt = this.formatToExtension(sourceFormat);
916
+ const targetExt = this.formatToExtension(targetFormat);
917
+ const sourcePath = join(tempDir, `input${sourceExt}`);
918
+ const targetPath = join(tempDir, `output${targetExt}`);
919
+ try {
920
+ // Write source file
921
+ writeFileSync(sourcePath, data);
922
+ // Build convert command
923
+ const args = [
924
+ sourcePath,
925
+ '-density', '300', // Good DPI for print
926
+ '-quality', '90', // JPEG quality
927
+ '-background', 'white', // White background for transparency
928
+ '-flatten', // Flatten layers
929
+ targetPath,
930
+ ];
931
+ // For multi-page PDFs, only convert first page
932
+ if (sourceFormat === 'application/pdf') {
933
+ args[0] = `${sourcePath}[0]`; // First page only
934
+ }
935
+ // Run conversion
936
+ const result = spawnSync('convert', args, {
937
+ timeout: 30000,
938
+ maxBuffer: 100 * 1024 * 1024, // 100MB
939
+ });
940
+ if (result.status !== 0) {
941
+ const stderr = result.stderr?.toString() || 'Unknown error';
942
+ throw new Error(`ImageMagick conversion failed: ${stderr}`);
943
+ }
944
+ // Read converted file
945
+ return readFileSync(targetPath);
946
+ }
947
+ finally {
948
+ // Cleanup temp files
949
+ try {
950
+ unlinkSync(sourcePath);
951
+ }
952
+ catch { }
953
+ try {
954
+ unlinkSync(targetPath);
955
+ }
956
+ catch { }
957
+ try {
958
+ const { rmdirSync } = await import('fs');
959
+ rmdirSync(tempDir);
960
+ }
961
+ catch { }
962
+ }
963
+ }
964
+ /**
965
+ * Get file extension for MIME type
966
+ */
967
+ formatToExtension(mimeType) {
968
+ const extensions = {
969
+ 'application/pdf': '.pdf',
970
+ 'image/jpeg': '.jpg',
971
+ 'image/png': '.png',
972
+ 'image/tiff': '.tiff',
973
+ 'application/postscript': '.ps',
974
+ 'image/pwg-raster': '.pwg',
975
+ 'image/urf': '.urf',
976
+ 'application/octet-stream': '.bin',
281
977
  };
978
+ return extensions[mimeType] || '.bin';
282
979
  }
283
980
  }
284
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdG9jb2wuaXBwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvcHJvdG9jb2xzL3Byb3RvY29sLmlwcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQU96Qzs7R0FFRztBQUNILE1BQU0sT0FBTyxXQUFXO0lBQ2QsVUFBVSxDQUFTO0lBQ25CLE9BQU8sQ0FBeUM7SUFFeEQsWUFBWSxPQUFlLEVBQUUsSUFBWSxFQUFFLE9BQWUsWUFBWTtRQUNwRSxJQUFJLENBQUMsVUFBVSxHQUFHLFNBQVMsT0FBTyxJQUFJLElBQUksR0FBRyxJQUFJLEVBQUUsQ0FBQztRQUNwRCxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUN0RCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsYUFBYTtRQUN4QixPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ3JDLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUNsQix3QkFBd0IsRUFDeEIsSUFBSSxFQUNKLENBQUMsR0FBaUIsRUFBRSxHQUE0QixFQUFFLEVBQUU7Z0JBQ2xELElBQUksR0FBRyxFQUFFLENBQUM7b0JBQ1IsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO29CQUNaLE9BQU87Z0JBQ1QsQ0FBQztnQkFFRCxJQUFJLENBQUM7b0JBQ0gsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLHdCQUF3QixDQUE0QixJQUFJLEVBQUUsQ0FBQztvQkFDN0UsT0FBTyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO2dCQUN6QyxDQUFDO2dCQUFDLE9BQU8sUUFBUSxFQUFFLENBQUM7b0JBQ2xCLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDbkIsQ0FBQztZ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
981
+ // Export as IppProtocol for consistency with other protocols
982
+ export { IppClient as IppProtocol };
983
+ // ============================================================================
984
+ // Exports
985
+ // ============================================================================
986
+ export { IPP_VERSION, IPP_OPERATION, IPP_STATUS, JOB_STATE, PRINTER_STATE, isSuccessful, statusCodeToString, };
987
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdG9jb2wuaXBwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvcHJvdG9jb2xzL3Byb3RvY29sLmlwcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFFSCwrRUFBK0U7QUFDL0UsWUFBWTtBQUNaLCtFQUErRTtBQUUvRSxrQkFBa0I7QUFDbEIsTUFBTSxXQUFXLEdBQUc7SUFDbEIsSUFBSSxFQUFFLE1BQU07SUFDWixJQUFJLEVBQUUsTUFBTTtDQUNKLENBQUM7QUFFWCxxQkFBcUI7QUFDckIsTUFBTSxhQUFhLEdBQUc7SUFDcEIsU0FBUyxFQUFFLE1BQU07SUFDakIsWUFBWSxFQUFFLE1BQU07SUFDcEIsVUFBVSxFQUFFLE1BQU07SUFDbEIsa0JBQWtCLEVBQUUsTUFBTTtJQUMxQixRQUFRLEVBQUUsTUFBTTtJQUNoQixzQkFBc0IsRUFBRSxNQUFNO0NBQ3RCLENBQUM7QUFFWCx1QkFBdUI7QUFDdkIsTUFBTSxVQUFVLEdBQUc7SUFDakIsYUFBYTtJQUNiLGFBQWEsRUFBRSxNQUFNO0lBQ3JCLGdDQUFnQyxFQUFFLE1BQU07SUFDeEMsb0NBQW9DLEVBQUUsTUFBTTtJQUU1QyxnQkFBZ0I7SUFDaEIsd0JBQXdCLEVBQUUsTUFBTTtJQUNoQyxzQkFBc0IsRUFBRSxNQUFNO0lBQzlCLDhCQUE4QixFQUFFLE1BQU07SUFDdEMsMkJBQTJCLEVBQUUsTUFBTTtJQUNuQyx5QkFBeUIsRUFBRSxNQUFNO0lBQ2pDLG9CQUFvQixFQUFFLE1BQU07SUFDNUIsc0JBQXNCLEVBQUUsTUFBTTtJQUM5QiwwQ0FBMEMsRUFBRSxNQUFNO0lBRWxELGdCQUFnQjtJQUNoQixxQkFBcUIsRUFBRSxNQUFNO0lBQzdCLG9DQUFvQyxFQUFFLE1BQU07SUFDNUMsZ0NBQWdDLEVBQUUsTUFBTTtJQUN4Qyx5QkFBeUIsRUFBRSxNQUFNO0lBQ2pDLCtCQUErQixFQUFFLE1BQU07SUFDdkMsaUJBQWlCLEVBQUUsTUFBTTtDQUNqQixD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