@capturebridge/sdk 0.8.0 → 0.9.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/CHANGELOG.md ADDED
@@ -0,0 +1,22 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.9.0] - 2024-06-06
9
+
10
+ ### Added
11
+
12
+ - Introduced Changelog.
13
+ - Add Verifone class and examples (features signature capture support for the M450)
14
+ - Add `format` parameter to `DEFAULT_CAPTURE_OPT` (defaults to `null` which will
15
+ use the plugin's default image format.)
16
+ - Add `CaptureResponseFormat` type definition to documentation.
17
+
18
+ ### Fixed
19
+
20
+ - Fix bug where `null` would be sent for some URL parameters.
21
+
22
+ [0.9.0]: https://www.npmjs.com/package/@capturebridge/sdk/v/0.9.0
package/Common.js CHANGED
@@ -75,6 +75,25 @@ export const DEFAULT_STREAM_OPT = {
75
75
  *
76
76
  */
77
77
 
78
+ /**
79
+ * @typedef {string} CaptureResponseFormat
80
+ * @summary The image format to be returned.
81
+ *
82
+ * Valid values:
83
+ *
84
+ * - `jpg`
85
+ * - `tiff`
86
+ *
87
+ * If not provided, a plugin or device-specific format will be returned.
88
+ *
89
+ * **Note:**
90
+ * - Some plugins have configuration options for specifying the return format,
91
+ * such configuration options should be used instead of this parameter to
92
+ * prevent unecessary transcoding.
93
+ * - Web browsers are not typically capable of displaying TIFF images.
94
+ *
95
+ */
96
+
78
97
  /**
79
98
  * @summary Default options for capture operations.
80
99
  * @constant
@@ -87,11 +106,14 @@ export const DEFAULT_STREAM_OPT = {
87
106
  * such as {@link Device#frameAsBase64}, ignore this parameter. This parameter
88
107
  * is also not sent in API requests, it is used internally by the SDK for
89
108
  * constructing the appropriate response type.
109
+ * @property {CaptureResponseFormat} format - The image format to be returned.
110
+ *
90
111
  * @typedef {object} CaptureOptions
91
112
  */
92
113
  export const DEFAULT_CAPTURE_OPT = {
93
114
  rotate: 0,
94
115
  base64: false,
116
+ format: null,
95
117
  kind: 'objecturl'
96
118
  }
97
119
 
@@ -175,6 +197,22 @@ export const checkResponse = async (response) => {
175
197
  }
176
198
  }
177
199
 
200
+ /**
201
+ * Helper function to convert a key/value map to a string, removing any items
202
+ * that are null or undefined (instead of converting them to a string which
203
+ * URLSearchParams().toString() will do.)
204
+ * @private
205
+ */
206
+ export const urlParamsToString = (params) => {
207
+ const filtered = {}
208
+ Object.keys(params).forEach(key => {
209
+ if (params[key] !== null && params[key] !== undefined) {
210
+ filtered[key] = params[key]
211
+ }
212
+ })
213
+ return new URLSearchParams(filtered).toString()
214
+ }
215
+
178
216
  /**
179
217
  * Allows passing in a string for the response type of capture methods
180
218
  * @private
package/Device.js CHANGED
@@ -6,7 +6,8 @@ import {
6
6
  DEFAULT_CAPTURE_OPT,
7
7
  checkResponse,
8
8
  timeout,
9
- asyncToCallback
9
+ asyncToCallback,
10
+ urlParamsToString
10
11
  } from './Common.js'
11
12
 
12
13
  /**
@@ -42,12 +43,27 @@ class Device {
42
43
  Object.assign(this, {}, properties)
43
44
  }
44
45
 
46
+ /**
47
+ * Will throw an exception if a plugin cannot perform the provided RPC command
48
+ * @param {string} method - The JSON RPC method to check.
49
+ */
45
50
  can (method) {
46
51
  if (this.plugin.methods.indexOf(method) === -1) {
47
52
  throw new Error(`${method} not supported for this device`)
48
53
  }
49
54
  }
50
55
 
56
+ /**
57
+ * Will throw an exception if the plugin cannot performa at least one of the
58
+ * provided JSON RPC commandss
59
+ * @param {string[]} methods - The JSON RPC methods to check.
60
+ */
61
+ canDoOne (methods) {
62
+ if (!methods.some(m => this.plugin.methods.includes(m))) {
63
+ throw new Error(`Device does not support any of the methods: ${methods.join(',')}`)
64
+ }
65
+ }
66
+
51
67
  /**
52
68
  * Get the stream endpoint URL.
53
69
  *
@@ -106,7 +122,7 @@ class Device {
106
122
  // Method ignores kind, always returns an object URL
107
123
  delete captureParams.kind
108
124
 
109
- const params = new URLSearchParams(captureParams).toString()
125
+ const params = urlParamsToString(captureParams)
110
126
  const url = `${this.baseUrl}/plugin/${this.plugin.id}/device/${this.id}/capture?${params}`
111
127
  const response = await fetch(url, POST)
112
128
  return await response.blob()
@@ -141,7 +157,7 @@ class Device {
141
157
  // Method ignores kind, always returns binary data (blob)
142
158
  delete captureParams.kind
143
159
 
144
- const params = new URLSearchParams(captureParams).toString()
160
+ const params = urlParamsToString(captureParams)
145
161
  const url = `${this.baseUrl}/plugin/${this.plugin.id}/device/${this.id}/capture?${params}`
146
162
  const response = await fetch(url, POST)
147
163
  return await response.blob()
@@ -200,7 +216,7 @@ class Device {
200
216
  delete captureParams.kind
201
217
  captureParams.base64 = true
202
218
 
203
- const params = new URLSearchParams(captureParams).toString()
219
+ const params = urlParamsToString(captureParams)
204
220
  const url = `${this.baseUrl}/plugin/${this.plugin.id}/device/${this.id}/capture?${params}`
205
221
  const response = await fetch(url, POST)
206
222
  await checkResponse(response)
@@ -262,7 +278,7 @@ class Device {
262
278
  delete captureParams.kind
263
279
  captureParams.base64 = true
264
280
 
265
- const params = new URLSearchParams(captureParams).toString()
281
+ const params = urlParamsToString(captureParams)
266
282
  const url = `${this.baseUrl}/plugin/${this.plugin.id}/device/${this.id}/livefeed?${params}`
267
283
  const response = await fetch(url)
268
284
  const result = await response.json()
@@ -352,7 +368,7 @@ class Device {
352
368
  // Method ignores kind, always returns binary data (blob)
353
369
  delete captureParams.kind
354
370
 
355
- const params = new URLSearchParams(captureParams).toString()
371
+ const params = urlParamsToString(captureParams)
356
372
  const url = `${this.baseUrl}/plugin/${this.plugin.id}/device/${this.id}/livefeed?${params}`
357
373
  const result = await this.frameAsBase64(captureOpt, millis)
358
374
  if (typeof result === 'string') {
@@ -459,7 +475,7 @@ class Device {
459
475
  * console.log(await await device.clear())
460
476
  */
461
477
  async clear (backlight) {
462
- this.can('draw')
478
+ this.canDoOne(['draw', 'clear'])
463
479
  let url = `${this.baseUrl}/plugin/${this.plugin.id}/device/${this.id}/display`
464
480
  if (typeof backlight === 'boolean') {
465
481
  url += `?backlight=${backlight}`
@@ -542,6 +558,38 @@ class Device {
542
558
  async displayObjectsHandler (objects, clear = true, callback) {
543
559
  asyncToCallback(this, this.displayObjects, callback, objects, clear)
544
560
  }
561
+
562
+ /**
563
+ * Get detailed information about a device
564
+ *
565
+ * @description Returns detailed information about a device.
566
+ *
567
+ * @async
568
+ * @method
569
+ * @returns {object} Device info
570
+ * @example
571
+ * const info = await device.info()
572
+ */
573
+ async info () {
574
+ this.can('device_info')
575
+ const url = `${this.baseUrl}/plugin/${this.plugin.id}/device/${this.id}/info`
576
+ const response = await fetch(url)
577
+ return await response.json()
578
+ }
579
+
580
+ /**
581
+ * Get detailed information about a device
582
+ *
583
+ * @description Returns detailed information about a device.
584
+ *
585
+ * @method
586
+ * @returns {object} Device info
587
+ * @example
588
+ * const info = await device.info()
589
+ */
590
+ async infoHandler (callback) {
591
+ asyncToCallback(this, this.info, callback)
592
+ }
545
593
  }
546
594
 
547
595
  export default Device
package/Verifone.js ADDED
@@ -0,0 +1,68 @@
1
+ import SignatureTablet from './SignatureTablet.js'
2
+ import { BASE_URL } from './Common.js'
3
+
4
+ /**
5
+ * Verifone
6
+ * @classdesc Captures a signature on Verifone device.
7
+ * @extends SignatureTablet
8
+ * @see {@link SignatureTablet}
9
+ */
10
+ class Verifone extends SignatureTablet {
11
+ /**
12
+ * Instantiate a Verifone Class
13
+ * @constructor
14
+ * @param {string} [baseURL] - Protocol, domain, and port for the service.
15
+ * @example
16
+ * const tablet = new Verifone()
17
+ *
18
+ */
19
+ constructor (baseUrl = BASE_URL) {
20
+ super('capture_signature_verifone', baseUrl)
21
+ }
22
+
23
+ /**
24
+ * Not currently supported for this plugin.
25
+ * @throws Not implemented error
26
+ * @example
27
+ * // Not currently supported for this plugin
28
+ * @override
29
+ */
30
+ async streamUrl () {
31
+ throw new Error('streamUrl() is not implemented for the Verifone Plugin')
32
+ }
33
+
34
+ /**
35
+ * Not currently supported for this plugin.
36
+ * @throws Not implemented error
37
+ * @example
38
+ * // Not currently supported for this plugin
39
+ * @override
40
+ */
41
+ async getMostRecentFrame () {
42
+ throw new Error('getMostRecentFrame() is not implemented for the Verifone Plugin')
43
+ }
44
+
45
+ /**
46
+ * Not currently supported for this plugin.
47
+ * @throws Not implemented error
48
+ * @example
49
+ * // Not currently supported for this plugin
50
+ * @override
51
+ */
52
+ async stopFeed () {
53
+ throw new Error('stopFeed() is not implemented for the Verifone Plugin')
54
+ }
55
+
56
+ /**
57
+ * Not currently supported for this plugin.
58
+ * @throws Not implemented error
59
+ * @example
60
+ * // Not currently supported for this plugin
61
+ * @override
62
+ */
63
+ async displayObjects () {
64
+ throw new Error('displayObjects() is not implemented for the Verifone Plugin')
65
+ }
66
+ }
67
+
68
+ export default Verifone
package/Version.js CHANGED
@@ -4,5 +4,5 @@
4
4
  * @constant
5
5
  * @type {string}
6
6
  */
7
- const VERSION = '0.8.0'
7
+ const VERSION = '0.9.0'
8
8
  export default VERSION
@@ -0,0 +1,23 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head><title>Verifone Minimal Example</title></head>
4
+ <body>
5
+ <script type="module">
6
+ import Verifone from '/sdk/js/Verifone.js'
7
+ (async () => {
8
+ try {
9
+ const tablet = new Verifone()
10
+
11
+ const img = document.createElement('img')
12
+ img.src = await tablet.signature({format: 'jpg'})
13
+ await tablet.clear()
14
+ document.body.appendChild(img)
15
+
16
+ } catch (e) {
17
+ console.error(e)
18
+ alert(`Error: ${e.message}`)
19
+ }
20
+ })()
21
+ </script>
22
+ </body>
23
+ </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capturebridge/sdk",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Capture Bridge JavaScript SDK for web applications",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0"