UNPKG

230 kBJavaScriptView Raw
1(function (global, factory) {
2 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3 typeof define === 'function' && define.amd ? define(['exports'], factory) :
4 (factory((global.Virgil = {})));
5}(this, (function (exports) { 'use strict';
6
7 var global$1 = (typeof global !== "undefined" ? global :
8 typeof self !== "undefined" ? self :
9 typeof window !== "undefined" ? window : {});
10
11 var lookup = [];
12 var revLookup = [];
13 var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array;
14 var inited = false;
15 function init () {
16 inited = true;
17 var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
18 for (var i = 0, len = code.length; i < len; ++i) {
19 lookup[i] = code[i];
20 revLookup[code.charCodeAt(i)] = i;
21 }
22
23 revLookup['-'.charCodeAt(0)] = 62;
24 revLookup['_'.charCodeAt(0)] = 63;
25 }
26
27 function toByteArray (b64) {
28 if (!inited) {
29 init();
30 }
31 var i, j, l, tmp, placeHolders, arr;
32 var len = b64.length;
33
34 if (len % 4 > 0) {
35 throw new Error('Invalid string. Length must be a multiple of 4')
36 }
37
38 // the number of equal signs (place holders)
39 // if there are two placeholders, than the two characters before it
40 // represent one byte
41 // if there is only one, then the three characters before it represent 2 bytes
42 // this is just a cheap hack to not do indexOf twice
43 placeHolders = b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0;
44
45 // base64 is 4/3 + up to two characters of the original data
46 arr = new Arr(len * 3 / 4 - placeHolders);
47
48 // if there are placeholders, only get up to the last complete 4 chars
49 l = placeHolders > 0 ? len - 4 : len;
50
51 var L = 0;
52
53 for (i = 0, j = 0; i < l; i += 4, j += 3) {
54 tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)];
55 arr[L++] = (tmp >> 16) & 0xFF;
56 arr[L++] = (tmp >> 8) & 0xFF;
57 arr[L++] = tmp & 0xFF;
58 }
59
60 if (placeHolders === 2) {
61 tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4);
62 arr[L++] = tmp & 0xFF;
63 } else if (placeHolders === 1) {
64 tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2);
65 arr[L++] = (tmp >> 8) & 0xFF;
66 arr[L++] = tmp & 0xFF;
67 }
68
69 return arr
70 }
71
72 function tripletToBase64 (num) {
73 return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]
74 }
75
76 function encodeChunk (uint8, start, end) {
77 var tmp;
78 var output = [];
79 for (var i = start; i < end; i += 3) {
80 tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]);
81 output.push(tripletToBase64(tmp));
82 }
83 return output.join('')
84 }
85
86 function fromByteArray (uint8) {
87 if (!inited) {
88 init();
89 }
90 var tmp;
91 var len = uint8.length;
92 var extraBytes = len % 3; // if we have 1 byte left, pad 2 bytes
93 var output = '';
94 var parts = [];
95 var maxChunkLength = 16383; // must be multiple of 3
96
97 // go through the array every three bytes, we'll deal with trailing stuff later
98 for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
99 parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)));
100 }
101
102 // pad the end with zeros, but make sure to not forget the extra bytes
103 if (extraBytes === 1) {
104 tmp = uint8[len - 1];
105 output += lookup[tmp >> 2];
106 output += lookup[(tmp << 4) & 0x3F];
107 output += '==';
108 } else if (extraBytes === 2) {
109 tmp = (uint8[len - 2] << 8) + (uint8[len - 1]);
110 output += lookup[tmp >> 10];
111 output += lookup[(tmp >> 4) & 0x3F];
112 output += lookup[(tmp << 2) & 0x3F];
113 output += '=';
114 }
115
116 parts.push(output);
117
118 return parts.join('')
119 }
120
121 function read (buffer, offset, isLE, mLen, nBytes) {
122 var e, m;
123 var eLen = nBytes * 8 - mLen - 1;
124 var eMax = (1 << eLen) - 1;
125 var eBias = eMax >> 1;
126 var nBits = -7;
127 var i = isLE ? (nBytes - 1) : 0;
128 var d = isLE ? -1 : 1;
129 var s = buffer[offset + i];
130
131 i += d;
132
133 e = s & ((1 << (-nBits)) - 1);
134 s >>= (-nBits);
135 nBits += eLen;
136 for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
137
138 m = e & ((1 << (-nBits)) - 1);
139 e >>= (-nBits);
140 nBits += mLen;
141 for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
142
143 if (e === 0) {
144 e = 1 - eBias;
145 } else if (e === eMax) {
146 return m ? NaN : ((s ? -1 : 1) * Infinity)
147 } else {
148 m = m + Math.pow(2, mLen);
149 e = e - eBias;
150 }
151 return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
152 }
153
154 function write (buffer, value, offset, isLE, mLen, nBytes) {
155 var e, m, c;
156 var eLen = nBytes * 8 - mLen - 1;
157 var eMax = (1 << eLen) - 1;
158 var eBias = eMax >> 1;
159 var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0);
160 var i = isLE ? 0 : (nBytes - 1);
161 var d = isLE ? 1 : -1;
162 var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
163
164 value = Math.abs(value);
165
166 if (isNaN(value) || value === Infinity) {
167 m = isNaN(value) ? 1 : 0;
168 e = eMax;
169 } else {
170 e = Math.floor(Math.log(value) / Math.LN2);
171 if (value * (c = Math.pow(2, -e)) < 1) {
172 e--;
173 c *= 2;
174 }
175 if (e + eBias >= 1) {
176 value += rt / c;
177 } else {
178 value += rt * Math.pow(2, 1 - eBias);
179 }
180 if (value * c >= 2) {
181 e++;
182 c /= 2;
183 }
184
185 if (e + eBias >= eMax) {
186 m = 0;
187 e = eMax;
188 } else if (e + eBias >= 1) {
189 m = (value * c - 1) * Math.pow(2, mLen);
190 e = e + eBias;
191 } else {
192 m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
193 e = 0;
194 }
195 }
196
197 for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
198
199 e = (e << mLen) | m;
200 eLen += mLen;
201 for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
202
203 buffer[offset + i - d] |= s * 128;
204 }
205
206 var toString = {}.toString;
207
208 var isArray = Array.isArray || function (arr) {
209 return toString.call(arr) == '[object Array]';
210 };
211
212 var INSPECT_MAX_BYTES = 50;
213
214 /**
215 * If `Buffer.TYPED_ARRAY_SUPPORT`:
216 * === true Use Uint8Array implementation (fastest)
217 * === false Use Object implementation (most compatible, even IE6)
218 *
219 * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
220 * Opera 11.6+, iOS 4.2+.
221 *
222 * Due to various browser bugs, sometimes the Object implementation will be used even
223 * when the browser supports typed arrays.
224 *
225 * Note:
226 *
227 * - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances,
228 * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
229 *
230 * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
231 *
232 * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
233 * incorrect length in some situations.
234
235 * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they
236 * get the Object implementation, which is slower but behaves correctly.
237 */
238 Buffer.TYPED_ARRAY_SUPPORT = global$1.TYPED_ARRAY_SUPPORT !== undefined
239 ? global$1.TYPED_ARRAY_SUPPORT
240 : true;
241
242 function kMaxLength () {
243 return Buffer.TYPED_ARRAY_SUPPORT
244 ? 0x7fffffff
245 : 0x3fffffff
246 }
247
248 function createBuffer (that, length) {
249 if (kMaxLength() < length) {
250 throw new RangeError('Invalid typed array length')
251 }
252 if (Buffer.TYPED_ARRAY_SUPPORT) {
253 // Return an augmented `Uint8Array` instance, for best performance
254 that = new Uint8Array(length);
255 that.__proto__ = Buffer.prototype;
256 } else {
257 // Fallback: Return an object instance of the Buffer class
258 if (that === null) {
259 that = new Buffer(length);
260 }
261 that.length = length;
262 }
263
264 return that
265 }
266
267 /**
268 * The Buffer constructor returns instances of `Uint8Array` that have their
269 * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of
270 * `Uint8Array`, so the returned instances will have all the node `Buffer` methods
271 * and the `Uint8Array` methods. Square bracket notation works as expected -- it
272 * returns a single octet.
273 *
274 * The `Uint8Array` prototype remains unmodified.
275 */
276
277 function Buffer (arg, encodingOrOffset, length) {
278 if (!Buffer.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer)) {
279 return new Buffer(arg, encodingOrOffset, length)
280 }
281
282 // Common case.
283 if (typeof arg === 'number') {
284 if (typeof encodingOrOffset === 'string') {
285 throw new Error(
286 'If encoding is specified then the first argument must be a string'
287 )
288 }
289 return allocUnsafe(this, arg)
290 }
291 return from(this, arg, encodingOrOffset, length)
292 }
293
294 Buffer.poolSize = 8192; // not used by this implementation
295
296 // TODO: Legacy, not needed anymore. Remove in next major version.
297 Buffer._augment = function (arr) {
298 arr.__proto__ = Buffer.prototype;
299 return arr
300 };
301
302 function from (that, value, encodingOrOffset, length) {
303 if (typeof value === 'number') {
304 throw new TypeError('"value" argument must not be a number')
305 }
306
307 if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) {
308 return fromArrayBuffer(that, value, encodingOrOffset, length)
309 }
310
311 if (typeof value === 'string') {
312 return fromString(that, value, encodingOrOffset)
313 }
314
315 return fromObject(that, value)
316 }
317
318 /**
319 * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError
320 * if value is a number.
321 * Buffer.from(str[, encoding])
322 * Buffer.from(array)
323 * Buffer.from(buffer)
324 * Buffer.from(arrayBuffer[, byteOffset[, length]])
325 **/
326 Buffer.from = function (value, encodingOrOffset, length) {
327 return from(null, value, encodingOrOffset, length)
328 };
329
330 if (Buffer.TYPED_ARRAY_SUPPORT) {
331 Buffer.prototype.__proto__ = Uint8Array.prototype;
332 Buffer.__proto__ = Uint8Array;
333 }
334
335 function assertSize (size) {
336 if (typeof size !== 'number') {
337 throw new TypeError('"size" argument must be a number')
338 } else if (size < 0) {
339 throw new RangeError('"size" argument must not be negative')
340 }
341 }
342
343 function alloc (that, size, fill, encoding) {
344 assertSize(size);
345 if (size <= 0) {
346 return createBuffer(that, size)
347 }
348 if (fill !== undefined) {
349 // Only pay attention to encoding if it's a string. This
350 // prevents accidentally sending in a number that would
351 // be interpretted as a start offset.
352 return typeof encoding === 'string'
353 ? createBuffer(that, size).fill(fill, encoding)
354 : createBuffer(that, size).fill(fill)
355 }
356 return createBuffer(that, size)
357 }
358
359 /**
360 * Creates a new filled Buffer instance.
361 * alloc(size[, fill[, encoding]])
362 **/
363 Buffer.alloc = function (size, fill, encoding) {
364 return alloc(null, size, fill, encoding)
365 };
366
367 function allocUnsafe (that, size) {
368 assertSize(size);
369 that = createBuffer(that, size < 0 ? 0 : checked(size) | 0);
370 if (!Buffer.TYPED_ARRAY_SUPPORT) {
371 for (var i = 0; i < size; ++i) {
372 that[i] = 0;
373 }
374 }
375 return that
376 }
377
378 /**
379 * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance.
380 * */
381 Buffer.allocUnsafe = function (size) {
382 return allocUnsafe(null, size)
383 };
384 /**
385 * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance.
386 */
387 Buffer.allocUnsafeSlow = function (size) {
388 return allocUnsafe(null, size)
389 };
390
391 function fromString (that, string, encoding) {
392 if (typeof encoding !== 'string' || encoding === '') {
393 encoding = 'utf8';
394 }
395
396 if (!Buffer.isEncoding(encoding)) {
397 throw new TypeError('"encoding" must be a valid string encoding')
398 }
399
400 var length = byteLength(string, encoding) | 0;
401 that = createBuffer(that, length);
402
403 var actual = that.write(string, encoding);
404
405 if (actual !== length) {
406 // Writing a hex string, for example, that contains invalid characters will
407 // cause everything after the first invalid character to be ignored. (e.g.
408 // 'abxxcd' will be treated as 'ab')
409 that = that.slice(0, actual);
410 }
411
412 return that
413 }
414
415 function fromArrayLike (that, array) {
416 var length = array.length < 0 ? 0 : checked(array.length) | 0;
417 that = createBuffer(that, length);
418 for (var i = 0; i < length; i += 1) {
419 that[i] = array[i] & 255;
420 }
421 return that
422 }
423
424 function fromArrayBuffer (that, array, byteOffset, length) {
425 array.byteLength; // this throws if `array` is not a valid ArrayBuffer
426
427 if (byteOffset < 0 || array.byteLength < byteOffset) {
428 throw new RangeError('\'offset\' is out of bounds')
429 }
430
431 if (array.byteLength < byteOffset + (length || 0)) {
432 throw new RangeError('\'length\' is out of bounds')
433 }
434
435 if (byteOffset === undefined && length === undefined) {
436 array = new Uint8Array(array);
437 } else if (length === undefined) {
438 array = new Uint8Array(array, byteOffset);
439 } else {
440 array = new Uint8Array(array, byteOffset, length);
441 }
442
443 if (Buffer.TYPED_ARRAY_SUPPORT) {
444 // Return an augmented `Uint8Array` instance, for best performance
445 that = array;
446 that.__proto__ = Buffer.prototype;
447 } else {
448 // Fallback: Return an object instance of the Buffer class
449 that = fromArrayLike(that, array);
450 }
451 return that
452 }
453
454 function fromObject (that, obj) {
455 if (internalIsBuffer(obj)) {
456 var len = checked(obj.length) | 0;
457 that = createBuffer(that, len);
458
459 if (that.length === 0) {
460 return that
461 }
462
463 obj.copy(that, 0, 0, len);
464 return that
465 }
466
467 if (obj) {
468 if ((typeof ArrayBuffer !== 'undefined' &&
469 obj.buffer instanceof ArrayBuffer) || 'length' in obj) {
470 if (typeof obj.length !== 'number' || isnan(obj.length)) {
471 return createBuffer(that, 0)
472 }
473 return fromArrayLike(that, obj)
474 }
475
476 if (obj.type === 'Buffer' && isArray(obj.data)) {
477 return fromArrayLike(that, obj.data)
478 }
479 }
480
481 throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.')
482 }
483
484 function checked (length) {
485 // Note: cannot use `length < kMaxLength()` here because that fails when
486 // length is NaN (which is otherwise coerced to zero.)
487 if (length >= kMaxLength()) {
488 throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
489 'size: 0x' + kMaxLength().toString(16) + ' bytes')
490 }
491 return length | 0
492 }
493 Buffer.isBuffer = isBuffer;
494 function internalIsBuffer (b) {
495 return !!(b != null && b._isBuffer)
496 }
497
498 Buffer.compare = function compare (a, b) {
499 if (!internalIsBuffer(a) || !internalIsBuffer(b)) {
500 throw new TypeError('Arguments must be Buffers')
501 }
502
503 if (a === b) return 0
504
505 var x = a.length;
506 var y = b.length;
507
508 for (var i = 0, len = Math.min(x, y); i < len; ++i) {
509 if (a[i] !== b[i]) {
510 x = a[i];
511 y = b[i];
512 break
513 }
514 }
515
516 if (x < y) return -1
517 if (y < x) return 1
518 return 0
519 };
520
521 Buffer.isEncoding = function isEncoding (encoding) {
522 switch (String(encoding).toLowerCase()) {
523 case 'hex':
524 case 'utf8':
525 case 'utf-8':
526 case 'ascii':
527 case 'latin1':
528 case 'binary':
529 case 'base64':
530 case 'ucs2':
531 case 'ucs-2':
532 case 'utf16le':
533 case 'utf-16le':
534 return true
535 default:
536 return false
537 }
538 };
539
540 Buffer.concat = function concat (list, length) {
541 if (!isArray(list)) {
542 throw new TypeError('"list" argument must be an Array of Buffers')
543 }
544
545 if (list.length === 0) {
546 return Buffer.alloc(0)
547 }
548
549 var i;
550 if (length === undefined) {
551 length = 0;
552 for (i = 0; i < list.length; ++i) {
553 length += list[i].length;
554 }
555 }
556
557 var buffer = Buffer.allocUnsafe(length);
558 var pos = 0;
559 for (i = 0; i < list.length; ++i) {
560 var buf = list[i];
561 if (!internalIsBuffer(buf)) {
562 throw new TypeError('"list" argument must be an Array of Buffers')
563 }
564 buf.copy(buffer, pos);
565 pos += buf.length;
566 }
567 return buffer
568 };
569
570 function byteLength (string, encoding) {
571 if (internalIsBuffer(string)) {
572 return string.length
573 }
574 if (typeof ArrayBuffer !== 'undefined' && typeof ArrayBuffer.isView === 'function' &&
575 (ArrayBuffer.isView(string) || string instanceof ArrayBuffer)) {
576 return string.byteLength
577 }
578 if (typeof string !== 'string') {
579 string = '' + string;
580 }
581
582 var len = string.length;
583 if (len === 0) return 0
584
585 // Use a for loop to avoid recursion
586 var loweredCase = false;
587 for (;;) {
588 switch (encoding) {
589 case 'ascii':
590 case 'latin1':
591 case 'binary':
592 return len
593 case 'utf8':
594 case 'utf-8':
595 case undefined:
596 return utf8ToBytes(string).length
597 case 'ucs2':
598 case 'ucs-2':
599 case 'utf16le':
600 case 'utf-16le':
601 return len * 2
602 case 'hex':
603 return len >>> 1
604 case 'base64':
605 return base64ToBytes(string).length
606 default:
607 if (loweredCase) return utf8ToBytes(string).length // assume utf8
608 encoding = ('' + encoding).toLowerCase();
609 loweredCase = true;
610 }
611 }
612 }
613 Buffer.byteLength = byteLength;
614
615 function slowToString (encoding, start, end) {
616 var loweredCase = false;
617
618 // No need to verify that "this.length <= MAX_UINT32" since it's a read-only
619 // property of a typed array.
620
621 // This behaves neither like String nor Uint8Array in that we set start/end
622 // to their upper/lower bounds if the value passed is out of range.
623 // undefined is handled specially as per ECMA-262 6th Edition,
624 // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization.
625 if (start === undefined || start < 0) {
626 start = 0;
627 }
628 // Return early if start > this.length. Done here to prevent potential uint32
629 // coercion fail below.
630 if (start > this.length) {
631 return ''
632 }
633
634 if (end === undefined || end > this.length) {
635 end = this.length;
636 }
637
638 if (end <= 0) {
639 return ''
640 }
641
642 // Force coersion to uint32. This will also coerce falsey/NaN values to 0.
643 end >>>= 0;
644 start >>>= 0;
645
646 if (end <= start) {
647 return ''
648 }
649
650 if (!encoding) encoding = 'utf8';
651
652 while (true) {
653 switch (encoding) {
654 case 'hex':
655 return hexSlice(this, start, end)
656
657 case 'utf8':
658 case 'utf-8':
659 return utf8Slice(this, start, end)
660
661 case 'ascii':
662 return asciiSlice(this, start, end)
663
664 case 'latin1':
665 case 'binary':
666 return latin1Slice(this, start, end)
667
668 case 'base64':
669 return base64Slice(this, start, end)
670
671 case 'ucs2':
672 case 'ucs-2':
673 case 'utf16le':
674 case 'utf-16le':
675 return utf16leSlice(this, start, end)
676
677 default:
678 if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
679 encoding = (encoding + '').toLowerCase();
680 loweredCase = true;
681 }
682 }
683 }
684
685 // The property is used by `Buffer.isBuffer` and `is-buffer` (in Safari 5-7) to detect
686 // Buffer instances.
687 Buffer.prototype._isBuffer = true;
688
689 function swap (b, n, m) {
690 var i = b[n];
691 b[n] = b[m];
692 b[m] = i;
693 }
694
695 Buffer.prototype.swap16 = function swap16 () {
696 var len = this.length;
697 if (len % 2 !== 0) {
698 throw new RangeError('Buffer size must be a multiple of 16-bits')
699 }
700 for (var i = 0; i < len; i += 2) {
701 swap(this, i, i + 1);
702 }
703 return this
704 };
705
706 Buffer.prototype.swap32 = function swap32 () {
707 var len = this.length;
708 if (len % 4 !== 0) {
709 throw new RangeError('Buffer size must be a multiple of 32-bits')
710 }
711 for (var i = 0; i < len; i += 4) {
712 swap(this, i, i + 3);
713 swap(this, i + 1, i + 2);
714 }
715 return this
716 };
717
718 Buffer.prototype.swap64 = function swap64 () {
719 var len = this.length;
720 if (len % 8 !== 0) {
721 throw new RangeError('Buffer size must be a multiple of 64-bits')
722 }
723 for (var i = 0; i < len; i += 8) {
724 swap(this, i, i + 7);
725 swap(this, i + 1, i + 6);
726 swap(this, i + 2, i + 5);
727 swap(this, i + 3, i + 4);
728 }
729 return this
730 };
731
732 Buffer.prototype.toString = function toString () {
733 var length = this.length | 0;
734 if (length === 0) return ''
735 if (arguments.length === 0) return utf8Slice(this, 0, length)
736 return slowToString.apply(this, arguments)
737 };
738
739 Buffer.prototype.equals = function equals (b) {
740 if (!internalIsBuffer(b)) throw new TypeError('Argument must be a Buffer')
741 if (this === b) return true
742 return Buffer.compare(this, b) === 0
743 };
744
745 Buffer.prototype.inspect = function inspect () {
746 var str = '';
747 var max = INSPECT_MAX_BYTES;
748 if (this.length > 0) {
749 str = this.toString('hex', 0, max).match(/.{2}/g).join(' ');
750 if (this.length > max) str += ' ... ';
751 }
752 return '<Buffer ' + str + '>'
753 };
754
755 Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) {
756 if (!internalIsBuffer(target)) {
757 throw new TypeError('Argument must be a Buffer')
758 }
759
760 if (start === undefined) {
761 start = 0;
762 }
763 if (end === undefined) {
764 end = target ? target.length : 0;
765 }
766 if (thisStart === undefined) {
767 thisStart = 0;
768 }
769 if (thisEnd === undefined) {
770 thisEnd = this.length;
771 }
772
773 if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) {
774 throw new RangeError('out of range index')
775 }
776
777 if (thisStart >= thisEnd && start >= end) {
778 return 0
779 }
780 if (thisStart >= thisEnd) {
781 return -1
782 }
783 if (start >= end) {
784 return 1
785 }
786
787 start >>>= 0;
788 end >>>= 0;
789 thisStart >>>= 0;
790 thisEnd >>>= 0;
791
792 if (this === target) return 0
793
794 var x = thisEnd - thisStart;
795 var y = end - start;
796 var len = Math.min(x, y);
797
798 var thisCopy = this.slice(thisStart, thisEnd);
799 var targetCopy = target.slice(start, end);
800
801 for (var i = 0; i < len; ++i) {
802 if (thisCopy[i] !== targetCopy[i]) {
803 x = thisCopy[i];
804 y = targetCopy[i];
805 break
806 }
807 }
808
809 if (x < y) return -1
810 if (y < x) return 1
811 return 0
812 };
813
814 // Finds either the first index of `val` in `buffer` at offset >= `byteOffset`,
815 // OR the last index of `val` in `buffer` at offset <= `byteOffset`.
816 //
817 // Arguments:
818 // - buffer - a Buffer to search
819 // - val - a string, Buffer, or number
820 // - byteOffset - an index into `buffer`; will be clamped to an int32
821 // - encoding - an optional encoding, relevant is val is a string
822 // - dir - true for indexOf, false for lastIndexOf
823 function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) {
824 // Empty buffer means no match
825 if (buffer.length === 0) return -1
826
827 // Normalize byteOffset
828 if (typeof byteOffset === 'string') {
829 encoding = byteOffset;
830 byteOffset = 0;
831 } else if (byteOffset > 0x7fffffff) {
832 byteOffset = 0x7fffffff;
833 } else if (byteOffset < -0x80000000) {
834 byteOffset = -0x80000000;
835 }
836 byteOffset = +byteOffset; // Coerce to Number.
837 if (isNaN(byteOffset)) {
838 // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer
839 byteOffset = dir ? 0 : (buffer.length - 1);
840 }
841
842 // Normalize byteOffset: negative offsets start from the end of the buffer
843 if (byteOffset < 0) byteOffset = buffer.length + byteOffset;
844 if (byteOffset >= buffer.length) {
845 if (dir) return -1
846 else byteOffset = buffer.length - 1;
847 } else if (byteOffset < 0) {
848 if (dir) byteOffset = 0;
849 else return -1
850 }
851
852 // Normalize val
853 if (typeof val === 'string') {
854 val = Buffer.from(val, encoding);
855 }
856
857 // Finally, search either indexOf (if dir is true) or lastIndexOf
858 if (internalIsBuffer(val)) {
859 // Special case: looking for empty string/buffer always fails
860 if (val.length === 0) {
861 return -1
862 }
863 return arrayIndexOf(buffer, val, byteOffset, encoding, dir)
864 } else if (typeof val === 'number') {
865 val = val & 0xFF; // Search for a byte value [0-255]
866 if (Buffer.TYPED_ARRAY_SUPPORT &&
867 typeof Uint8Array.prototype.indexOf === 'function') {
868 if (dir) {
869 return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset)
870 } else {
871 return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset)
872 }
873 }
874 return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir)
875 }
876
877 throw new TypeError('val must be string, number or Buffer')
878 }
879
880 function arrayIndexOf (arr, val, byteOffset, encoding, dir) {
881 var indexSize = 1;
882 var arrLength = arr.length;
883 var valLength = val.length;
884
885 if (encoding !== undefined) {
886 encoding = String(encoding).toLowerCase();
887 if (encoding === 'ucs2' || encoding === 'ucs-2' ||
888 encoding === 'utf16le' || encoding === 'utf-16le') {
889 if (arr.length < 2 || val.length < 2) {
890 return -1
891 }
892 indexSize = 2;
893 arrLength /= 2;
894 valLength /= 2;
895 byteOffset /= 2;
896 }
897 }
898
899 function read$$1 (buf, i) {
900 if (indexSize === 1) {
901 return buf[i]
902 } else {
903 return buf.readUInt16BE(i * indexSize)
904 }
905 }
906
907 var i;
908 if (dir) {
909 var foundIndex = -1;
910 for (i = byteOffset; i < arrLength; i++) {
911 if (read$$1(arr, i) === read$$1(val, foundIndex === -1 ? 0 : i - foundIndex)) {
912 if (foundIndex === -1) foundIndex = i;
913 if (i - foundIndex + 1 === valLength) return foundIndex * indexSize
914 } else {
915 if (foundIndex !== -1) i -= i - foundIndex;
916 foundIndex = -1;
917 }
918 }
919 } else {
920 if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength;
921 for (i = byteOffset; i >= 0; i--) {
922 var found = true;
923 for (var j = 0; j < valLength; j++) {
924 if (read$$1(arr, i + j) !== read$$1(val, j)) {
925 found = false;
926 break
927 }
928 }
929 if (found) return i
930 }
931 }
932
933 return -1
934 }
935
936 Buffer.prototype.includes = function includes (val, byteOffset, encoding) {
937 return this.indexOf(val, byteOffset, encoding) !== -1
938 };
939
940 Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) {
941 return bidirectionalIndexOf(this, val, byteOffset, encoding, true)
942 };
943
944 Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) {
945 return bidirectionalIndexOf(this, val, byteOffset, encoding, false)
946 };
947
948 function hexWrite (buf, string, offset, length) {
949 offset = Number(offset) || 0;
950 var remaining = buf.length - offset;
951 if (!length) {
952 length = remaining;
953 } else {
954 length = Number(length);
955 if (length > remaining) {
956 length = remaining;
957 }
958 }
959
960 // must be an even number of digits
961 var strLen = string.length;
962 if (strLen % 2 !== 0) throw new TypeError('Invalid hex string')
963
964 if (length > strLen / 2) {
965 length = strLen / 2;
966 }
967 for (var i = 0; i < length; ++i) {
968 var parsed = parseInt(string.substr(i * 2, 2), 16);
969 if (isNaN(parsed)) return i
970 buf[offset + i] = parsed;
971 }
972 return i
973 }
974
975 function utf8Write (buf, string, offset, length) {
976 return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
977 }
978
979 function asciiWrite (buf, string, offset, length) {
980 return blitBuffer(asciiToBytes(string), buf, offset, length)
981 }
982
983 function latin1Write (buf, string, offset, length) {
984 return asciiWrite(buf, string, offset, length)
985 }
986
987 function base64Write (buf, string, offset, length) {
988 return blitBuffer(base64ToBytes(string), buf, offset, length)
989 }
990
991 function ucs2Write (buf, string, offset, length) {
992 return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
993 }
994
995 Buffer.prototype.write = function write$$1 (string, offset, length, encoding) {
996 // Buffer#write(string)
997 if (offset === undefined) {
998 encoding = 'utf8';
999 length = this.length;
1000 offset = 0;
1001 // Buffer#write(string, encoding)
1002 } else if (length === undefined && typeof offset === 'string') {
1003 encoding = offset;
1004 length = this.length;
1005 offset = 0;
1006 // Buffer#write(string, offset[, length][, encoding])
1007 } else if (isFinite(offset)) {
1008 offset = offset | 0;
1009 if (isFinite(length)) {
1010 length = length | 0;
1011 if (encoding === undefined) encoding = 'utf8';
1012 } else {
1013 encoding = length;
1014 length = undefined;
1015 }
1016 // legacy write(string, encoding, offset, length) - remove in v0.13
1017 } else {
1018 throw new Error(
1019 'Buffer.write(string, encoding, offset[, length]) is no longer supported'
1020 )
1021 }
1022
1023 var remaining = this.length - offset;
1024 if (length === undefined || length > remaining) length = remaining;
1025
1026 if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
1027 throw new RangeError('Attempt to write outside buffer bounds')
1028 }
1029
1030 if (!encoding) encoding = 'utf8';
1031
1032 var loweredCase = false;
1033 for (;;) {
1034 switch (encoding) {
1035 case 'hex':
1036 return hexWrite(this, string, offset, length)
1037
1038 case 'utf8':
1039 case 'utf-8':
1040 return utf8Write(this, string, offset, length)
1041
1042 case 'ascii':
1043 return asciiWrite(this, string, offset, length)
1044
1045 case 'latin1':
1046 case 'binary':
1047 return latin1Write(this, string, offset, length)
1048
1049 case 'base64':
1050 // Warning: maxLength not taken into account in base64Write
1051 return base64Write(this, string, offset, length)
1052
1053 case 'ucs2':
1054 case 'ucs-2':
1055 case 'utf16le':
1056 case 'utf-16le':
1057 return ucs2Write(this, string, offset, length)
1058
1059 default:
1060 if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
1061 encoding = ('' + encoding).toLowerCase();
1062 loweredCase = true;
1063 }
1064 }
1065 };
1066
1067 Buffer.prototype.toJSON = function toJSON () {
1068 return {
1069 type: 'Buffer',
1070 data: Array.prototype.slice.call(this._arr || this, 0)
1071 }
1072 };
1073
1074 function base64Slice (buf, start, end) {
1075 if (start === 0 && end === buf.length) {
1076 return fromByteArray(buf)
1077 } else {
1078 return fromByteArray(buf.slice(start, end))
1079 }
1080 }
1081
1082 function utf8Slice (buf, start, end) {
1083 end = Math.min(buf.length, end);
1084 var res = [];
1085
1086 var i = start;
1087 while (i < end) {
1088 var firstByte = buf[i];
1089 var codePoint = null;
1090 var bytesPerSequence = (firstByte > 0xEF) ? 4
1091 : (firstByte > 0xDF) ? 3
1092 : (firstByte > 0xBF) ? 2
1093 : 1;
1094
1095 if (i + bytesPerSequence <= end) {
1096 var secondByte, thirdByte, fourthByte, tempCodePoint;
1097
1098 switch (bytesPerSequence) {
1099 case 1:
1100 if (firstByte < 0x80) {
1101 codePoint = firstByte;
1102 }
1103 break
1104 case 2:
1105 secondByte = buf[i + 1];
1106 if ((secondByte & 0xC0) === 0x80) {
1107 tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F);
1108 if (tempCodePoint > 0x7F) {
1109 codePoint = tempCodePoint;
1110 }
1111 }
1112 break
1113 case 3:
1114 secondByte = buf[i + 1];
1115 thirdByte = buf[i + 2];
1116 if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
1117 tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F);
1118 if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
1119 codePoint = tempCodePoint;
1120 }
1121 }
1122 break
1123 case 4:
1124 secondByte = buf[i + 1];
1125 thirdByte = buf[i + 2];
1126 fourthByte = buf[i + 3];
1127 if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
1128 tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F);
1129 if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
1130 codePoint = tempCodePoint;
1131 }
1132 }
1133 }
1134 }
1135
1136 if (codePoint === null) {
1137 // we did not generate a valid codePoint so insert a
1138 // replacement char (U+FFFD) and advance only 1 byte
1139 codePoint = 0xFFFD;
1140 bytesPerSequence = 1;
1141 } else if (codePoint > 0xFFFF) {
1142 // encode to utf16 (surrogate pair dance)
1143 codePoint -= 0x10000;
1144 res.push(codePoint >>> 10 & 0x3FF | 0xD800);
1145 codePoint = 0xDC00 | codePoint & 0x3FF;
1146 }
1147
1148 res.push(codePoint);
1149 i += bytesPerSequence;
1150 }
1151
1152 return decodeCodePointsArray(res)
1153 }
1154
1155 // Based on http://stackoverflow.com/a/22747272/680742, the browser with
1156 // the lowest limit is Chrome, with 0x10000 args.
1157 // We go 1 magnitude less, for safety
1158 var MAX_ARGUMENTS_LENGTH = 0x1000;
1159
1160 function decodeCodePointsArray (codePoints) {
1161 var len = codePoints.length;
1162 if (len <= MAX_ARGUMENTS_LENGTH) {
1163 return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
1164 }
1165
1166 // Decode in chunks to avoid "call stack size exceeded".
1167 var res = '';
1168 var i = 0;
1169 while (i < len) {
1170 res += String.fromCharCode.apply(
1171 String,
1172 codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
1173 );
1174 }
1175 return res
1176 }
1177
1178 function asciiSlice (buf, start, end) {
1179 var ret = '';
1180 end = Math.min(buf.length, end);
1181
1182 for (var i = start; i < end; ++i) {
1183 ret += String.fromCharCode(buf[i] & 0x7F);
1184 }
1185 return ret
1186 }
1187
1188 function latin1Slice (buf, start, end) {
1189 var ret = '';
1190 end = Math.min(buf.length, end);
1191
1192 for (var i = start; i < end; ++i) {
1193 ret += String.fromCharCode(buf[i]);
1194 }
1195 return ret
1196 }
1197
1198 function hexSlice (buf, start, end) {
1199 var len = buf.length;
1200
1201 if (!start || start < 0) start = 0;
1202 if (!end || end < 0 || end > len) end = len;
1203
1204 var out = '';
1205 for (var i = start; i < end; ++i) {
1206 out += toHex(buf[i]);
1207 }
1208 return out
1209 }
1210
1211 function utf16leSlice (buf, start, end) {
1212 var bytes = buf.slice(start, end);
1213 var res = '';
1214 for (var i = 0; i < bytes.length; i += 2) {
1215 res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256);
1216 }
1217 return res
1218 }
1219
1220 Buffer.prototype.slice = function slice (start, end) {
1221 var len = this.length;
1222 start = ~~start;
1223 end = end === undefined ? len : ~~end;
1224
1225 if (start < 0) {
1226 start += len;
1227 if (start < 0) start = 0;
1228 } else if (start > len) {
1229 start = len;
1230 }
1231
1232 if (end < 0) {
1233 end += len;
1234 if (end < 0) end = 0;
1235 } else if (end > len) {
1236 end = len;
1237 }
1238
1239 if (end < start) end = start;
1240
1241 var newBuf;
1242 if (Buffer.TYPED_ARRAY_SUPPORT) {
1243 newBuf = this.subarray(start, end);
1244 newBuf.__proto__ = Buffer.prototype;
1245 } else {
1246 var sliceLen = end - start;
1247 newBuf = new Buffer(sliceLen, undefined);
1248 for (var i = 0; i < sliceLen; ++i) {
1249 newBuf[i] = this[i + start];
1250 }
1251 }
1252
1253 return newBuf
1254 };
1255
1256 /*
1257 * Need to make sure that buffer isn't trying to write out of bounds.
1258 */
1259 function checkOffset (offset, ext, length) {
1260 if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
1261 if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
1262 }
1263
1264 Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
1265 offset = offset | 0;
1266 byteLength = byteLength | 0;
1267 if (!noAssert) checkOffset(offset, byteLength, this.length);
1268
1269 var val = this[offset];
1270 var mul = 1;
1271 var i = 0;
1272 while (++i < byteLength && (mul *= 0x100)) {
1273 val += this[offset + i] * mul;
1274 }
1275
1276 return val
1277 };
1278
1279 Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
1280 offset = offset | 0;
1281 byteLength = byteLength | 0;
1282 if (!noAssert) {
1283 checkOffset(offset, byteLength, this.length);
1284 }
1285
1286 var val = this[offset + --byteLength];
1287 var mul = 1;
1288 while (byteLength > 0 && (mul *= 0x100)) {
1289 val += this[offset + --byteLength] * mul;
1290 }
1291
1292 return val
1293 };
1294
1295 Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
1296 if (!noAssert) checkOffset(offset, 1, this.length);
1297 return this[offset]
1298 };
1299
1300 Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
1301 if (!noAssert) checkOffset(offset, 2, this.length);
1302 return this[offset] | (this[offset + 1] << 8)
1303 };
1304
1305 Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
1306 if (!noAssert) checkOffset(offset, 2, this.length);
1307 return (this[offset] << 8) | this[offset + 1]
1308 };
1309
1310 Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
1311 if (!noAssert) checkOffset(offset, 4, this.length);
1312
1313 return ((this[offset]) |
1314 (this[offset + 1] << 8) |
1315 (this[offset + 2] << 16)) +
1316 (this[offset + 3] * 0x1000000)
1317 };
1318
1319 Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
1320 if (!noAssert) checkOffset(offset, 4, this.length);
1321
1322 return (this[offset] * 0x1000000) +
1323 ((this[offset + 1] << 16) |
1324 (this[offset + 2] << 8) |
1325 this[offset + 3])
1326 };
1327
1328 Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
1329 offset = offset | 0;
1330 byteLength = byteLength | 0;
1331 if (!noAssert) checkOffset(offset, byteLength, this.length);
1332
1333 var val = this[offset];
1334 var mul = 1;
1335 var i = 0;
1336 while (++i < byteLength && (mul *= 0x100)) {
1337 val += this[offset + i] * mul;
1338 }
1339 mul *= 0x80;
1340
1341 if (val >= mul) val -= Math.pow(2, 8 * byteLength);
1342
1343 return val
1344 };
1345
1346 Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
1347 offset = offset | 0;
1348 byteLength = byteLength | 0;
1349 if (!noAssert) checkOffset(offset, byteLength, this.length);
1350
1351 var i = byteLength;
1352 var mul = 1;
1353 var val = this[offset + --i];
1354 while (i > 0 && (mul *= 0x100)) {
1355 val += this[offset + --i] * mul;
1356 }
1357 mul *= 0x80;
1358
1359 if (val >= mul) val -= Math.pow(2, 8 * byteLength);
1360
1361 return val
1362 };
1363
1364 Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
1365 if (!noAssert) checkOffset(offset, 1, this.length);
1366 if (!(this[offset] & 0x80)) return (this[offset])
1367 return ((0xff - this[offset] + 1) * -1)
1368 };
1369
1370 Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
1371 if (!noAssert) checkOffset(offset, 2, this.length);
1372 var val = this[offset] | (this[offset + 1] << 8);
1373 return (val & 0x8000) ? val | 0xFFFF0000 : val
1374 };
1375
1376 Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
1377 if (!noAssert) checkOffset(offset, 2, this.length);
1378 var val = this[offset + 1] | (this[offset] << 8);
1379 return (val & 0x8000) ? val | 0xFFFF0000 : val
1380 };
1381
1382 Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
1383 if (!noAssert) checkOffset(offset, 4, this.length);
1384
1385 return (this[offset]) |
1386 (this[offset + 1] << 8) |
1387 (this[offset + 2] << 16) |
1388 (this[offset + 3] << 24)
1389 };
1390
1391 Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
1392 if (!noAssert) checkOffset(offset, 4, this.length);
1393
1394 return (this[offset] << 24) |
1395 (this[offset + 1] << 16) |
1396 (this[offset + 2] << 8) |
1397 (this[offset + 3])
1398 };
1399
1400 Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
1401 if (!noAssert) checkOffset(offset, 4, this.length);
1402 return read(this, offset, true, 23, 4)
1403 };
1404
1405 Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
1406 if (!noAssert) checkOffset(offset, 4, this.length);
1407 return read(this, offset, false, 23, 4)
1408 };
1409
1410 Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
1411 if (!noAssert) checkOffset(offset, 8, this.length);
1412 return read(this, offset, true, 52, 8)
1413 };
1414
1415 Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
1416 if (!noAssert) checkOffset(offset, 8, this.length);
1417 return read(this, offset, false, 52, 8)
1418 };
1419
1420 function checkInt (buf, value, offset, ext, max, min) {
1421 if (!internalIsBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance')
1422 if (value > max || value < min) throw new RangeError('"value" argument is out of bounds')
1423 if (offset + ext > buf.length) throw new RangeError('Index out of range')
1424 }
1425
1426 Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
1427 value = +value;
1428 offset = offset | 0;
1429 byteLength = byteLength | 0;
1430 if (!noAssert) {
1431 var maxBytes = Math.pow(2, 8 * byteLength) - 1;
1432 checkInt(this, value, offset, byteLength, maxBytes, 0);
1433 }
1434
1435 var mul = 1;
1436 var i = 0;
1437 this[offset] = value & 0xFF;
1438 while (++i < byteLength && (mul *= 0x100)) {
1439 this[offset + i] = (value / mul) & 0xFF;
1440 }
1441
1442 return offset + byteLength
1443 };
1444
1445 Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
1446 value = +value;
1447 offset = offset | 0;
1448 byteLength = byteLength | 0;
1449 if (!noAssert) {
1450 var maxBytes = Math.pow(2, 8 * byteLength) - 1;
1451 checkInt(this, value, offset, byteLength, maxBytes, 0);
1452 }
1453
1454 var i = byteLength - 1;
1455 var mul = 1;
1456 this[offset + i] = value & 0xFF;
1457 while (--i >= 0 && (mul *= 0x100)) {
1458 this[offset + i] = (value / mul) & 0xFF;
1459 }
1460
1461 return offset + byteLength
1462 };
1463
1464 Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
1465 value = +value;
1466 offset = offset | 0;
1467 if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0);
1468 if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value);
1469 this[offset] = (value & 0xff);
1470 return offset + 1
1471 };
1472
1473 function objectWriteUInt16 (buf, value, offset, littleEndian) {
1474 if (value < 0) value = 0xffff + value + 1;
1475 for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; ++i) {
1476 buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
1477 (littleEndian ? i : 1 - i) * 8;
1478 }
1479 }
1480
1481 Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
1482 value = +value;
1483 offset = offset | 0;
1484 if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0);
1485 if (Buffer.TYPED_ARRAY_SUPPORT) {
1486 this[offset] = (value & 0xff);
1487 this[offset + 1] = (value >>> 8);
1488 } else {
1489 objectWriteUInt16(this, value, offset, true);
1490 }
1491 return offset + 2
1492 };
1493
1494 Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
1495 value = +value;
1496 offset = offset | 0;
1497 if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0);
1498 if (Buffer.TYPED_ARRAY_SUPPORT) {
1499 this[offset] = (value >>> 8);
1500 this[offset + 1] = (value & 0xff);
1501 } else {
1502 objectWriteUInt16(this, value, offset, false);
1503 }
1504 return offset + 2
1505 };
1506
1507 function objectWriteUInt32 (buf, value, offset, littleEndian) {
1508 if (value < 0) value = 0xffffffff + value + 1;
1509 for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; ++i) {
1510 buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff;
1511 }
1512 }
1513
1514 Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
1515 value = +value;
1516 offset = offset | 0;
1517 if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0);
1518 if (Buffer.TYPED_ARRAY_SUPPORT) {
1519 this[offset + 3] = (value >>> 24);
1520 this[offset + 2] = (value >>> 16);
1521 this[offset + 1] = (value >>> 8);
1522 this[offset] = (value & 0xff);
1523 } else {
1524 objectWriteUInt32(this, value, offset, true);
1525 }
1526 return offset + 4
1527 };
1528
1529 Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
1530 value = +value;
1531 offset = offset | 0;
1532 if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0);
1533 if (Buffer.TYPED_ARRAY_SUPPORT) {
1534 this[offset] = (value >>> 24);
1535 this[offset + 1] = (value >>> 16);
1536 this[offset + 2] = (value >>> 8);
1537 this[offset + 3] = (value & 0xff);
1538 } else {
1539 objectWriteUInt32(this, value, offset, false);
1540 }
1541 return offset + 4
1542 };
1543
1544 Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
1545 value = +value;
1546 offset = offset | 0;
1547 if (!noAssert) {
1548 var limit = Math.pow(2, 8 * byteLength - 1);
1549
1550 checkInt(this, value, offset, byteLength, limit - 1, -limit);
1551 }
1552
1553 var i = 0;
1554 var mul = 1;
1555 var sub = 0;
1556 this[offset] = value & 0xFF;
1557 while (++i < byteLength && (mul *= 0x100)) {
1558 if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) {
1559 sub = 1;
1560 }
1561 this[offset + i] = ((value / mul) >> 0) - sub & 0xFF;
1562 }
1563
1564 return offset + byteLength
1565 };
1566
1567 Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
1568 value = +value;
1569 offset = offset | 0;
1570 if (!noAssert) {
1571 var limit = Math.pow(2, 8 * byteLength - 1);
1572
1573 checkInt(this, value, offset, byteLength, limit - 1, -limit);
1574 }
1575
1576 var i = byteLength - 1;
1577 var mul = 1;
1578 var sub = 0;
1579 this[offset + i] = value & 0xFF;
1580 while (--i >= 0 && (mul *= 0x100)) {
1581 if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) {
1582 sub = 1;
1583 }
1584 this[offset + i] = ((value / mul) >> 0) - sub & 0xFF;
1585 }
1586
1587 return offset + byteLength
1588 };
1589
1590 Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
1591 value = +value;
1592 offset = offset | 0;
1593 if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80);
1594 if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value);
1595 if (value < 0) value = 0xff + value + 1;
1596 this[offset] = (value & 0xff);
1597 return offset + 1
1598 };
1599
1600 Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
1601 value = +value;
1602 offset = offset | 0;
1603 if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000);
1604 if (Buffer.TYPED_ARRAY_SUPPORT) {
1605 this[offset] = (value & 0xff);
1606 this[offset + 1] = (value >>> 8);
1607 } else {
1608 objectWriteUInt16(this, value, offset, true);
1609 }
1610 return offset + 2
1611 };
1612
1613 Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
1614 value = +value;
1615 offset = offset | 0;
1616 if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000);
1617 if (Buffer.TYPED_ARRAY_SUPPORT) {
1618 this[offset] = (value >>> 8);
1619 this[offset + 1] = (value & 0xff);
1620 } else {
1621 objectWriteUInt16(this, value, offset, false);
1622 }
1623 return offset + 2
1624 };
1625
1626 Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
1627 value = +value;
1628 offset = offset | 0;
1629 if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000);
1630 if (Buffer.TYPED_ARRAY_SUPPORT) {
1631 this[offset] = (value & 0xff);
1632 this[offset + 1] = (value >>> 8);
1633 this[offset + 2] = (value >>> 16);
1634 this[offset + 3] = (value >>> 24);
1635 } else {
1636 objectWriteUInt32(this, value, offset, true);
1637 }
1638 return offset + 4
1639 };
1640
1641 Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
1642 value = +value;
1643 offset = offset | 0;
1644 if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000);
1645 if (value < 0) value = 0xffffffff + value + 1;
1646 if (Buffer.TYPED_ARRAY_SUPPORT) {
1647 this[offset] = (value >>> 24);
1648 this[offset + 1] = (value >>> 16);
1649 this[offset + 2] = (value >>> 8);
1650 this[offset + 3] = (value & 0xff);
1651 } else {
1652 objectWriteUInt32(this, value, offset, false);
1653 }
1654 return offset + 4
1655 };
1656
1657 function checkIEEE754 (buf, value, offset, ext, max, min) {
1658 if (offset + ext > buf.length) throw new RangeError('Index out of range')
1659 if (offset < 0) throw new RangeError('Index out of range')
1660 }
1661
1662 function writeFloat (buf, value, offset, littleEndian, noAssert) {
1663 if (!noAssert) {
1664 checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38);
1665 }
1666 write(buf, value, offset, littleEndian, 23, 4);
1667 return offset + 4
1668 }
1669
1670 Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
1671 return writeFloat(this, value, offset, true, noAssert)
1672 };
1673
1674 Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
1675 return writeFloat(this, value, offset, false, noAssert)
1676 };
1677
1678 function writeDouble (buf, value, offset, littleEndian, noAssert) {
1679 if (!noAssert) {
1680 checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308);
1681 }
1682 write(buf, value, offset, littleEndian, 52, 8);
1683 return offset + 8
1684 }
1685
1686 Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
1687 return writeDouble(this, value, offset, true, noAssert)
1688 };
1689
1690 Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
1691 return writeDouble(this, value, offset, false, noAssert)
1692 };
1693
1694 // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
1695 Buffer.prototype.copy = function copy (target, targetStart, start, end) {
1696 if (!start) start = 0;
1697 if (!end && end !== 0) end = this.length;
1698 if (targetStart >= target.length) targetStart = target.length;
1699 if (!targetStart) targetStart = 0;
1700 if (end > 0 && end < start) end = start;
1701
1702 // Copy 0 bytes; we're done
1703 if (end === start) return 0
1704 if (target.length === 0 || this.length === 0) return 0
1705
1706 // Fatal error conditions
1707 if (targetStart < 0) {
1708 throw new RangeError('targetStart out of bounds')
1709 }
1710 if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds')
1711 if (end < 0) throw new RangeError('sourceEnd out of bounds')
1712
1713 // Are we oob?
1714 if (end > this.length) end = this.length;
1715 if (target.length - targetStart < end - start) {
1716 end = target.length - targetStart + start;
1717 }
1718
1719 var len = end - start;
1720 var i;
1721
1722 if (this === target && start < targetStart && targetStart < end) {
1723 // descending copy from end
1724 for (i = len - 1; i >= 0; --i) {
1725 target[i + targetStart] = this[i + start];
1726 }
1727 } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
1728 // ascending copy from start
1729 for (i = 0; i < len; ++i) {
1730 target[i + targetStart] = this[i + start];
1731 }
1732 } else {
1733 Uint8Array.prototype.set.call(
1734 target,
1735 this.subarray(start, start + len),
1736 targetStart
1737 );
1738 }
1739
1740 return len
1741 };
1742
1743 // Usage:
1744 // buffer.fill(number[, offset[, end]])
1745 // buffer.fill(buffer[, offset[, end]])
1746 // buffer.fill(string[, offset[, end]][, encoding])
1747 Buffer.prototype.fill = function fill (val, start, end, encoding) {
1748 // Handle string cases:
1749 if (typeof val === 'string') {
1750 if (typeof start === 'string') {
1751 encoding = start;
1752 start = 0;
1753 end = this.length;
1754 } else if (typeof end === 'string') {
1755 encoding = end;
1756 end = this.length;
1757 }
1758 if (val.length === 1) {
1759 var code = val.charCodeAt(0);
1760 if (code < 256) {
1761 val = code;
1762 }
1763 }
1764 if (encoding !== undefined && typeof encoding !== 'string') {
1765 throw new TypeError('encoding must be a string')
1766 }
1767 if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) {
1768 throw new TypeError('Unknown encoding: ' + encoding)
1769 }
1770 } else if (typeof val === 'number') {
1771 val = val & 255;
1772 }
1773
1774 // Invalid ranges are not set to a default, so can range check early.
1775 if (start < 0 || this.length < start || this.length < end) {
1776 throw new RangeError('Out of range index')
1777 }
1778
1779 if (end <= start) {
1780 return this
1781 }
1782
1783 start = start >>> 0;
1784 end = end === undefined ? this.length : end >>> 0;
1785
1786 if (!val) val = 0;
1787
1788 var i;
1789 if (typeof val === 'number') {
1790 for (i = start; i < end; ++i) {
1791 this[i] = val;
1792 }
1793 } else {
1794 var bytes = internalIsBuffer(val)
1795 ? val
1796 : utf8ToBytes(new Buffer(val, encoding).toString());
1797 var len = bytes.length;
1798 for (i = 0; i < end - start; ++i) {
1799 this[i + start] = bytes[i % len];
1800 }
1801 }
1802
1803 return this
1804 };
1805
1806 // HELPER FUNCTIONS
1807 // ================
1808
1809 var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g;
1810
1811 function base64clean (str) {
1812 // Node strips out invalid characters like \n and \t from the string, base64-js does not
1813 str = stringtrim(str).replace(INVALID_BASE64_RE, '');
1814 // Node converts strings with length < 2 to ''
1815 if (str.length < 2) return ''
1816 // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
1817 while (str.length % 4 !== 0) {
1818 str = str + '=';
1819 }
1820 return str
1821 }
1822
1823 function stringtrim (str) {
1824 if (str.trim) return str.trim()
1825 return str.replace(/^\s+|\s+$/g, '')
1826 }
1827
1828 function toHex (n) {
1829 if (n < 16) return '0' + n.toString(16)
1830 return n.toString(16)
1831 }
1832
1833 function utf8ToBytes (string, units) {
1834 units = units || Infinity;
1835 var codePoint;
1836 var length = string.length;
1837 var leadSurrogate = null;
1838 var bytes = [];
1839
1840 for (var i = 0; i < length; ++i) {
1841 codePoint = string.charCodeAt(i);
1842
1843 // is surrogate component
1844 if (codePoint > 0xD7FF && codePoint < 0xE000) {
1845 // last char was a lead
1846 if (!leadSurrogate) {
1847 // no lead yet
1848 if (codePoint > 0xDBFF) {
1849 // unexpected trail
1850 if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD);
1851 continue
1852 } else if (i + 1 === length) {
1853 // unpaired lead
1854 if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD);
1855 continue
1856 }
1857
1858 // valid lead
1859 leadSurrogate = codePoint;
1860
1861 continue
1862 }
1863
1864 // 2 leads in a row
1865 if (codePoint < 0xDC00) {
1866 if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD);
1867 leadSurrogate = codePoint;
1868 continue
1869 }
1870
1871 // valid surrogate pair
1872 codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000;
1873 } else if (leadSurrogate) {
1874 // valid bmp char, but last char was a lead
1875 if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD);
1876 }
1877
1878 leadSurrogate = null;
1879
1880 // encode utf8
1881 if (codePoint < 0x80) {
1882 if ((units -= 1) < 0) break
1883 bytes.push(codePoint);
1884 } else if (codePoint < 0x800) {
1885 if ((units -= 2) < 0) break
1886 bytes.push(
1887 codePoint >> 0x6 | 0xC0,
1888 codePoint & 0x3F | 0x80
1889 );
1890 } else if (codePoint < 0x10000) {
1891 if ((units -= 3) < 0) break
1892 bytes.push(
1893 codePoint >> 0xC | 0xE0,
1894 codePoint >> 0x6 & 0x3F | 0x80,
1895 codePoint & 0x3F | 0x80
1896 );
1897 } else if (codePoint < 0x110000) {
1898 if ((units -= 4) < 0) break
1899 bytes.push(
1900 codePoint >> 0x12 | 0xF0,
1901 codePoint >> 0xC & 0x3F | 0x80,
1902 codePoint >> 0x6 & 0x3F | 0x80,
1903 codePoint & 0x3F | 0x80
1904 );
1905 } else {
1906 throw new Error('Invalid code point')
1907 }
1908 }
1909
1910 return bytes
1911 }
1912
1913 function asciiToBytes (str) {
1914 var byteArray = [];
1915 for (var i = 0; i < str.length; ++i) {
1916 // Node's code seems to be doing this and not & 0x7F..
1917 byteArray.push(str.charCodeAt(i) & 0xFF);
1918 }
1919 return byteArray
1920 }
1921
1922 function utf16leToBytes (str, units) {
1923 var c, hi, lo;
1924 var byteArray = [];
1925 for (var i = 0; i < str.length; ++i) {
1926 if ((units -= 2) < 0) break
1927
1928 c = str.charCodeAt(i);
1929 hi = c >> 8;
1930 lo = c % 256;
1931 byteArray.push(lo);
1932 byteArray.push(hi);
1933 }
1934
1935 return byteArray
1936 }
1937
1938
1939 function base64ToBytes (str) {
1940 return toByteArray(base64clean(str))
1941 }
1942
1943 function blitBuffer (src, dst, offset, length) {
1944 for (var i = 0; i < length; ++i) {
1945 if ((i + offset >= dst.length) || (i >= src.length)) break
1946 dst[i + offset] = src[i];
1947 }
1948 return i
1949 }
1950
1951 function isnan (val) {
1952 return val !== val // eslint-disable-line no-self-compare
1953 }
1954
1955
1956 // the following is from is-buffer, also by Feross Aboukhadijeh and with same lisence
1957 // The _isBuffer check is for Safari 5-7 support, because it's missing
1958 // Object.prototype.constructor. Remove this eventually
1959 function isBuffer(obj) {
1960 return obj != null && (!!obj._isBuffer || isFastBuffer(obj) || isSlowBuffer(obj))
1961 }
1962
1963 function isFastBuffer (obj) {
1964 return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)
1965 }
1966
1967 // For Node v0.10 support. Remove this eventually.
1968 function isSlowBuffer (obj) {
1969 return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isFastBuffer(obj.slice(0, 0))
1970 }
1971
1972 var BASE_64 = 'base64';
1973 /**
1974 * Decodes the base64 encoded string into a `Buffer` or `string` depending on
1975 * the presence of `outputEncoding` parameter.
1976 * @hidden
1977 * @param {string} input
1978 * @param {string} [outputEncoding] - If provided, specifies the output string
1979 * encoding.
1980 * @returns {Buffer|string}
1981 */
1982 function base64Decode(input, outputEncoding) {
1983 if (outputEncoding) {
1984 return Buffer.from(input, BASE_64).toString(outputEncoding);
1985 }
1986 return Buffer.from(input, BASE_64);
1987 }
1988 /**
1989 * Encodes the `input` bytes into a string using base64 encoding.
1990 * If `input` is a string, it is first converted to byte array by decoding
1991 * it using `inputEncoding`.
1992 * @hidden
1993 * @param {Buffer | string} input
1994 * @param {string} inputEncoding
1995 * @returns {string}
1996 */
1997 function base64Encode(input, inputEncoding) {
1998 var buffer;
1999 if (Buffer.isBuffer(input)) {
2000 buffer = input;
2001 }
2002 else if (inputEncoding && Buffer.isEncoding(inputEncoding)) {
2003 buffer = Buffer.from(input, inputEncoding);
2004 }
2005 else {
2006 buffer = Buffer.from(input);
2007 }
2008 return buffer.toString(BASE_64);
2009 }
2010 /**
2011 * Converts regular base64 encoded string to URL-safe base64 encoded string.
2012 * @hidden
2013 * @param {string} input - Regular base64 encoded string.
2014 * @returns {string} - URL-safe base64 encoded string.
2015 */
2016 function base64UrlFromBase64(input) {
2017 input = input.split('=')[0];
2018 input = input.replace(/\+/g, '-').replace(/\//g, '_');
2019 return input;
2020 }
2021 /**
2022 * Converts URL-safe base64 encoded string to regular base64 encoded string.
2023 * @hidden
2024 * @param {string} input - URL-safe base64 encoded string.
2025 * @returns {string} - Regular base64 encoded string.
2026 */
2027 function base64UrlToBase64(input) {
2028 input = input.replace(/-/g, '+').replace(/_/g, '/');
2029 switch (input.length % 4) {
2030 case 0: break; // no padding needed
2031 case 2:
2032 input = input + '==';
2033 break;
2034 case 3:
2035 input = input + '=';
2036 break;
2037 default:
2038 throw new Error('Invalid base64 string');
2039 }
2040 return input;
2041 }
2042 /**
2043 * * Encodes the `input` bytes into a string using URL-safe base64 encoding.
2044 * If `input` is a string, it is first converted to byte array by decoding
2045 * it using `inputEncoding`.
2046 *
2047 * @hidden
2048 *
2049 * @param {string | Buffer} input - The input.
2050 * @param {string} inputEncoding - If `input` is a string, this parameter
2051 * specifies the encoding of the input string. If `input` is a `Buffer`, this
2052 * parameter is ignored.
2053 * @returns {string}
2054 */
2055 function base64UrlEncode(input, inputEncoding) {
2056 var output = base64Encode(input, inputEncoding);
2057 return base64UrlFromBase64(output);
2058 }
2059 /**
2060 * Decodes the URL-safe base64-encoded `input` string into a `Buffer` or
2061 * `string` depending on the presence of `outputEncoding` parameter.
2062 *
2063 * @hidden
2064 *
2065 * @param {string} input
2066 * @param {string} [outputEncoding] - If provided, specifies the output string
2067 * encoding.
2068 * @returns {Buffer|string}
2069 */
2070 function base64UrlDecode(input, outputEncoding) {
2071 input = base64UrlToBase64(input);
2072 if (outputEncoding) {
2073 return base64Decode(input, outputEncoding);
2074 }
2075 return base64Decode(input);
2076 }
2077
2078 /**
2079 * Converts javascript date object or timestamp in milliseconds
2080 * to Unix timestamp.
2081 *
2082 * @hidden
2083 *
2084 * @param {Date | number} date - The date or timestamp to convert.
2085 * @returns {number}
2086 */
2087 function getUnixTimestamp(date) {
2088 var time;
2089 if (typeof date === 'number') {
2090 time = date;
2091 }
2092 else {
2093 time = date.getTime();
2094 }
2095 return Math.floor(time / 1000);
2096 }
2097 /**
2098 * Adds the given number of seconds to the given date.
2099 *
2100 * @hidden
2101 *
2102 * @param {Date | number} date - The date to add seconds to.
2103 * If `date` is a `number` it is treated as a timestamp in milliseconds.
2104 * @param {number} seconds - The number of seconds to add.
2105 * @returns {Date} - The new date.
2106 */
2107 function addSeconds(date, seconds) {
2108 if (typeof date === 'number') {
2109 return new Date(date + seconds * 1000);
2110 }
2111 return new Date(date.getTime() + seconds * 1000);
2112 }
2113
2114 /**
2115 * JWT Subject.
2116 * @hidden
2117 */
2118 var SubjectPrefix = "identity-";
2119 /**
2120 * JWT Issuer.
2121 * @hidden
2122 */
2123 var IssuerPrefix = "virgil-";
2124 /**
2125 * Content type of the token. Used to convey structural information
2126 * about the JWT.
2127 * @hidden
2128 */
2129 var VirgilContentType = "virgil-jwt;v=1";
2130 /**
2131 * Media type of the JWT.
2132 * @hidden
2133 */
2134 var JwtContentType = "JWT";
2135
2136 /**
2137 * Class representing the JWT providing access to the
2138 * Virgil Security APIs.
2139 * Implements {@link IAccessToken} interface.
2140 */
2141 var Jwt = /** @class */ (function () {
2142 /**
2143 * Creates a new instance of `Jwt` with the given header, body and
2144 * optional signature.
2145 *
2146 * @param {IJwtHeader} header
2147 * @param {IJwtBody} body
2148 * @param {string} signature
2149 */
2150 function Jwt(header, body, signature) {
2151 this.header = header;
2152 this.body = body;
2153 this.signature = signature;
2154 var withoutSignature = this.headerBase64() + '.' + this.bodyBase64();
2155 this.unsignedData = withoutSignature;
2156 if (this.signature == null) {
2157 this.stringRepresentation = withoutSignature;
2158 }
2159 else {
2160 this.stringRepresentation = withoutSignature + '.' + this.signatureBase64();
2161 }
2162 }
2163 /**
2164 * Parses the string representation of the JWT into
2165 * an object representation.
2166 *
2167 * @param {string} jwtStr - The JWT string. Must have the following format:
2168 *
2169 * `base64UrlEncode(Header) + "." + base64UrlEncode(Body) + "." + base64UrlEncode(Signature)`
2170 *
2171 * See the {@link https://jwt.io/introduction/ | Introduction to JWT} for more details.
2172 *
2173 * @returns {Jwt}
2174 */
2175 Jwt.fromString = function (jwtStr) {
2176 var parts = jwtStr.split('.');
2177 if (parts.length !== 3)
2178 throw new Error('Wrong JWT format');
2179 try {
2180 var headerJson = base64UrlDecode(parts[0], 'utf8');
2181 var bodyJson = base64UrlDecode(parts[1], 'utf8');
2182 var signature = base64UrlToBase64(parts[2]);
2183 var header = JSON.parse(headerJson);
2184 var body = JSON.parse(bodyJson);
2185 return new Jwt(header, body, signature);
2186 }
2187 catch (e) {
2188 throw new Error('Wrong JWT format');
2189 }
2190 };
2191 /**
2192 * Returns the string representation of this JWT.
2193 * @returns {string}
2194 */
2195 Jwt.prototype.toString = function () {
2196 return this.stringRepresentation;
2197 };
2198 /**
2199 * Retrieves the identity that is the subject of this JWT.
2200 * @returns {string}
2201 */
2202 Jwt.prototype.identity = function () {
2203 if (this.body.sub.indexOf(SubjectPrefix) !== 0) {
2204 throw new Error('wrong sub format');
2205 }
2206 return this.body.sub.substr(SubjectPrefix.length);
2207 };
2208 /**
2209 * Retrieves the application ID that is the issuer of this JWT.
2210 * @returns {string}
2211 */
2212 Jwt.prototype.appId = function () {
2213 if (this.body.iss.indexOf(IssuerPrefix) !== 0) {
2214 throw new Error('wrong iss format');
2215 }
2216 return this.body.iss.substr(IssuerPrefix.length);
2217 };
2218 /**
2219 * Returns a boolean indicating whether this JWT is (or will be)
2220 * expired at the given date or not.
2221 *
2222 * @param {Date} at - The date to check. Defaults to `new Date()`.
2223 * @returns {boolean} - `true` if token is expired, otherwise `false`.
2224 */
2225 Jwt.prototype.isExpired = function (at) {
2226 if (at === void 0) { at = new Date; }
2227 var now = getUnixTimestamp(at);
2228 return this.body.exp < now;
2229 };
2230 Jwt.prototype.headerBase64 = function () {
2231 return base64UrlEncode(JSON.stringify(this.header));
2232 };
2233 Jwt.prototype.bodyBase64 = function () {
2234 return base64UrlEncode(JSON.stringify(this.body));
2235 };
2236 Jwt.prototype.signatureBase64 = function () {
2237 return base64UrlFromBase64(this.signature);
2238 };
2239 return Jwt;
2240 }());
2241
2242 /**
2243 * Test if `condition` is truthy. If it is not, an `Error` is thrown with a
2244 * `message` property equal to `message` parameter.
2245 * @hidden
2246 * @param {boolean} condition
2247 * @param {string} message
2248 */
2249 function assert(condition, message) {
2250 if (!condition) {
2251 throw new Error(message);
2252 }
2253 }
2254
2255 var DEFAULT_TOKEN_TTL = 20 * 60 * 1000; // 20 minutes
2256 /**
2257 * Class responsible for JWT generation.
2258 */
2259 var JwtGenerator = /** @class */ (function () {
2260 function JwtGenerator(options) {
2261 validateOptions(options);
2262 this.appId = options.appId;
2263 this.apiKey = options.apiKey;
2264 this.apiKeyId = options.apiKeyId;
2265 this.accessTokenSigner = options.accessTokenSigner;
2266 this.millisecondsToLive = options.millisecondsToLive !== undefined
2267 ? Number(options.millisecondsToLive)
2268 : DEFAULT_TOKEN_TTL;
2269 }
2270 /**
2271 * Generates a token with the given identity as the subject and optional
2272 * additional data.
2273 * @param {string} identity - Identity to be associated with JWT (i.e.
2274 * the Subject).
2275 * @param {IExtraData} ada - Additional data to be encoded in the JWT.
2276 * @returns {Jwt}
2277 */
2278 JwtGenerator.prototype.generateToken = function (identity, ada) {
2279 var iat = getUnixTimestamp(new Date());
2280 var exp = getUnixTimestamp(new Date().getTime() + this.millisecondsToLive);
2281 var body = {
2282 iss: IssuerPrefix + this.appId,
2283 sub: SubjectPrefix + identity,
2284 iat: iat,
2285 exp: exp,
2286 ada: ada
2287 };
2288 var header = {
2289 alg: this.accessTokenSigner.getAlgorithm(),
2290 kid: this.apiKeyId,
2291 typ: JwtContentType,
2292 cty: VirgilContentType
2293 };
2294 var unsignedJwt = new Jwt(header, body);
2295 var signature = this.accessTokenSigner.generateTokenSignature(unsignedJwt.unsignedData, this.apiKey);
2296 return new Jwt(header, body, signature.toString('base64'));
2297 };
2298 return JwtGenerator;
2299 }());
2300 function validateOptions(opts) {
2301 var invalidOptionMessage = function (name) {
2302 return "Invalid JwtGenerator options. `" + name + "` is required";
2303 };
2304 assert(opts != null, 'JwtGenerator options must be provided');
2305 assert(opts.apiKey != null, invalidOptionMessage('apiKey'));
2306 assert(opts.apiKeyId != null, invalidOptionMessage('apiKeyId'));
2307 assert(opts.appId != null, invalidOptionMessage('appId'));
2308 assert(opts.accessTokenSigner != null, invalidOptionMessage('accessTokenSigner'));
2309 }
2310
2311 /**
2312 * Class responsible for verification of JWTs.
2313 */
2314 var JwtVerifier = /** @class */ (function () {
2315 function JwtVerifier(options) {
2316 validateOptions$1(options);
2317 this.accessTokenSigner = options.accessTokenSigner;
2318 this.apiPublicKey = options.apiPublicKey;
2319 this.apiKeyId = options.apiKeyId;
2320 }
2321 /**
2322 * Verifies the validity of the given JWT.
2323 * @param {Jwt} token - The JWT to verify.
2324 * @returns {boolean}
2325 */
2326 JwtVerifier.prototype.verifyToken = function (token) {
2327 if (token == null) {
2328 throw new Error('Token is empty');
2329 }
2330 if (!this.allFieldsAreCorrect(token)) {
2331 return false;
2332 }
2333 return this.accessTokenSigner.verifyTokenSignature(token.unsignedData, token.signature, this.apiPublicKey);
2334 };
2335 JwtVerifier.prototype.allFieldsAreCorrect = function (token) {
2336 return token.header.kid == this.apiKeyId
2337 && token.header.alg == this.accessTokenSigner.getAlgorithm()
2338 && token.header.cty == VirgilContentType
2339 && token.header.typ == JwtContentType;
2340 };
2341 return JwtVerifier;
2342 }());
2343 function validateOptions$1(opts) {
2344 var invalidOptionMessage = function (name) {
2345 return "Invalid JwtVerifier options. `" + name + "` is required";
2346 };
2347 assert(opts != null, 'JwtVerifier options must be provided');
2348 assert(opts.apiPublicKey != null, invalidOptionMessage('apiPublicKey'));
2349 assert(opts.apiKeyId != null, invalidOptionMessage('apiKeyId'));
2350 assert(opts.accessTokenSigner != null, invalidOptionMessage('accessTokenSigner'));
2351 }
2352
2353 var TOKEN_EXPIRATION_MARGIN = 5;
2354 /**
2355 * Implementation of {@link IAccessTokenProvider} that caches the JWT
2356 * in memory while it's fresh (i.e. not expired) and uses the user-provided
2357 * callback function to get the JWT when requested by the clients.
2358 */
2359 var CachingJwtProvider = /** @class */ (function () {
2360 /**
2361 * Creates a new instance of `CachingJwtProvider`.
2362 * @param {GetJwtCallback} renewJwtFn - The function that will be called
2363 * whenever the fresh JWT is needed. If the `renewJwtFn` returns the JWT
2364 * as a string, it will be converted to {@link Jwt} instance automatically.
2365 * @param {Jwt|string} [initialToken] - Optional initial JWT.
2366 */
2367 function CachingJwtProvider(renewJwtFn, initialToken) {
2368 var _this = this;
2369 if (typeof renewJwtFn !== 'function') {
2370 throw new TypeError('`renewJwtFn` must be a function');
2371 }
2372 if (initialToken) {
2373 var jwt = void 0;
2374 if (typeof initialToken === 'string') {
2375 jwt = Jwt.fromString(initialToken);
2376 }
2377 else if (initialToken instanceof Jwt) {
2378 jwt = initialToken;
2379 }
2380 else {
2381 throw new Error("Expected \"initialToken\" to be a string or an instance of Jwt, got " + typeof initialToken);
2382 }
2383 this.cachedJwt = jwt;
2384 }
2385 this.getJwt = function (context) {
2386 if (_this.cachedJwt && !_this.cachedJwt.isExpired(addSeconds(new Date, TOKEN_EXPIRATION_MARGIN))) {
2387 return Promise.resolve(_this.cachedJwt);
2388 }
2389 if (_this.jwtPromise) {
2390 return _this.jwtPromise;
2391 }
2392 _this.jwtPromise = Promise.resolve(renewJwtFn(context))
2393 .then(function (token) {
2394 var jwt = typeof token === 'string' ? Jwt.fromString(token) : token;
2395 _this.cachedJwt = jwt;
2396 _this.jwtPromise = undefined;
2397 return jwt;
2398 }).catch(function (err) {
2399 _this.jwtPromise = undefined;
2400 throw err;
2401 });
2402 return _this.jwtPromise;
2403 };
2404 }
2405 /**
2406 * Returns a `Promise` resolved with the cached token if it's fresh, or the
2407 * token obtained by the call to the `renewJwtCallback` otherwise. The token
2408 * obtained from the `renewJwtCallback` is then cached. If the `renewJwtCallback`
2409 * returns the JWT as a string, it is converted to {@link Jwt} instance before returning.
2410 * @param {ITokenContext} context
2411 * @returns {Promise<IAccessToken>}
2412 */
2413 CachingJwtProvider.prototype.getToken = function (context) {
2414 return this.getJwt(context);
2415 };
2416 return CachingJwtProvider;
2417 }());
2418
2419 /**
2420 * Implementation of {@link IAccessToken} that calls the user-provided
2421 * callback function to get the JWT when requested by the clients.
2422 */
2423 var CallbackJwtProvider = /** @class */ (function () {
2424 /**
2425 * Creates a new instance of `CallbackJwtProvider`.
2426 *
2427 * @param {GetJwtCallback} getJwtFn - The function that will be called
2428 * whenever the JWT is needed. If the `getJwtFn` returns the JWT as a
2429 * string, it will be converted to {@link Jwt} instance automatically.
2430 */
2431 function CallbackJwtProvider(getJwtFn) {
2432 if (typeof getJwtFn !== 'function') {
2433 throw new TypeError('`getJwtFn` must be a function');
2434 }
2435 this.getJwt = function (context) {
2436 return Promise.resolve(getJwtFn(context))
2437 .then(function (token) { return typeof token === 'string' ? Jwt.fromString(token) : token; });
2438 };
2439 }
2440 /**
2441 * Returns a `Promise` resolved with the {@link Jwt} instance obtained
2442 * by the call to the {@link CallbackJwtProvider.getJwt}. If the
2443 * `getJwtFn` returns the JWT as a string, it is converted to
2444 * {@link Jwt} instance before returning.
2445 *
2446 * @param {ITokenContext} context
2447 * @returns {Promise<IAccessToken>}
2448 */
2449 CallbackJwtProvider.prototype.getToken = function (context) {
2450 return this.getJwt(context);
2451 };
2452 return CallbackJwtProvider;
2453 }());
2454
2455 /**
2456 * Implementation of {@link IAccessTokenProvider} that returns a
2457 * user-provided constant access token whenever it is requested by the clients.
2458 */
2459 var ConstAccessTokenProvider = /** @class */ (function () {
2460 /**
2461 * Creates a new instance of `ConstAccessTokenProvider`
2462 * @param {IAccessToken} accessToken - The access token to be returned
2463 * whenever it is requested.
2464 */
2465 function ConstAccessTokenProvider(accessToken) {
2466 this.accessToken = accessToken;
2467 if (accessToken == null) {
2468 throw new TypeError('`accessToken` is required');
2469 }
2470 }
2471 /**
2472 * Returns a `Promise` fulfilled with the
2473 * {@link ConstAccessTokenProvider.accessToken} provided to the constructor
2474 * of this instance.
2475 *
2476 * @param {ITokenContext} context
2477 * @returns {Promise<IAccessToken>}
2478 */
2479 ConstAccessTokenProvider.prototype.getToken = function (context) {
2480 return Promise.resolve(this.accessToken);
2481 };
2482 return ConstAccessTokenProvider;
2483 }());
2484
2485 /**
2486 * Implementation of {@link IAccessTokenProvider} that generates a
2487 * new JWT whenever it is requested by the clients.
2488 *
2489 * This class is meant to be used on the server side only.
2490 */
2491 var GeneratorJwtProvider = /** @class */ (function () {
2492 /**
2493 * Creates a new instance of `GeneratorJwtProvider` with the given
2494 * {@link JwtGenerator}, additional data and default identity.
2495 *
2496 * @param {JwtGenerator} jwtGenerator - Object to delegate the JWT generation to.
2497 * @param {IExtraData} additionalData - Additional data to include with the JWT.
2498 * @param {string} defaultIdentity - Identity of the user to include in the token
2499 * when none is provided explicitly by the client.
2500 */
2501 function GeneratorJwtProvider(jwtGenerator, additionalData, defaultIdentity) {
2502 this.jwtGenerator = jwtGenerator;
2503 this.additionalData = additionalData;
2504 this.defaultIdentity = defaultIdentity;
2505 if (jwtGenerator == null) {
2506 throw new TypeError('`jwtGenerator` is required');
2507 }
2508 }
2509 /**
2510 * Returns a `Promise` fulfilled with the JWT obtained from the call
2511 * to {@link GeneratorJwtProvider.jwtGenerator} {@link JwtGenerator.generateToken}
2512 * method, passing it the {@link GeneratorJwtProvider.additionalData} and
2513 * {@link GeneratorJwtProvider.defaultIdentity}
2514 *
2515 * @param {ITokenContext} context
2516 * @returns {Promise<IAccessToken>}
2517 */
2518 GeneratorJwtProvider.prototype.getToken = function (context) {
2519 var _this = this;
2520 return Promise.resolve().then(function () {
2521 var jwt = _this.jwtGenerator.generateToken(context.identity || _this.defaultIdentity || '', _this.additionalData);
2522 return jwt;
2523 });
2524 };
2525 return GeneratorJwtProvider;
2526 }());
2527
2528 /*! *****************************************************************************
2529 Copyright (c) Microsoft Corporation. All rights reserved.
2530 Licensed under the Apache License, Version 2.0 (the "License"); you may not use
2531 this file except in compliance with the License. You may obtain a copy of the
2532 License at http://www.apache.org/licenses/LICENSE-2.0
2533
2534 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
2535 KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
2536 WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
2537 MERCHANTABLITY OR NON-INFRINGEMENT.
2538
2539 See the Apache Version 2.0 License for specific language governing permissions
2540 and limitations under the License.
2541 ***************************************************************************** */
2542 /* global Reflect, Promise */
2543
2544 var extendStatics = function(d, b) {
2545 extendStatics = Object.setPrototypeOf ||
2546 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
2547 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
2548 return extendStatics(d, b);
2549 };
2550
2551 function __extends(d, b) {
2552 extendStatics(d, b);
2553 function __() { this.constructor = d; }
2554 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
2555 }
2556
2557 var __assign = function() {
2558 __assign = Object.assign || function __assign(t) {
2559 for (var s, i = 1, n = arguments.length; i < n; i++) {
2560 s = arguments[i];
2561 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
2562 }
2563 return t;
2564 };
2565 return __assign.apply(this, arguments);
2566 };
2567
2568 function __rest(s, e) {
2569 var t = {};
2570 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
2571 t[p] = s[p];
2572 if (s != null && typeof Object.getOwnPropertySymbols === "function")
2573 for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
2574 t[p[i]] = s[p[i]];
2575 return t;
2576 }
2577
2578 function __awaiter(thisArg, _arguments, P, generator) {
2579 return new (P || (P = Promise))(function (resolve, reject) {
2580 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
2581 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
2582 function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
2583 step((generator = generator.apply(thisArg, _arguments || [])).next());
2584 });
2585 }
2586
2587 function __generator(thisArg, body) {
2588 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
2589 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
2590 function verb(n) { return function (v) { return step([n, v]); }; }
2591 function step(op) {
2592 if (f) throw new TypeError("Generator is already executing.");
2593 while (_) try {
2594 if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
2595 if (y = 0, t) op = [op[0] & 2, t.value];
2596 switch (op[0]) {
2597 case 0: case 1: t = op; break;
2598 case 4: _.label++; return { value: op[1], done: false };
2599 case 5: _.label++; y = op[1]; op = [0]; continue;
2600 case 7: op = _.ops.pop(); _.trys.pop(); continue;
2601 default:
2602 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
2603 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
2604 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
2605 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
2606 if (t[2]) _.ops.pop();
2607 _.trys.pop(); continue;
2608 }
2609 op = body.call(thisArg, _);
2610 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
2611 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
2612 }
2613 }
2614
2615 /**
2616 * Intermediate representation of the Virgil Card with `contentSnapshot`
2617 * and `snapshot`s of the signatures in UTF-8.
2618 */
2619 var RawSignedModel = /** @class */ (function () {
2620 /**
2621 * Initializes a new instance of `RawSignedModel`.
2622 * @param {string} contentSnapshot - The content snapshot in UTF-8.
2623 * @param {IRawSignature[]} signatures - The signatures. If signatures
2624 * themselves have snapshots, those must also be in UTF-8.
2625 */
2626 function RawSignedModel(contentSnapshot, signatures) {
2627 this.contentSnapshot = contentSnapshot;
2628 this.signatures = signatures;
2629 }
2630 /**
2631 * Converts the `str` in base64 encoding into a `RawSignedModel` object.
2632 *
2633 * @param {string} str - Base64 string representation of the card as
2634 * returned by {@RawSignedModel.toString} method.
2635 *
2636 * @returns {RawSignedModel}
2637 */
2638 RawSignedModel.fromString = function (str) {
2639 var jsonStr = base64Decode(str, 'utf8');
2640 var obj;
2641 try {
2642 obj = JSON.parse(jsonStr);
2643 }
2644 catch (error) {
2645 throw new Error('The string to be parsed is in invalid format');
2646 }
2647 return RawSignedModel.fromJson(obj);
2648 };
2649 /**
2650 * Converts the `json` serializable object into a `RawSignedModel` object.
2651 * @param {IRawSignedModelJson} json - JSON-serializable object returned by
2652 * {@link RawSignedModel.toJson} method.
2653 * @returns {RawSignedModel}
2654 */
2655 RawSignedModel.fromJson = function (json) {
2656 var contentSnapshotUtf8 = base64Decode(json.content_snapshot, 'utf8');
2657 var signaturesWithUtf8Snapshots = (json.signatures || []).map(function (_a) {
2658 var signer = _a.signer, signature = _a.signature, snapshot = _a.snapshot;
2659 if (snapshot) {
2660 return {
2661 signer: signer,
2662 signature: signature,
2663 snapshot: base64Decode(snapshot, 'utf8')
2664 };
2665 }
2666 return { signer: signer, signature: signature };
2667 });
2668 return new RawSignedModel(contentSnapshotUtf8, signaturesWithUtf8Snapshots);
2669 };
2670 /**
2671 * This is to make it work with `JSON.stringify`, calls
2672 * {@link RawSignedModel.toJson} under the hood.
2673 * @returns {IRawSignedModelJson}
2674 */
2675 RawSignedModel.prototype.toJSON = function () {
2676 return this.toJson();
2677 };
2678 /**
2679 * Returns a JSON-serializable representation of this model in the
2680 * format it is stored in the Virgil Cards Service. (i.e. with
2681 * `contentSnapshot` and `snapshot`s of the signatures as base64 encoded
2682 * strings.
2683 * @returns {IRawSignedModelJson}
2684 */
2685 RawSignedModel.prototype.toJson = function () {
2686 return {
2687 content_snapshot: base64Encode(this.contentSnapshot, 'utf8'),
2688 signatures: this.signatures.map(function (_a) {
2689 var signer = _a.signer, signature = _a.signature, snapshot = _a.snapshot;
2690 if (snapshot) {
2691 return {
2692 signer: signer,
2693 signature: signature,
2694 snapshot: base64Encode(snapshot, 'utf8')
2695 };
2696 }
2697 return { signer: signer, signature: signature };
2698 })
2699 };
2700 };
2701 /**
2702 * Serializes this model to string in base64 encoding.
2703 * @returns {string}
2704 */
2705 RawSignedModel.prototype.toString = function () {
2706 return base64Encode(JSON.stringify(this), 'utf8');
2707 };
2708 /**
2709 * Same as {@link RawSignedModel.toJson}. Please use that instead.
2710 * @returns {IRawSignedModelJson}
2711 */
2712 RawSignedModel.prototype.exportAsJson = function () {
2713 return this.toJson();
2714 };
2715 /**
2716 * Same as {@link RawSignedModel.toString}. Please use that instead.
2717 * @returns {string}
2718 */
2719 RawSignedModel.prototype.exportAsString = function () {
2720 return this.toString();
2721 };
2722 return RawSignedModel;
2723 }());
2724
2725 var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
2726
2727 function createCommonjsModule(fn, module) {
2728 return module = { exports: {} }, fn(module, module.exports), module.exports;
2729 }
2730
2731 var fetchBrowser = createCommonjsModule(function (module, exports) {
2732 (function (self) {
2733
2734 function fetchPonyfill(options) {
2735 var Promise = options && options.Promise || self.Promise;
2736 var XMLHttpRequest = options && options.XMLHttpRequest || self.XMLHttpRequest;
2737 var global = self;
2738
2739 return (function () {
2740 var self = Object.create(global, {
2741 fetch: {
2742 value: undefined,
2743 writable: true
2744 }
2745 });
2746
2747 (function(self) {
2748
2749 if (self.fetch) {
2750 return
2751 }
2752
2753 var support = {
2754 searchParams: 'URLSearchParams' in self,
2755 iterable: 'Symbol' in self && 'iterator' in Symbol,
2756 blob: 'FileReader' in self && 'Blob' in self && (function() {
2757 try {
2758 new Blob();
2759 return true
2760 } catch(e) {
2761 return false
2762 }
2763 })(),
2764 formData: 'FormData' in self,
2765 arrayBuffer: 'ArrayBuffer' in self
2766 };
2767
2768 if (support.arrayBuffer) {
2769 var viewClasses = [
2770 '[object Int8Array]',
2771 '[object Uint8Array]',
2772 '[object Uint8ClampedArray]',
2773 '[object Int16Array]',
2774 '[object Uint16Array]',
2775 '[object Int32Array]',
2776 '[object Uint32Array]',
2777 '[object Float32Array]',
2778 '[object Float64Array]'
2779 ];
2780
2781 var isDataView = function(obj) {
2782 return obj && DataView.prototype.isPrototypeOf(obj)
2783 };
2784
2785 var isArrayBufferView = ArrayBuffer.isView || function(obj) {
2786 return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1
2787 };
2788 }
2789
2790 function normalizeName(name) {
2791 if (typeof name !== 'string') {
2792 name = String(name);
2793 }
2794 if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) {
2795 throw new TypeError('Invalid character in header field name')
2796 }
2797 return name.toLowerCase()
2798 }
2799
2800 function normalizeValue(value) {
2801 if (typeof value !== 'string') {
2802 value = String(value);
2803 }
2804 return value
2805 }
2806
2807 // Build a destructive iterator for the value list
2808 function iteratorFor(items) {
2809 var iterator = {
2810 next: function() {
2811 var value = items.shift();
2812 return {done: value === undefined, value: value}
2813 }
2814 };
2815
2816 if (support.iterable) {
2817 iterator[Symbol.iterator] = function() {
2818 return iterator
2819 };
2820 }
2821
2822 return iterator
2823 }
2824
2825 function Headers(headers) {
2826 this.map = {};
2827
2828 if (headers instanceof Headers) {
2829 headers.forEach(function(value, name) {
2830 this.append(name, value);
2831 }, this);
2832 } else if (Array.isArray(headers)) {
2833 headers.forEach(function(header) {
2834 this.append(header[0], header[1]);
2835 }, this);
2836 } else if (headers) {
2837 Object.getOwnPropertyNames(headers).forEach(function(name) {
2838 this.append(name, headers[name]);
2839 }, this);
2840 }
2841 }
2842
2843 Headers.prototype.append = function(name, value) {
2844 name = normalizeName(name);
2845 value = normalizeValue(value);
2846 var oldValue = this.map[name];
2847 this.map[name] = oldValue ? oldValue+','+value : value;
2848 };
2849
2850 Headers.prototype['delete'] = function(name) {
2851 delete this.map[normalizeName(name)];
2852 };
2853
2854 Headers.prototype.get = function(name) {
2855 name = normalizeName(name);
2856 return this.has(name) ? this.map[name] : null
2857 };
2858
2859 Headers.prototype.has = function(name) {
2860 return this.map.hasOwnProperty(normalizeName(name))
2861 };
2862
2863 Headers.prototype.set = function(name, value) {
2864 this.map[normalizeName(name)] = normalizeValue(value);
2865 };
2866
2867 Headers.prototype.forEach = function(callback, thisArg) {
2868 for (var name in this.map) {
2869 if (this.map.hasOwnProperty(name)) {
2870 callback.call(thisArg, this.map[name], name, this);
2871 }
2872 }
2873 };
2874
2875 Headers.prototype.keys = function() {
2876 var items = [];
2877 this.forEach(function(value, name) { items.push(name); });
2878 return iteratorFor(items)
2879 };
2880
2881 Headers.prototype.values = function() {
2882 var items = [];
2883 this.forEach(function(value) { items.push(value); });
2884 return iteratorFor(items)
2885 };
2886
2887 Headers.prototype.entries = function() {
2888 var items = [];
2889 this.forEach(function(value, name) { items.push([name, value]); });
2890 return iteratorFor(items)
2891 };
2892
2893 if (support.iterable) {
2894 Headers.prototype[Symbol.iterator] = Headers.prototype.entries;
2895 }
2896
2897 function consumed(body) {
2898 if (body.bodyUsed) {
2899 return Promise.reject(new TypeError('Already read'))
2900 }
2901 body.bodyUsed = true;
2902 }
2903
2904 function fileReaderReady(reader) {
2905 return new Promise(function(resolve, reject) {
2906 reader.onload = function() {
2907 resolve(reader.result);
2908 };
2909 reader.onerror = function() {
2910 reject(reader.error);
2911 };
2912 })
2913 }
2914
2915 function readBlobAsArrayBuffer(blob) {
2916 var reader = new FileReader();
2917 var promise = fileReaderReady(reader);
2918 reader.readAsArrayBuffer(blob);
2919 return promise
2920 }
2921
2922 function readBlobAsText(blob) {
2923 var reader = new FileReader();
2924 var promise = fileReaderReady(reader);
2925 reader.readAsText(blob);
2926 return promise
2927 }
2928
2929 function readArrayBufferAsText(buf) {
2930 var view = new Uint8Array(buf);
2931 var chars = new Array(view.length);
2932
2933 for (var i = 0; i < view.length; i++) {
2934 chars[i] = String.fromCharCode(view[i]);
2935 }
2936 return chars.join('')
2937 }
2938
2939 function bufferClone(buf) {
2940 if (buf.slice) {
2941 return buf.slice(0)
2942 } else {
2943 var view = new Uint8Array(buf.byteLength);
2944 view.set(new Uint8Array(buf));
2945 return view.buffer
2946 }
2947 }
2948
2949 function Body() {
2950 this.bodyUsed = false;
2951
2952 this._initBody = function(body) {
2953 this._bodyInit = body;
2954 if (!body) {
2955 this._bodyText = '';
2956 } else if (typeof body === 'string') {
2957 this._bodyText = body;
2958 } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {
2959 this._bodyBlob = body;
2960 } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {
2961 this._bodyFormData = body;
2962 } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
2963 this._bodyText = body.toString();
2964 } else if (support.arrayBuffer && support.blob && isDataView(body)) {
2965 this._bodyArrayBuffer = bufferClone(body.buffer);
2966 // IE 10-11 can't handle a DataView body.
2967 this._bodyInit = new Blob([this._bodyArrayBuffer]);
2968 } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) {
2969 this._bodyArrayBuffer = bufferClone(body);
2970 } else {
2971 throw new Error('unsupported BodyInit type')
2972 }
2973
2974 if (!this.headers.get('content-type')) {
2975 if (typeof body === 'string') {
2976 this.headers.set('content-type', 'text/plain;charset=UTF-8');
2977 } else if (this._bodyBlob && this._bodyBlob.type) {
2978 this.headers.set('content-type', this._bodyBlob.type);
2979 } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
2980 this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8');
2981 }
2982 }
2983 };
2984
2985 if (support.blob) {
2986 this.blob = function() {
2987 var rejected = consumed(this);
2988 if (rejected) {
2989 return rejected
2990 }
2991
2992 if (this._bodyBlob) {
2993 return Promise.resolve(this._bodyBlob)
2994 } else if (this._bodyArrayBuffer) {
2995 return Promise.resolve(new Blob([this._bodyArrayBuffer]))
2996 } else if (this._bodyFormData) {
2997 throw new Error('could not read FormData body as blob')
2998 } else {
2999 return Promise.resolve(new Blob([this._bodyText]))
3000 }
3001 };
3002
3003 this.arrayBuffer = function() {
3004 if (this._bodyArrayBuffer) {
3005 return consumed(this) || Promise.resolve(this._bodyArrayBuffer)
3006 } else {
3007 return this.blob().then(readBlobAsArrayBuffer)
3008 }
3009 };
3010 }
3011
3012 this.text = function() {
3013 var rejected = consumed(this);
3014 if (rejected) {
3015 return rejected
3016 }
3017
3018 if (this._bodyBlob) {
3019 return readBlobAsText(this._bodyBlob)
3020 } else if (this._bodyArrayBuffer) {
3021 return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer))
3022 } else if (this._bodyFormData) {
3023 throw new Error('could not read FormData body as text')
3024 } else {
3025 return Promise.resolve(this._bodyText)
3026 }
3027 };
3028
3029 if (support.formData) {
3030 this.formData = function() {
3031 return this.text().then(decode)
3032 };
3033 }
3034
3035 this.json = function() {
3036 return this.text().then(JSON.parse)
3037 };
3038
3039 return this
3040 }
3041
3042 // HTTP methods whose capitalization should be normalized
3043 var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT'];
3044
3045 function normalizeMethod(method) {
3046 var upcased = method.toUpperCase();
3047 return (methods.indexOf(upcased) > -1) ? upcased : method
3048 }
3049
3050 function Request(input, options) {
3051 options = options || {};
3052 var body = options.body;
3053
3054 if (input instanceof Request) {
3055 if (input.bodyUsed) {
3056 throw new TypeError('Already read')
3057 }
3058 this.url = input.url;
3059 this.credentials = input.credentials;
3060 if (!options.headers) {
3061 this.headers = new Headers(input.headers);
3062 }
3063 this.method = input.method;
3064 this.mode = input.mode;
3065 if (!body && input._bodyInit != null) {
3066 body = input._bodyInit;
3067 input.bodyUsed = true;
3068 }
3069 } else {
3070 this.url = String(input);
3071 }
3072
3073 this.credentials = options.credentials || this.credentials || 'omit';
3074 if (options.headers || !this.headers) {
3075 this.headers = new Headers(options.headers);
3076 }
3077 this.method = normalizeMethod(options.method || this.method || 'GET');
3078 this.mode = options.mode || this.mode || null;
3079 this.referrer = null;
3080
3081 if ((this.method === 'GET' || this.method === 'HEAD') && body) {
3082 throw new TypeError('Body not allowed for GET or HEAD requests')
3083 }
3084 this._initBody(body);
3085 }
3086
3087 Request.prototype.clone = function() {
3088 return new Request(this, { body: this._bodyInit })
3089 };
3090
3091 function decode(body) {
3092 var form = new FormData();
3093 body.trim().split('&').forEach(function(bytes) {
3094 if (bytes) {
3095 var split = bytes.split('=');
3096 var name = split.shift().replace(/\+/g, ' ');
3097 var value = split.join('=').replace(/\+/g, ' ');
3098 form.append(decodeURIComponent(name), decodeURIComponent(value));
3099 }
3100 });
3101 return form
3102 }
3103
3104 function parseHeaders(rawHeaders) {
3105 var headers = new Headers();
3106 rawHeaders.split(/\r?\n/).forEach(function(line) {
3107 var parts = line.split(':');
3108 var key = parts.shift().trim();
3109 if (key) {
3110 var value = parts.join(':').trim();
3111 headers.append(key, value);
3112 }
3113 });
3114 return headers
3115 }
3116
3117 Body.call(Request.prototype);
3118
3119 function Response(bodyInit, options) {
3120 if (!options) {
3121 options = {};
3122 }
3123
3124 this.type = 'default';
3125 this.status = 'status' in options ? options.status : 200;
3126 this.ok = this.status >= 200 && this.status < 300;
3127 this.statusText = 'statusText' in options ? options.statusText : 'OK';
3128 this.headers = new Headers(options.headers);
3129 this.url = options.url || '';
3130 this._initBody(bodyInit);
3131 }
3132
3133 Body.call(Response.prototype);
3134
3135 Response.prototype.clone = function() {
3136 return new Response(this._bodyInit, {
3137 status: this.status,
3138 statusText: this.statusText,
3139 headers: new Headers(this.headers),
3140 url: this.url
3141 })
3142 };
3143
3144 Response.error = function() {
3145 var response = new Response(null, {status: 0, statusText: ''});
3146 response.type = 'error';
3147 return response
3148 };
3149
3150 var redirectStatuses = [301, 302, 303, 307, 308];
3151
3152 Response.redirect = function(url, status) {
3153 if (redirectStatuses.indexOf(status) === -1) {
3154 throw new RangeError('Invalid status code')
3155 }
3156
3157 return new Response(null, {status: status, headers: {location: url}})
3158 };
3159
3160 self.Headers = Headers;
3161 self.Request = Request;
3162 self.Response = Response;
3163
3164 self.fetch = function(input, init) {
3165 return new Promise(function(resolve, reject) {
3166 var request = new Request(input, init);
3167 var xhr = new XMLHttpRequest();
3168
3169 xhr.onload = function() {
3170 var options = {
3171 status: xhr.status,
3172 statusText: xhr.statusText,
3173 headers: parseHeaders(xhr.getAllResponseHeaders() || '')
3174 };
3175 options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL');
3176 var body = 'response' in xhr ? xhr.response : xhr.responseText;
3177 resolve(new Response(body, options));
3178 };
3179
3180 xhr.onerror = function() {
3181 reject(new TypeError('Network request failed'));
3182 };
3183
3184 xhr.ontimeout = function() {
3185 reject(new TypeError('Network request failed'));
3186 };
3187
3188 xhr.open(request.method, request.url, true);
3189
3190 if (request.credentials === 'include') {
3191 xhr.withCredentials = true;
3192 }
3193
3194 if ('responseType' in xhr && support.blob) {
3195 xhr.responseType = 'blob';
3196 }
3197
3198 request.headers.forEach(function(value, name) {
3199 xhr.setRequestHeader(name, value);
3200 });
3201
3202 xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit);
3203 })
3204 };
3205 self.fetch.polyfill = true;
3206 })(typeof self !== 'undefined' ? self : this);
3207
3208
3209 return {
3210 fetch: self.fetch,
3211 Headers: self.Headers,
3212 Request: self.Request,
3213 Response: self.Response
3214 };
3215 }());
3216 }
3217
3218 {
3219 module.exports = fetchPonyfill;
3220 }
3221 }(typeof self !== 'undefined' ? self : typeof commonjsGlobal !== 'undefined' ? commonjsGlobal : commonjsGlobal));
3222 });
3223
3224 var _a = fetchBrowser(), fetch = _a.fetch, Request = _a.Request, Response = _a.Response, Headers = _a.Headers;
3225
3226 /**
3227 * Class responsible for making HTTP requests.
3228 * @hidden
3229 */
3230 var Connection = /** @class */ (function () {
3231 /**
3232 * Initializes a new instance of `Connection`.
3233 * @param {string} prefix - `prefix` will be prepended to the `endpoint`
3234 * argument of request methods.
3235 */
3236 function Connection(prefix) {
3237 this.prefix = prefix;
3238 }
3239 /**
3240 * Issues a GET request against the `endpoint`.
3241 * @param {string} endpoint - Endpoint URL relative to the `prefix`.
3242 * @param {string} accessToken - Token to authenticate the request.
3243 * @returns {Promise<Response>}
3244 */
3245 Connection.prototype.get = function (endpoint, accessToken) {
3246 var headers = this.createHeaders(accessToken);
3247 return this.send(endpoint, 'GET', { headers: headers });
3248 };
3249 /**
3250 * Issues a POST request against the `endpoint` sending the `data` as JSON.
3251 * @param {string} endpoint - Endpoint URL relative to the `prefix`.
3252 * @param {string} accessToken - Token to authenticate the request.
3253 * @param {object} data - Response body.
3254 * @returns {Promise<Response>}
3255 */
3256 Connection.prototype.post = function (endpoint, accessToken, data) {
3257 if (data === void 0) { data = {}; }
3258 var headers = this.createHeaders(accessToken);
3259 headers.set('Content-Type', 'application/json');
3260 return this.send(endpoint, 'POST', {
3261 headers: headers,
3262 body: JSON.stringify(data)
3263 });
3264 };
3265 Connection.prototype.send = function (endpoint, method, params) {
3266 return fetch(this.prefix + endpoint, __assign({ method: method }, params));
3267 };
3268 Connection.prototype.createHeaders = function (accessToken) {
3269 var headers = new Headers();
3270 headers.set('Authorization', "Virgil " + accessToken);
3271 return headers;
3272 };
3273 return Connection;
3274 }());
3275
3276 /**
3277 * Custom error class for errors specific to Virgil SDK.
3278 */
3279 var VirgilError = /** @class */ (function (_super) {
3280 __extends(VirgilError, _super);
3281 function VirgilError(m, name) {
3282 var _newTarget = this.constructor;
3283 if (name === void 0) { name = 'VirgilError'; }
3284 var _this = _super.call(this, m) || this;
3285 Object.setPrototypeOf(_this, _newTarget.prototype);
3286 _this.name = name;
3287 return _this;
3288 }
3289 return VirgilError;
3290 }(Error));
3291
3292 var ErrorCode;
3293 (function (ErrorCode) {
3294 ErrorCode[ErrorCode["AccessTokenExpired"] = 20304] = "AccessTokenExpired";
3295 ErrorCode[ErrorCode["Unknown"] = 0] = "Unknown";
3296 })(ErrorCode || (ErrorCode = {}));
3297 /**
3298 * Error thrown by {@link CardManager} when request to the Virgil Cards Service
3299 * fails.
3300 */
3301 var VirgilHttpError = /** @class */ (function (_super) {
3302 __extends(VirgilHttpError, _super);
3303 function VirgilHttpError(message, status, errorCode) {
3304 var _this = _super.call(this, message, 'VirgilHttpError') || this;
3305 _this.httpStatus = status;
3306 _this.errorCode = errorCode;
3307 return _this;
3308 }
3309 return VirgilHttpError;
3310 }(VirgilError));
3311 /**
3312 * Generates error object from response object with HTTP status >= 400
3313 *
3314 * @hidden
3315 *
3316 * @param {Response} response
3317 * @returns {Promise<VirgilHttpError>}
3318 */
3319 function generateErrorFromResponse(response) {
3320 return __awaiter(this, void 0, void 0, function () {
3321 var reason;
3322 return __generator(this, function (_a) {
3323 switch (_a.label) {
3324 case 0:
3325 if (!(response.status >= 400 && response.status < 500)) return [3 /*break*/, 2];
3326 return [4 /*yield*/, response.json()];
3327 case 1:
3328 reason = _a.sent();
3329 return [2 /*return*/, new VirgilHttpError(reason.message, response.status, reason.code)];
3330 case 2: return [2 /*return*/, new VirgilHttpError(response.statusText, response.status, 0)];
3331 }
3332 });
3333 });
3334 }
3335
3336 var PublishEndpoint = '/card/v5';
3337 var SearchEndpoint = '/card/v5/actions/search';
3338 var GetCardEndpoint = function (cardId) { return "/card/v5/" + cardId; };
3339 /**
3340 * Class responsible for sending requests to the Virgil Cards Service.
3341 *
3342 * @hidden
3343 */
3344 var CardClient = /** @class */ (function () {
3345 /**
3346 * Initializes new instance of `CardClient`.
3347 * @param {IConnection | string} connection - Object implementing the
3348 * {@link IConnection} interface.
3349 */
3350 function CardClient(connection) {
3351 if (typeof connection === 'string') {
3352 this.connection = new Connection(connection);
3353 }
3354 else if (connection) {
3355 this.connection = connection;
3356 }
3357 else {
3358 this.connection = new Connection('https://api.virgilsecurity.com');
3359 }
3360 }
3361 /**
3362 * Issues a request to search cards by the `identity`.
3363 * @param {string[]} identities - Array of identities to search for.
3364 * @param {string} jwtToken - A token to authenticate the request.
3365 * @returns {Promise<RawSignedModel[]>}
3366 */
3367 CardClient.prototype.searchCards = function (identities, jwtToken) {
3368 return __awaiter(this, void 0, void 0, function () {
3369 var response, cardsJson;
3370 return __generator(this, function (_a) {
3371 switch (_a.label) {
3372 case 0: return [4 /*yield*/, this.connection.post(SearchEndpoint, jwtToken, { identities: identities })];
3373 case 1:
3374 response = _a.sent();
3375 if (!!response.ok) return [3 /*break*/, 3];
3376 return [4 /*yield*/, generateErrorFromResponse(response)];
3377 case 2: throw _a.sent();
3378 case 3: return [4 /*yield*/, response.json()];
3379 case 4:
3380 cardsJson = _a.sent();
3381 if (cardsJson === null)
3382 return [2 /*return*/, []];
3383 return [2 /*return*/, cardsJson.map(RawSignedModel.fromJson)];
3384 }
3385 });
3386 });
3387 };
3388 /**
3389 * Issues a request to get the card by id.
3390 * @param {string} cardId - Id of the card to fetch.
3391 * @param {string} jwtToken - A token to authenticate the request.
3392 * @returns {Promise<ICardResult>}
3393 */
3394 CardClient.prototype.getCard = function (cardId, jwtToken) {
3395 return __awaiter(this, void 0, void 0, function () {
3396 var response, isOutdated, cardJson, cardRaw;
3397 return __generator(this, function (_a) {
3398 switch (_a.label) {
3399 case 0:
3400 if (!cardId)
3401 throw new TypeError('`cardId` should not be empty');
3402 if (!jwtToken)
3403 throw new TypeError('`jwtToken` should not be empty');
3404 return [4 /*yield*/, this.connection.get(GetCardEndpoint(cardId), jwtToken)];
3405 case 1:
3406 response = _a.sent();
3407 if (!!response.ok) return [3 /*break*/, 3];
3408 return [4 /*yield*/, generateErrorFromResponse(response)];
3409 case 2: throw _a.sent();
3410 case 3:
3411 isOutdated = response.headers.get('X-Virgil-Is-Superseeded') === 'true';
3412 return [4 /*yield*/, response.json()];
3413 case 4:
3414 cardJson = _a.sent();
3415 cardRaw = RawSignedModel.fromJson(cardJson);
3416 return [2 /*return*/, { cardRaw: cardRaw, isOutdated: isOutdated }];
3417 }
3418 });
3419 });
3420 };
3421 /**
3422 * Issues a request to publish the card.
3423 * @param {RawSignedModel} model - Card to publish.
3424 * @param {string} jwtToken - A token to authenticate the request.
3425 * @returns {Promise<RawSignedModel>}
3426 */
3427 CardClient.prototype.publishCard = function (model, jwtToken) {
3428 return __awaiter(this, void 0, void 0, function () {
3429 var response, cardJson;
3430 return __generator(this, function (_a) {
3431 switch (_a.label) {
3432 case 0:
3433 if (!model)
3434 throw new TypeError('`model` should not be empty');
3435 if (!jwtToken)
3436 throw new TypeError('`jwtToken` should not be empty');
3437 return [4 /*yield*/, this.connection.post(PublishEndpoint, jwtToken, model)];
3438 case 1:
3439 response = _a.sent();
3440 if (!!response.ok) return [3 /*break*/, 3];
3441 return [4 /*yield*/, generateErrorFromResponse(response)];
3442 case 2: throw _a.sent();
3443 case 3: return [4 /*yield*/, response.json()];
3444 case 4:
3445 cardJson = _a.sent();
3446 return [2 /*return*/, RawSignedModel.fromJson(cardJson)];
3447 }
3448 });
3449 });
3450 };
3451 return CardClient;
3452 }());
3453
3454 /**
3455 * @hidden
3456 */
3457 var SelfSigner = "self";
3458 /**
3459 * @hidden
3460 */
3461 var VirgilSigner = "virgil";
3462 /**
3463 * @hidden
3464 */
3465 var CardVersion = '5.0';
3466 /**
3467 * @hidden
3468 */
3469 var CardIdByteLength = 32;
3470
3471 /**
3472 * Class responsible for generating signatures of the cards.
3473 */
3474 var ModelSigner = /** @class */ (function () {
3475 /**
3476 * Initializes a new instance of `ModelSigner`.
3477 * @param {ICardCrypto} crypto - Object implementing the
3478 * {@link ICardCrypto} interface.
3479 */
3480 function ModelSigner(crypto) {
3481 this.crypto = crypto;
3482 }
3483 /**
3484 * Generates a new signature based on `rawParams`.
3485 * @param {IRawSignParams} rawParams
3486 */
3487 ModelSigner.prototype.sign = function (rawParams) {
3488 var _a = this.prepareParams(rawParams), model = _a.model, signerPrivateKey = _a.signerPrivateKey, signer = _a.signer, extraSnapshot = _a.extraSnapshot;
3489 var signedSnapshot = extraSnapshot != null
3490 ? model.contentSnapshot + extraSnapshot
3491 : model.contentSnapshot;
3492 var signature = this.crypto.generateSignature(signedSnapshot, signerPrivateKey);
3493 model.signatures.push({
3494 signer: signer,
3495 signature: signature.toString('base64'),
3496 snapshot: extraSnapshot
3497 });
3498 };
3499 ModelSigner.prototype.prepareParams = function (_a) {
3500 var model = _a.model, signerPrivateKey = _a.signerPrivateKey, extraFields = _a.extraFields, signer = _a.signer;
3501 signer = signer || SelfSigner;
3502 var extraSnapshot;
3503 if (extraFields != null) {
3504 extraSnapshot = JSON.stringify(extraFields);
3505 }
3506 var final = { model: model, signerPrivateKey: signerPrivateKey, signer: signer, extraSnapshot: extraSnapshot };
3507 this.validate(final);
3508 return final;
3509 };
3510 ModelSigner.prototype.validate = function (_a) {
3511 var model = _a.model, signerPrivateKey = _a.signerPrivateKey, signer = _a.signer;
3512 if (model == null) {
3513 throw new Error("Model is empty");
3514 }
3515 if (signerPrivateKey == null) {
3516 throw new Error("`signerPrivateKey` property is mandatory");
3517 }
3518 if (model.signatures != null && model.signatures.some(function (s) { return s.signer == signer; })) {
3519 throw new Error("The model already has this signature.");
3520 }
3521 };
3522 return ModelSigner;
3523 }());
3524
3525 /**
3526 * Converts an {@link ICard} to a {@link RawSignedModel}.
3527 *
3528 * @hidden
3529 *
3530 * @param {ICard} card - The {@link ICard} to convert.
3531 * @returns {RawSignedModel}
3532 */
3533 function cardToRawSignedModel(card) {
3534 return new RawSignedModel(card.contentSnapshot, card.signatures.slice());
3535 }
3536 /**
3537 * Generates a {@link RawSignedModel} from the given `params`.
3538 *
3539 * @hidden
3540 *
3541 * @param {ICardCrypto} crypto - Object implementing the {@link ICardCrypto}
3542 * interface.
3543 * @param {INewCardParams} params - New card parameters.
3544 * @returns {RawSignedModel}
3545 */
3546 function generateRawSigned(crypto, params) {
3547 var identity = params.identity, publicKey = params.publicKey, previousCardId = params.previousCardId;
3548 var now = getUnixTimestamp(new Date);
3549 var details = {
3550 identity: identity,
3551 previous_card_id: previousCardId,
3552 created_at: now,
3553 version: CardVersion,
3554 public_key: base64Encode(crypto.exportPublicKey(publicKey))
3555 };
3556 return new RawSignedModel(JSON.stringify(details), []);
3557 }
3558 /**
3559 * Converts the {@link RawSignedModel} into the {@link ICard}.
3560 *
3561 * @hidden
3562 *
3563 * @param {ICardCrypto} crypto - Object implementing the {@link ICardCrypto}
3564 * interface.
3565 * @param {RawSignedModel} model - The model to convert.
3566 * @param {boolean} isOutdated - Boolean indicating whether there is a newer
3567 * Virgil Card replacing the one that `model` represents.
3568 *
3569 * @returns {ICard}
3570 */
3571 function parseRawSignedModel(crypto, model, isOutdated) {
3572 if (isOutdated === void 0) { isOutdated = false; }
3573 var content = JSON.parse(model.contentSnapshot);
3574 var signatures = model.signatures.map(rawSignToCardSign);
3575 return {
3576 id: generateCardId(crypto, model.contentSnapshot),
3577 publicKey: crypto.importPublicKey(content.public_key),
3578 contentSnapshot: model.contentSnapshot,
3579 identity: content.identity,
3580 version: content.version,
3581 createdAt: new Date(content.created_at * 1000),
3582 previousCardId: content.previous_card_id,
3583 signatures: signatures,
3584 isOutdated: isOutdated
3585 };
3586 }
3587 /**
3588 * Given the array of `cards`, returns another array with outdated cards
3589 * filtered out and the `previousCard` properties of the cards that replace
3590 * the outdated ones being populated with appropriate outdated cards.
3591 * i.e. turns this (A is for Actual, O is for Outdated):
3592 * ```
3593 * A -> O -> A -> A -> O
3594 * ```
3595 * into this
3596 * ```
3597 * A -> A -> A
3598 * | |
3599 * O O
3600 * ```
3601 *
3602 * @hidden
3603 *
3604 * @param {ICard[]} cards - The cards array to transform.
3605 * @returns {ICard[]} - Transformed array.
3606 */
3607 function linkedCardList(cards) {
3608 var unsorted = Object.create(null);
3609 for (var _i = 0, cards_1 = cards; _i < cards_1.length; _i++) {
3610 var card = cards_1[_i];
3611 unsorted[card.id] = card;
3612 }
3613 for (var _a = 0, cards_2 = cards; _a < cards_2.length; _a++) {
3614 var card = cards_2[_a];
3615 if (card.previousCardId == null)
3616 continue;
3617 if (unsorted[card.previousCardId] == null)
3618 continue;
3619 unsorted[card.previousCardId].isOutdated = true;
3620 card.previousCard = unsorted[card.previousCardId];
3621 delete unsorted[card.previousCardId];
3622 }
3623 return Object.keys(unsorted).map(function (key) { return unsorted[key]; });
3624 }
3625 /**
3626 * Calculates ID for the VirgilCard from the `snapshot` of its contents.
3627 *
3628 * @hidden
3629 *
3630 * @param {ICardCrypto} crypto - Object implementing the {@link ICardCrypto}
3631 * interface.
3632 * @param {string} snapshot - The VirgilCard's contents snapshot.
3633 * @returns {string} - VirgilCard's ID encoded in HEX.
3634 */
3635 function generateCardId(crypto, snapshot) {
3636 var fingerprint = crypto.generateSha512(snapshot).slice(0, CardIdByteLength);
3637 return fingerprint.toString('hex');
3638 }
3639 function rawSignToCardSign(_a) {
3640 var snapshot = _a.snapshot, signature = _a.signature, signer = _a.signer;
3641 return {
3642 signer: signer,
3643 signature: signature,
3644 snapshot: snapshot,
3645 extraFields: tryParseExtraFields(snapshot)
3646 };
3647 }
3648 function tryParseExtraFields(snapshot) {
3649 if (snapshot) {
3650 try {
3651 return JSON.parse(snapshot);
3652 }
3653 catch (ignored) { }
3654 }
3655 return {};
3656 }
3657
3658 /**
3659 * Error thrown by {@link CardManager} instances when the card received from
3660 * the network (or imported from string\json) fails verification.
3661 */
3662 var VirgilCardVerificationError = /** @class */ (function (_super) {
3663 __extends(VirgilCardVerificationError, _super);
3664 function VirgilCardVerificationError(m) {
3665 return _super.call(this, m, 'CardVerificationError') || this;
3666 }
3667 return VirgilCardVerificationError;
3668 }(VirgilError));
3669
3670 /**
3671 * @hidden
3672 */
3673 var throwingAccessTokenProvider = {
3674 getToken: function () {
3675 throw new Error('Please set `CardManager.accessTokenProvider` to be able to make requests.');
3676 }
3677 };
3678 /**
3679 * Class responsible for creating, publishing and retrieving Virgil Cards.
3680 */
3681 var CardManager = /** @class */ (function () {
3682 function CardManager(params) {
3683 this.crypto = params.cardCrypto;
3684 this.client = new CardClient(params.apiUrl);
3685 this.modelSigner = new ModelSigner(params.cardCrypto);
3686 this.signCallback = params.signCallback;
3687 this.retryOnUnauthorized = params.retryOnUnauthorized;
3688 this.cardVerifier = params.cardVerifier;
3689 this.accessTokenProvider = params.accessTokenProvider || throwingAccessTokenProvider;
3690 }
3691 /**
3692 * Generates a {@link RawSignedModel} that represents a card from
3693 * `cardParams`.
3694 * Use this method if you don't need to publish the card right away, for
3695 * example if you need to first send it to your backend server to apply
3696 * additional signature.
3697 *
3698 * @param {INewCardParams} cardParams - New card parameters.
3699 * @returns {RawSignedModel}
3700 */
3701 CardManager.prototype.generateRawCard = function (cardParams) {
3702 var model = generateRawSigned(this.crypto, cardParams);
3703 this.modelSigner.sign({
3704 model: model,
3705 signerPrivateKey: cardParams.privateKey,
3706 signer: SelfSigner,
3707 extraFields: cardParams.extraFields
3708 });
3709 return model;
3710 };
3711 /**
3712 * Generates a card from `cardParams` and publishes it in the Virgil Cards
3713 * Service.
3714 * @param {INewCardParams} cardParams - New card parameters.
3715 * @returns {Promise<ICard>}
3716 */
3717 CardManager.prototype.publishCard = function (cardParams) {
3718 return __awaiter(this, void 0, void 0, function () {
3719 var tokenContext, token, rawSignedModel;
3720 return __generator(this, function (_a) {
3721 switch (_a.label) {
3722 case 0:
3723 validateCardParams(cardParams);
3724 tokenContext = { identity: cardParams.identity, operation: 'publish' };
3725 return [4 /*yield*/, this.accessTokenProvider.getToken(tokenContext)];
3726 case 1:
3727 token = _a.sent();
3728 rawSignedModel = this.generateRawCard(Object.assign({}, cardParams, { identity: token.identity() }));
3729 return [4 /*yield*/, this.publishRawSignedModel(rawSignedModel, tokenContext, token)];
3730 case 2: return [2 /*return*/, _a.sent()];
3731 }
3732 });
3733 });
3734 };
3735 /**
3736 * Publishes a previously generated card in the form of
3737 * {@link RawSignedModel} object.
3738 *
3739 * @param {RawSignedModel} rawCard - The card to publish.
3740 * @returns {Promise<ICard>}
3741 */
3742 CardManager.prototype.publishRawCard = function (rawCard) {
3743 return __awaiter(this, void 0, void 0, function () {
3744 var cardDetails, tokenContext, token;
3745 return __generator(this, function (_a) {
3746 switch (_a.label) {
3747 case 0:
3748 assert(rawCard != null && rawCard.contentSnapshot != null, '`rawCard` should not be empty');
3749 cardDetails = JSON.parse(rawCard.contentSnapshot);
3750 tokenContext = { identity: cardDetails.identity, operation: 'publish' };
3751 return [4 /*yield*/, this.accessTokenProvider.getToken(tokenContext)];
3752 case 1:
3753 token = _a.sent();
3754 return [2 /*return*/, this.publishRawSignedModel(rawCard, tokenContext, token)];
3755 }
3756 });
3757 });
3758 };
3759 /**
3760 * Fetches the card by `cardId` from the Virgil Card Service.
3761 * @param {string} cardId - Id of the card to fetch.
3762 * @returns {Promise<ICard>}
3763 */
3764 CardManager.prototype.getCard = function (cardId) {
3765 return __awaiter(this, void 0, void 0, function () {
3766 var tokenContext, accessToken, cardWithStatus, card;
3767 var _this = this;
3768 return __generator(this, function (_a) {
3769 switch (_a.label) {
3770 case 0:
3771 tokenContext = { operation: 'get' };
3772 return [4 /*yield*/, this.accessTokenProvider.getToken(tokenContext)];
3773 case 1:
3774 accessToken = _a.sent();
3775 return [4 /*yield*/, this.tryDo(tokenContext, accessToken, function (token) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
3776 switch (_a.label) {
3777 case 0: return [4 /*yield*/, this.client.getCard(cardId, token.toString())];
3778 case 1: return [2 /*return*/, _a.sent()];
3779 }
3780 }); }); })];
3781 case 2:
3782 cardWithStatus = _a.sent();
3783 card = parseRawSignedModel(this.crypto, cardWithStatus.cardRaw, cardWithStatus.isOutdated);
3784 if (card.id !== cardId) {
3785 throw new VirgilCardVerificationError('Received invalid card');
3786 }
3787 this.validateCards([card]);
3788 return [2 /*return*/, card];
3789 }
3790 });
3791 });
3792 };
3793 /**
3794 * Fetches collection of cards with the given `identity` from the Virgil
3795 * Cards Service.
3796 * @param {string|string[]} identities - Identity or an array of identities of the cards to fetch.
3797 * @returns {Promise<ICard[]>}
3798 */
3799 CardManager.prototype.searchCards = function (identities) {
3800 return __awaiter(this, void 0, void 0, function () {
3801 var identitiesArr, tokenContext, accessToken, rawCards, cards, identitiesSet;
3802 var _this = this;
3803 return __generator(this, function (_a) {
3804 switch (_a.label) {
3805 case 0:
3806 if (!identities)
3807 throw new TypeError('Argument `identities` is required');
3808 identitiesArr = Array.isArray(identities) ? identities : [identities];
3809 if (identitiesArr.length === 0)
3810 throw new TypeError('Identities array must not be empty');
3811 tokenContext = { operation: 'search' };
3812 return [4 /*yield*/, this.accessTokenProvider.getToken(tokenContext)];
3813 case 1:
3814 accessToken = _a.sent();
3815 return [4 /*yield*/, this.tryDo(tokenContext, accessToken, function (token) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
3816 switch (_a.label) {
3817 case 0: return [4 /*yield*/, this.client.searchCards(identitiesArr, token.toString())];
3818 case 1: return [2 /*return*/, _a.sent()];
3819 }
3820 }); }); })];
3821 case 2:
3822 rawCards = _a.sent();
3823 cards = rawCards.map(function (raw) { return parseRawSignedModel(_this.crypto, raw, false); });
3824 identitiesSet = new Set(identitiesArr);
3825 if (cards.some(function (c) { return !identitiesSet.has(c.identity); })) {
3826 throw new VirgilCardVerificationError('Received invalid cards');
3827 }
3828 this.validateCards(cards);
3829 return [2 /*return*/, linkedCardList(cards)];
3830 }
3831 });
3832 });
3833 };
3834 /**
3835 * Converts the card in the form of {@link RawSignedModel} object to the
3836 * {@link ICard} object.
3837 *
3838 * @see {@link CardManager.exportCard}
3839 *
3840 * @param {RawSignedModel} rawCard - The card to convert.
3841 * @returns {ICard}
3842 */
3843 CardManager.prototype.importCard = function (rawCard) {
3844 var card = parseRawSignedModel(this.crypto, rawCard);
3845 this.validateCards([card]);
3846 return card;
3847 };
3848 /**
3849 * Converts the card in the base64 string form to the {@link ICard} object.
3850 *
3851 * @see {@link CardManager.exportCardAsString}
3852 *
3853 * @param {string} str - The string in base64.
3854 * @returns {ICard}
3855 */
3856 CardManager.prototype.importCardFromString = function (str) {
3857 assert(Boolean(str), '`str` should not be empty');
3858 return this.importCard(RawSignedModel.fromString(str));
3859 };
3860 /**
3861 * Converts the card in the JSON-serializable object form to the
3862 * {@link ICard} object.
3863 *
3864 * @see {@link CardManager.exportCardAsJson}
3865 *
3866 * @param {IRawSignedModelJson} json
3867 * @returns {ICard}
3868 */
3869 CardManager.prototype.importCardFromJson = function (json) {
3870 assert(Boolean(json), '`json` should not be empty');
3871 return this.importCard(RawSignedModel.fromJson(json));
3872 };
3873 /**
3874 * Converts the card in the form of {@link ICard} object to the
3875 * {@link RawSignedModel} object.
3876 *
3877 * @see {@link CardManager.importCard}
3878 *
3879 * @param {ICard} card
3880 * @returns {RawSignedModel}
3881 */
3882 CardManager.prototype.exportCard = function (card) {
3883 return cardToRawSignedModel(card);
3884 };
3885 /**
3886 * Converts the card in the form of {@link ICard} object to the string
3887 * in base64 encoding.
3888 *
3889 * @see {@link CardManager.importCardFromString}
3890 *
3891 * @param {ICard} card
3892 * @returns {string}
3893 */
3894 CardManager.prototype.exportCardAsString = function (card) {
3895 return this.exportCard(card).toString();
3896 };
3897 /**
3898 * Converts the card in the form of {@link ICard} object to the
3899 * JSON-serializable object form.
3900 *
3901 * @see {@link CardManager.importCardFromJson}
3902 *
3903 * @param {ICard} card
3904 * @returns {IRawSignedModelJson}
3905 */
3906 CardManager.prototype.exportCardAsJson = function (card) {
3907 return this.exportCard(card).toJson();
3908 };
3909 /**
3910 * @hidden
3911 */
3912 CardManager.prototype.publishRawSignedModel = function (rawCard, context, accessToken) {
3913 return __awaiter(this, void 0, void 0, function () {
3914 var publishedModel, card;
3915 var _this = this;
3916 return __generator(this, function (_a) {
3917 switch (_a.label) {
3918 case 0:
3919 if (!(this.signCallback != null)) return [3 /*break*/, 2];
3920 return [4 /*yield*/, this.signCallback(rawCard)];
3921 case 1:
3922 rawCard = _a.sent();
3923 _a.label = 2;
3924 case 2: return [4 /*yield*/, this.tryDo(context, accessToken, function (token) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
3925 switch (_a.label) {
3926 case 0: return [4 /*yield*/, this.client.publishCard(rawCard, token.toString())];
3927 case 1: return [2 /*return*/, _a.sent()];
3928 }
3929 }); }); })];
3930 case 3:
3931 publishedModel = _a.sent();
3932 if (rawCard.contentSnapshot !== publishedModel.contentSnapshot) {
3933 throw new VirgilCardVerificationError('Received invalid card');
3934 }
3935 card = parseRawSignedModel(this.crypto, publishedModel);
3936 this.validateCards([card]);
3937 return [2 /*return*/, card];
3938 }
3939 });
3940 });
3941 };
3942 /**
3943 * @hidden
3944 */
3945 CardManager.prototype.tryDo = function (context, token, func) {
3946 return __awaiter(this, void 0, void 0, function () {
3947 var e_1;
3948 return __generator(this, function (_a) {
3949 switch (_a.label) {
3950 case 0:
3951 _a.trys.push([0, 2, , 6]);
3952 return [4 /*yield*/, func(token)];
3953 case 1: return [2 /*return*/, _a.sent()];
3954 case 2:
3955 e_1 = _a.sent();
3956 if (!(e_1 instanceof VirgilHttpError &&
3957 e_1.httpStatus === 401 &&
3958 e_1.errorCode === ErrorCode.AccessTokenExpired &&
3959 this.retryOnUnauthorized)) return [3 /*break*/, 5];
3960 return [4 /*yield*/, this.accessTokenProvider.getToken({
3961 identity: context.identity,
3962 operation: context.operation,
3963 forceReload: true
3964 })];
3965 case 3:
3966 token = _a.sent();
3967 return [4 /*yield*/, func(token)];
3968 case 4: return [2 /*return*/, _a.sent()];
3969 case 5: throw e_1;
3970 case 6: return [2 /*return*/];
3971 }
3972 });
3973 });
3974 };
3975 /**
3976 * Delegates to the {@link CardManager.cardVerifier} to verify the validity
3977 * of the `cards`.
3978 *
3979 * @throws {@link VirgilCardVerificationError} if any of the cards is not
3980 * valid.
3981 *
3982 * @param {ICard[]} cards
3983 */
3984 CardManager.prototype.validateCards = function (cards) {
3985 if (this.cardVerifier == null)
3986 return;
3987 for (var _i = 0, cards_1 = cards; _i < cards_1.length; _i++) {
3988 var card = cards_1[_i];
3989 if (!this.cardVerifier.verifyCard(card)) {
3990 throw new VirgilCardVerificationError('Validation errors have been detected');
3991 }
3992 }
3993 };
3994 return CardManager;
3995 }());
3996 /**
3997 * @hidden
3998 */
3999 function validateCardParams(params, validateIdentity) {
4000 if (validateIdentity === void 0) { validateIdentity = false; }
4001 assert(params != null, 'Card parameters must be provided');
4002 assert(params.privateKey != null, 'Card\'s private key is required');
4003 assert(params.publicKey != null, 'Card\'s public key is required');
4004 if (validateIdentity) {
4005 assert(typeof params.identity === 'string' && params.identity !== '', 'Card\'s identity is required');
4006 }
4007 }
4008
4009 var DEFAULTS = {
4010 verifySelfSignature: true,
4011 verifyVirgilSignature: true,
4012 whitelists: []
4013 };
4014 var VIRGIL_CARDS_PUBKEY_BASE64 = 'MCowBQYDK2VwAyEAljOYGANYiVq1WbvVvoYIKtvZi2ji9bAhxyu6iV/LF8M=';
4015 /**
4016 * Class responsible for validating cards by verifying their digital
4017 * signatures.
4018 */
4019 var VirgilCardVerifier = /** @class */ (function () {
4020 /**
4021 * Initializes a new instance of `VirgilCardVerifier`.
4022 * @param {ICardCrypto} crypto - Object implementing the
4023 * {@link ICardCrypto} interface.
4024 * @param {IVirgilCardVerifierParams} options - Initialization options.
4025 */
4026 function VirgilCardVerifier(crypto, options) {
4027 this.crypto = crypto;
4028 var params = __assign({}, DEFAULTS, (options || {}));
4029 this.verifySelfSignature = params.verifySelfSignature;
4030 this.verifyVirgilSignature = params.verifyVirgilSignature;
4031 this.whitelists = params.whitelists;
4032 this.virgilCardsPublicKey = crypto.importPublicKey(VIRGIL_CARDS_PUBKEY_BASE64);
4033 }
4034 /**
4035 * Verifies the signatures of the `card`.
4036 * @param {ICard} card
4037 * @returns {boolean} `true` if the signatures to be verified are present
4038 * and valid, otherwise `false`.
4039 */
4040 VirgilCardVerifier.prototype.verifyCard = function (card) {
4041 var _this = this;
4042 if (this.selfValidationFailed(card)) {
4043 return false;
4044 }
4045 if (this.virgilValidationFailed(card)) {
4046 return false;
4047 }
4048 if (!this.whitelists || this.whitelists.length === 0) {
4049 return true;
4050 }
4051 var signers = card.signatures.map(function (s) { return s.signer; });
4052 for (var _i = 0, _a = this.whitelists; _i < _a.length; _i++) {
4053 var whitelist = _a[_i];
4054 if (whitelist == null || whitelist.length === 0) {
4055 return false;
4056 }
4057 var intersectedCreds = whitelist.filter(function (x) { return signers.indexOf(x.signer) !== -1; });
4058 if (intersectedCreds.length === 0) {
4059 return false;
4060 }
4061 var isValidForSome = intersectedCreds.some(function (cred) {
4062 return _this.validateSignerSignature(card, _this.getPublicKey(cred.publicKeyBase64), cred.signer);
4063 });
4064 if (!isValidForSome) {
4065 return false;
4066 }
4067 }
4068 return true;
4069 };
4070 VirgilCardVerifier.prototype.selfValidationFailed = function (card) {
4071 return this.verifySelfSignature
4072 && !this.validateSignerSignature(card, card.publicKey, SelfSigner);
4073 };
4074 VirgilCardVerifier.prototype.virgilValidationFailed = function (card) {
4075 return this.verifyVirgilSignature
4076 && !this.validateSignerSignature(card, this.virgilCardsPublicKey, VirgilSigner);
4077 };
4078 VirgilCardVerifier.prototype.getPublicKey = function (signerPublicKeyBase64) {
4079 return this.crypto.importPublicKey(signerPublicKeyBase64);
4080 };
4081 VirgilCardVerifier.prototype.validateSignerSignature = function (card, signerPublicKey, signer) {
4082 var signature = card.signatures.find(function (s) { return s.signer === signer; });
4083 if (signature == null)
4084 return false;
4085 var extendedSnapshot = signature.snapshot == null
4086 ? card.contentSnapshot
4087 : card.contentSnapshot + signature.snapshot;
4088 return this.crypto.verifySignature(extendedSnapshot, signature.signature, signerPublicKey);
4089 };
4090 return VirgilCardVerifier;
4091 }());
4092
4093 // Some code originally from localForage
4094 // See: https://github.com/localForage/localForage/blob/master/src/utils/isIndexedDBValid.js
4095 /**
4096 * @hidden
4097 * @returns {boolean}
4098 */
4099 function isIndexedDbValid() {
4100 // We mimic PouchDB here
4101 // Following #7085 (see https://github.com/pouchdb/pouchdb/issues/7085)
4102 // buggy idb versions (typically Safari < 10.1) are considered valid.
4103 // On Firefox SecurityError is thrown while referencing indexedDB if cookies
4104 // are not allowed. `typeof indexedDB` also triggers the error.
4105 try {
4106 // some outdated implementations of IDB that appear on Samsung
4107 // and HTC Android devices <4.4 are missing IDBKeyRange
4108 return typeof indexedDB !== 'undefined' && typeof IDBKeyRange !== 'undefined';
4109 }
4110 catch (e) {
4111 return false;
4112 }
4113 }
4114
4115 /**
4116 * Error thrown by {@link IStorageAdapter.store} method when saving a value
4117 * with a key that already exists in store.
4118 */
4119 var StorageEntryAlreadyExistsError = /** @class */ (function (_super) {
4120 __extends(StorageEntryAlreadyExistsError, _super);
4121 function StorageEntryAlreadyExistsError(key) {
4122 return _super.call(this, "Storage entry " + (key ? 'with key ' + name : 'with the given key') + "already exists", 'StorageEntryAlreadyExistsError') || this;
4123 }
4124 return StorageEntryAlreadyExistsError;
4125 }(VirgilError));
4126
4127 // Some code originally from localForage in
4128 // [localForage](https://github.com/localForage/localForage).
4129 // Transaction Modes
4130 var READ_ONLY = 'readonly';
4131 var READ_WRITE = 'readwrite';
4132 var dbContexts = {};
4133 /**
4134 * Implementation of {@link IStorageAdapter} that uses IndexedDB for
4135 * persistence. For use in browsers.
4136 */
4137 var IndexedDbStorageAdapter = /** @class */ (function () {
4138 /**
4139 * Initializes an instance of `IndexedDbStorageAdapter`.
4140 * @param {IStorageAdapterConfig} config - Configuration options.
4141 * Currently only `name` is supported and must be the name of the
4142 * IndexedDB database where the data will be stored.
4143 */
4144 function IndexedDbStorageAdapter(config) {
4145 var _this = this;
4146 // Open the IndexedDB database (automatically creates one if one didn't
4147 // previously exist), using any options set in the config.
4148 this._initStorage = function () {
4149 var dbInfo = {
4150 db: null,
4151 name: _this._defaultConfig.name,
4152 storeName: _this._defaultConfig.storeName,
4153 version: _this._defaultConfig.version
4154 };
4155 // Get the current context of the database;
4156 var dbContext = dbContexts[dbInfo.name];
4157 // ...or create a new context.
4158 if (!dbContext) {
4159 dbContext = createDbContext();
4160 // Register the new context in the global container.
4161 dbContexts[dbInfo.name] = dbContext;
4162 }
4163 // Initialize the connection process only when
4164 // all the related storages aren't pending.
4165 return Promise.resolve()
4166 .then(function () {
4167 dbInfo.db = dbContext.db;
4168 // Get the connection or open a new one without upgrade.
4169 return _getOriginalConnection(dbInfo);
4170 })
4171 .then(function (db) {
4172 dbInfo.db = db;
4173 if (_isUpgradeNeeded(dbInfo, _this._defaultConfig.version)) {
4174 // Reopen the database for upgrading.
4175 return _getUpgradedConnection(dbInfo);
4176 }
4177 return db;
4178 })
4179 .then(function (db) {
4180 dbInfo.db = dbContext.db = db;
4181 _this._dbInfo = dbInfo;
4182 });
4183 };
4184 // Specialize the default `ready()` function by making it dependent
4185 // on the current database operations. Thus, the driver will be actually
4186 // ready when it's been initialized (default) *and* there are no pending
4187 // operations on the database (initiated by some other instances).
4188 this.ready = function () {
4189 var promise = _this._ready.then(function () {
4190 var dbContext = dbContexts[_this._dbInfo.name];
4191 if (dbContext && dbContext.dbReady) {
4192 return dbContext.dbReady;
4193 }
4194 });
4195 return promise;
4196 };
4197 if (!isIndexedDbValid()) {
4198 throw new Error('Cannot use IndexedDbStorageAdapter. indexedDb is not supported');
4199 }
4200 this._defaultConfig = {
4201 name: config.name,
4202 version: 1,
4203 storeName: 'keyvaluepairs'
4204 };
4205 this._ready = this._initStorage();
4206 }
4207 /**
4208 * @inheritDoc
4209 */
4210 IndexedDbStorageAdapter.prototype.store = function (key, data) {
4211 var _this = this;
4212 key = normalizeKey(key);
4213 return new Promise(function (resolve, reject) {
4214 _this.ready().then(function () {
4215 createTransaction(_this._dbInfo, READ_WRITE, function (err, transaction) {
4216 if (err) {
4217 return reject(err);
4218 }
4219 try {
4220 var store = transaction.objectStore(_this._dbInfo.storeName);
4221 var req_1 = store.add(toArrayBuffer(data), key);
4222 transaction.oncomplete = function () {
4223 resolve();
4224 };
4225 transaction.onabort = transaction.onerror = function () {
4226 var error = req_1.error
4227 ? req_1.error
4228 : req_1.transaction.error;
4229 if (error && error.name === 'ConstraintError') {
4230 reject(new StorageEntryAlreadyExistsError(key));
4231 }
4232 reject(error);
4233 };
4234 }
4235 catch (error) {
4236 reject(error);
4237 }
4238 });
4239 }).catch(reject);
4240 });
4241 };
4242 /**
4243 * @inheritDoc
4244 */
4245 IndexedDbStorageAdapter.prototype.load = function (key) {
4246 var _this = this;
4247 key = normalizeKey(key);
4248 return new Promise(function (resolve, reject) {
4249 _this.ready().then(function () {
4250 createTransaction(_this._dbInfo, READ_ONLY, function (err, transaction) {
4251 if (err) {
4252 return reject(err);
4253 }
4254 try {
4255 var store = transaction.objectStore(_this._dbInfo.storeName);
4256 var req_2 = store.get(key);
4257 req_2.onsuccess = function () {
4258 if (req_2.result == null) {
4259 return resolve(null);
4260 }
4261 var arrayBuffer = req_2.result;
4262 var buffer = Buffer.from(arrayBuffer);
4263 resolve(buffer);
4264 };
4265 req_2.onerror = function () {
4266 reject(req_2.error);
4267 };
4268 }
4269 catch (e) {
4270 reject(e);
4271 }
4272 });
4273 }).catch(reject);
4274 });
4275 };
4276 /**
4277 * @inheritDoc
4278 */
4279 IndexedDbStorageAdapter.prototype.exists = function (key) {
4280 var _this = this;
4281 key = normalizeKey(key);
4282 return new Promise(function (resolve, reject) {
4283 _this.ready().then(function () {
4284 createTransaction(_this._dbInfo, READ_ONLY, function (err, transaction) {
4285 if (err) {
4286 return reject(err);
4287 }
4288 try {
4289 var store = transaction.objectStore(_this._dbInfo.storeName);
4290 var req_3 = store.openCursor(key);
4291 req_3.onsuccess = function () {
4292 var cursor = req_3.result;
4293 resolve(cursor !== null);
4294 };
4295 req_3.onerror = function () {
4296 reject(req_3.error);
4297 };
4298 }
4299 catch (e) {
4300 reject(e);
4301 }
4302 });
4303 }).catch(reject);
4304 });
4305 };
4306 /**
4307 * @inheritDoc
4308 */
4309 IndexedDbStorageAdapter.prototype.remove = function (key) {
4310 var _this = this;
4311 key = normalizeKey(key);
4312 return new Promise(function (resolve, reject) {
4313 _this.ready().then(function () {
4314 createTransaction(_this._dbInfo, READ_WRITE, function (err, transaction) {
4315 if (err) {
4316 return reject(err);
4317 }
4318 try {
4319 var store_1 = transaction.objectStore(_this._dbInfo.storeName);
4320 var countReq_1 = store_1.count(key);
4321 var delReq_1;
4322 countReq_1.onsuccess = function () {
4323 var count = countReq_1.result;
4324 if (count === 0) {
4325 return resolve(false);
4326 }
4327 // safe for IE and some versions of Android
4328 // (including those used by Cordova).
4329 // Normally IE won't like `.delete()` and will insist on
4330 // using `['delete']()`
4331 delReq_1 = store_1['delete'](key);
4332 delReq_1.onsuccess = function () { return resolve(true); };
4333 };
4334 // The request will be also be aborted if we've exceeded our storage
4335 // space.
4336 transaction.onabort = transaction.onerror = function () {
4337 var req = delReq_1 || countReq_1;
4338 var err = req.error
4339 ? req.error
4340 : req.transaction.error;
4341 reject(err);
4342 };
4343 }
4344 catch (e) {
4345 reject(e);
4346 }
4347 });
4348 }).catch(reject);
4349 });
4350 };
4351 /**
4352 * @inheritDoc
4353 */
4354 IndexedDbStorageAdapter.prototype.update = function (key, data) {
4355 var _this = this;
4356 key = normalizeKey(key);
4357 return new Promise(function (resolve, reject) {
4358 _this.ready().then(function () {
4359 createTransaction(_this._dbInfo, READ_WRITE, function (err, transaction) {
4360 if (err) {
4361 return reject(err);
4362 }
4363 try {
4364 var store = transaction.objectStore(_this._dbInfo.storeName);
4365 var req_4 = store.put(toArrayBuffer(data), key);
4366 req_4.onsuccess = function () {
4367 resolve();
4368 };
4369 req_4.onerror = function () {
4370 reject(req_4.error);
4371 };
4372 }
4373 catch (error) {
4374 reject(error);
4375 }
4376 });
4377 }).catch(reject);
4378 });
4379 };
4380 /**
4381 * @inheritDoc
4382 */
4383 IndexedDbStorageAdapter.prototype.clear = function () {
4384 var _this = this;
4385 return new Promise(function (resolve, reject) {
4386 _this.ready().then(function () {
4387 createTransaction(_this._dbInfo, READ_WRITE, function (err, transaction) {
4388 if (err) {
4389 return reject(err);
4390 }
4391 try {
4392 var store = transaction.objectStore(_this._dbInfo.storeName);
4393 var req_5 = store.clear();
4394 transaction.oncomplete = function () { return resolve(); };
4395 transaction.onabort = transaction.onerror = function () {
4396 var err = req_5.error
4397 ? req_5.error
4398 : req_5.transaction.error;
4399 reject(err);
4400 };
4401 }
4402 catch (e) {
4403 reject(e);
4404 }
4405 });
4406 }).catch(reject);
4407 });
4408 };
4409 /**
4410 * @inheritDoc
4411 */
4412 IndexedDbStorageAdapter.prototype.list = function () {
4413 var _this = this;
4414 return new Promise(function (resolve, reject) {
4415 _this.ready().then(function () {
4416 createTransaction(_this._dbInfo, READ_ONLY, function (err, transaction) {
4417 if (err) {
4418 return reject(err);
4419 }
4420 try {
4421 var store = transaction.objectStore(_this._dbInfo.storeName);
4422 var req_6 = store.openCursor();
4423 var entries_1 = [];
4424 req_6.onsuccess = function () {
4425 var cursor = req_6.result;
4426 if (!cursor) {
4427 resolve(entries_1);
4428 }
4429 else {
4430 entries_1.push(Buffer.from(cursor.value));
4431 cursor.continue();
4432 }
4433 };
4434 req_6.onerror = function () {
4435 reject(req_6.error);
4436 };
4437 }
4438 catch (e) {
4439 reject(e);
4440 }
4441 });
4442 }).catch(reject);
4443 });
4444 };
4445 return IndexedDbStorageAdapter;
4446 }());
4447 function createDbContext() {
4448 return {
4449 // Database.
4450 db: null,
4451 // Database readiness (promise).
4452 dbReady: null,
4453 // Deferred operations on the database.
4454 deferredOperations: []
4455 };
4456 }
4457 function _deferReadiness(dbInfo) {
4458 var dbContext = dbContexts[dbInfo.name];
4459 // Create a deferred object representing the current database operation.
4460 var deferredOperation = {};
4461 deferredOperation.promise = new Promise(function (resolve, reject) {
4462 deferredOperation.resolve = resolve;
4463 deferredOperation.reject = reject;
4464 });
4465 // Enqueue the deferred operation.
4466 dbContext.deferredOperations.push(deferredOperation);
4467 // Chain its promise to the database readiness.
4468 if (!dbContext.dbReady) {
4469 dbContext.dbReady = deferredOperation.promise;
4470 }
4471 else {
4472 dbContext.dbReady = dbContext.dbReady.then(function () { return deferredOperation.promise; });
4473 }
4474 }
4475 function _advanceReadiness(dbInfo) {
4476 var dbContext = dbContexts[dbInfo.name];
4477 // Dequeue a deferred operation.
4478 var deferredOperation = dbContext.deferredOperations.pop();
4479 // Resolve its promise (which is part of the database readiness
4480 // chain of promises).
4481 if (deferredOperation) {
4482 deferredOperation.resolve();
4483 return deferredOperation.promise;
4484 }
4485 }
4486 function _rejectReadiness(dbInfo, err) {
4487 var dbContext = dbContexts[dbInfo.name];
4488 // Dequeue a deferred operation.
4489 var deferredOperation = dbContext.deferredOperations.pop();
4490 // Reject its promise (which is part of the database readiness
4491 // chain of promises).
4492 if (deferredOperation) {
4493 deferredOperation.reject(err);
4494 return deferredOperation.promise;
4495 }
4496 }
4497 function _getConnection(dbInfo, upgradeNeeded) {
4498 return new Promise(function (resolve, reject) {
4499 dbContexts[dbInfo.name] = dbContexts[dbInfo.name] || createDbContext();
4500 if (dbInfo.db) {
4501 if (upgradeNeeded) {
4502 _deferReadiness(dbInfo);
4503 dbInfo.db.close();
4504 }
4505 else {
4506 return resolve(dbInfo.db);
4507 }
4508 }
4509 var dbArgs = [dbInfo.name];
4510 if (upgradeNeeded) {
4511 dbArgs.push(String(dbInfo.version));
4512 }
4513 var openReq = indexedDB.open.apply(indexedDB, dbArgs);
4514 if (upgradeNeeded) {
4515 openReq.onupgradeneeded = function (e) {
4516 var db = openReq.result;
4517 try {
4518 db.createObjectStore(dbInfo.storeName);
4519 }
4520 catch (ex) {
4521 if (ex.name === 'ConstraintError') {
4522 console.warn('The database "' +
4523 dbInfo.name +
4524 '"' +
4525 ' has been upgraded from version ' +
4526 e.oldVersion +
4527 ' to version ' +
4528 e.newVersion +
4529 ', but the storage "' +
4530 dbInfo.storeName +
4531 '" already exists.');
4532 }
4533 else {
4534 throw ex;
4535 }
4536 }
4537 };
4538 }
4539 openReq.onerror = function (e) {
4540 e.preventDefault();
4541 reject(openReq.error);
4542 };
4543 openReq.onsuccess = function () {
4544 resolve(openReq.result);
4545 _advanceReadiness(dbInfo);
4546 };
4547 });
4548 }
4549 function _getOriginalConnection(dbInfo) {
4550 return _getConnection(dbInfo, false);
4551 }
4552 function _getUpgradedConnection(dbInfo) {
4553 return _getConnection(dbInfo, true);
4554 }
4555 function _isUpgradeNeeded(dbInfo, defaultVersion) {
4556 if (!dbInfo.db) {
4557 return true;
4558 }
4559 var isNewStore = !dbInfo.db.objectStoreNames.contains(dbInfo.storeName);
4560 var isDowngrade = dbInfo.version < dbInfo.db.version;
4561 var isUpgrade = dbInfo.version > dbInfo.db.version;
4562 if (isDowngrade) {
4563 // If the version is not the default one
4564 // then warn for impossible downgrade.
4565 if (dbInfo.version !== defaultVersion) {
4566 console.warn('The database "' +
4567 dbInfo.name +
4568 '"' +
4569 " can't be downgraded from version " +
4570 dbInfo.db.version +
4571 ' to version ' +
4572 dbInfo.version +
4573 '.');
4574 }
4575 // Align the versions to prevent errors.
4576 dbInfo.version = dbInfo.db.version;
4577 }
4578 if (isUpgrade || isNewStore) {
4579 // If the store is new then increment the version (if needed).
4580 // This will trigger an "upgradeneeded" event which is required
4581 // for creating a store.
4582 if (isNewStore) {
4583 var incVersion = dbInfo.db.version + 1;
4584 if (incVersion > dbInfo.version) {
4585 dbInfo.version = incVersion;
4586 }
4587 }
4588 return true;
4589 }
4590 return false;
4591 }
4592 // Try to establish a new db connection to replace the
4593 // current one which is broken (i.e. experiencing
4594 // InvalidStateError while creating a transaction).
4595 function _tryReconnect(dbInfo) {
4596 _deferReadiness(dbInfo);
4597 var dbContext = dbContexts[dbInfo.name];
4598 dbInfo.db = null;
4599 return _getOriginalConnection(dbInfo)
4600 .then(function (db) {
4601 dbInfo.db = db;
4602 if (_isUpgradeNeeded(dbInfo)) {
4603 // Reopen the database for upgrading.
4604 return _getUpgradedConnection(dbInfo);
4605 }
4606 return db;
4607 })
4608 .then(function (db) {
4609 // store the latest db reference
4610 // in case the db was upgraded
4611 dbInfo.db = dbContext.db = db;
4612 })
4613 .catch(function (err) {
4614 _rejectReadiness(dbInfo, err);
4615 throw err;
4616 });
4617 }
4618 // FF doesn't like Promises (micro-tasks) and IDDB store operations,
4619 // so we have to do it with callbacks
4620 function createTransaction(dbInfo, mode, callback, retries) {
4621 if (retries === undefined) {
4622 retries = 1;
4623 }
4624 try {
4625 var tx = dbInfo.db.transaction(dbInfo.storeName, mode);
4626 callback(null, tx);
4627 }
4628 catch (err) {
4629 if (retries > 0 &&
4630 (!dbInfo.db ||
4631 err.name === 'InvalidStateError' ||
4632 err.name === 'NotFoundError')) {
4633 Promise.resolve()
4634 .then(function () {
4635 if (!dbInfo.db ||
4636 (err.name === 'NotFoundError' &&
4637 !dbInfo.db.objectStoreNames.contains(dbInfo.storeName) &&
4638 dbInfo.version <= dbInfo.db.version)) {
4639 // increase the db version, to create the new ObjectStore
4640 if (dbInfo.db) {
4641 dbInfo.version = dbInfo.db.version + 1;
4642 }
4643 // Reopen the database for upgrading.
4644 return _getUpgradedConnection(dbInfo);
4645 }
4646 })
4647 .then(function () {
4648 return _tryReconnect(dbInfo).then(function () {
4649 createTransaction(dbInfo, mode, callback, retries - 1);
4650 });
4651 })
4652 .catch(callback);
4653 }
4654 callback(err);
4655 }
4656 }
4657 function normalizeKey(key) {
4658 // Cast the key to a string, as that's all we can set as a key.
4659 if (typeof key !== 'string') {
4660 console.warn(key + " used as a key, but it is not a string.");
4661 key = String(key);
4662 }
4663 return key;
4664 }
4665 // taken from here https://github.com/jhiesey/to-arraybuffer
4666 function toArrayBuffer(buf) {
4667 // If the buffer is backed by a Uint8Array, a faster version will work
4668 if (buf instanceof Uint8Array) {
4669 // If the buffer isn't a subarray, return the underlying ArrayBuffer
4670 if (buf.byteOffset === 0 && buf.byteLength === buf.buffer.byteLength) {
4671 return buf.buffer;
4672 }
4673 else if (typeof buf.buffer.slice === 'function') {
4674 // Otherwise we need to get a proper copy
4675 return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
4676 }
4677 }
4678 if (Buffer.isBuffer(buf)) {
4679 // This is the slow version that will work with any Buffer
4680 // implementation (even in old browsers)
4681 var arrayCopy = new Uint8Array(buf.length);
4682 var len = buf.length;
4683 for (var i = 0; i < len; i++) {
4684 arrayCopy[i] = buf[i];
4685 }
4686 return arrayCopy.buffer;
4687 }
4688 else {
4689 throw new Error('Argument must be a Buffer');
4690 }
4691 }
4692
4693 /**
4694 * {@link FileSystemStorageAdapter} or {@link IndexedDbStorageAdapter}
4695 * depending on the target platform (node or browser).
4696 */
4697
4698 /**
4699 * Error thrown from {@link PrivateKeyStorage.save} method when saving
4700 * a private key with a name that already exists in store.
4701 */
4702 var PrivateKeyExistsError = /** @class */ (function (_super) {
4703 __extends(PrivateKeyExistsError, _super);
4704 function PrivateKeyExistsError(message) {
4705 if (message === void 0) { message = 'Private key with same name already exists'; }
4706 return _super.call(this, message, 'PrivateKeyExistsError') || this;
4707 }
4708 return PrivateKeyExistsError;
4709 }(VirgilError));
4710
4711 var DEFAULTS$1 = {
4712 dir: '.virgil_keys',
4713 name: 'VirgilKeys'
4714 };
4715 /**
4716 * Class representing a storage container for private key data.
4717 * Use this class if you need to load the keys stored with
4718 * version 4.x of this library. For new code, use the
4719 * {@link PrivateKeyStorage} instead.
4720 *
4721 * @deprecated since version 5.0
4722 */
4723 var KeyStorage = /** @class */ (function () {
4724 function KeyStorage(config) {
4725 if (config === void 0) { config = {}; }
4726 console.log('Warning! `KeyStorage` is deprecated. Use `PrivateKeyStorage` instead.');
4727 this.adapter = resolveAdapter(config);
4728 }
4729 /**
4730 * Checks whether a private key data with the given name exist in persistent storage.
4731 * @param {string} name - Name to check.
4732 * @returns {Promise<boolean>} - True if key data exist, otherwise false.
4733 */
4734 KeyStorage.prototype.exists = function (name) {
4735 validateName(name);
4736 return this.adapter.exists(name);
4737 };
4738 /**
4739 * Loads the private key data by the given name.
4740 * @param {string} name - Name of key data to load.
4741 * @returns {Promise<Buffer | null>} - Private key data as Buffer,
4742 * or null if there is no data for the given name.
4743 */
4744 KeyStorage.prototype.load = function (name) {
4745 validateName(name);
4746 return this.adapter.load(name);
4747 };
4748 /**
4749 * Removes the private key data stored under the given name from persistent storage.
4750 * @param {string} name - Name of the key data to remove.
4751 * @returns {Promise<boolean>} - True if the key has been removed, otherwise false.
4752 */
4753 KeyStorage.prototype.remove = function (name) {
4754 validateName(name);
4755 return this.adapter.remove(name);
4756 };
4757 /**
4758 * Persists the private key data under the given name.
4759 * @param {string} name - Name of the key data.
4760 * @param {Buffer} data - The key data.
4761 * @returns {Promise<void>}
4762 */
4763 KeyStorage.prototype.save = function (name, data) {
4764 validateName(name);
4765 validateData(data);
4766 return this.adapter.store(name, data)
4767 .catch(function (error) {
4768 if (error && error.code === 'EEXIST') {
4769 return Promise.reject(new PrivateKeyExistsError());
4770 }
4771 return Promise.reject(error);
4772 });
4773 };
4774 return KeyStorage;
4775 }());
4776 function resolveAdapter(config) {
4777 if (typeof config === 'string') {
4778 return new IndexedDbStorageAdapter({ dir: config, name: config });
4779 }
4780 var adapter = config.adapter, rest = __rest(config, ["adapter"]);
4781 if (adapter != null) {
4782 return adapter;
4783 }
4784 return new IndexedDbStorageAdapter(__assign({}, DEFAULTS$1, rest));
4785 }
4786 function validateName(name) {
4787 if (!name)
4788 throw new TypeError('Argument `name` is required.');
4789 }
4790 function validateData(data) {
4791 if (!data)
4792 throw new TypeError('Argument `data` is required.');
4793 }
4794
4795 /**
4796 * Error thrown when the value loaded from persistent storage cannot be
4797 * parsed as a {@link IKeyEntry} object.
4798 */
4799 var InvalidKeyEntryError = /** @class */ (function (_super) {
4800 __extends(InvalidKeyEntryError, _super);
4801 function InvalidKeyEntryError(message) {
4802 if (message === void 0) { message = 'Loaded key entry was in invalid format.'; }
4803 return _super.call(this, message, 'InvalidKeyEntryError') || this;
4804 }
4805 return InvalidKeyEntryError;
4806 }(VirgilError));
4807 /**
4808 * Error thrown from {@link KeyEntryStorage.save} method when saving a
4809 * a key entry with the name that already exists in store.
4810 */
4811 var KeyEntryAlreadyExistsError = /** @class */ (function (_super) {
4812 __extends(KeyEntryAlreadyExistsError, _super);
4813 function KeyEntryAlreadyExistsError(name) {
4814 return _super.call(this, "Key entry " + (name ? 'named ' + name : 'with same name') + "already exists", 'KeyEntryAlreadyExistsError') || this;
4815 }
4816 return KeyEntryAlreadyExistsError;
4817 }(VirgilError));
4818 /**
4819 * Error thrown from {@link KeyEntryStorage.update} method when updating
4820 * a key entry that doesn't exist in store.
4821 */
4822 var KeyEntryDoesNotExistError = /** @class */ (function (_super) {
4823 __extends(KeyEntryDoesNotExistError, _super);
4824 function KeyEntryDoesNotExistError(name) {
4825 return _super.call(this, "Key entry " + (name ? 'named ' + name : 'with the given name') + " does not exist.", 'KeyEntryDoesNotExistError') || this;
4826 }
4827 return KeyEntryDoesNotExistError;
4828 }(VirgilError));
4829
4830 var DEFAULTS$2 = {
4831 dir: '.virgil_key_entries',
4832 name: 'VirgilKeyEntries'
4833 };
4834 var VALUE_KEY = 'value';
4835 var CREATION_DATE_KEY = 'creationDate';
4836 var MODIFICATION_DATE_KEY = 'modificationDate';
4837 /**
4838 * Class responsible for persisting private key bytes with optional
4839 * user-defined metadata.
4840 */
4841 var KeyEntryStorage = /** @class */ (function () {
4842 /**
4843 * Initializes a new instance of `KeyEntryStorage`.
4844 *
4845 * @param {IKeyEntryStorageConfig} config - Instance configuration.
4846 */
4847 function KeyEntryStorage(config) {
4848 if (config === void 0) { config = {}; }
4849 this.adapter = resolveAdapter$1(config);
4850 }
4851 /**
4852 * @inheritDoc
4853 */
4854 KeyEntryStorage.prototype.exists = function (name) {
4855 validateName$1(name);
4856 return this.adapter.exists(name);
4857 };
4858 /**
4859 * @inheritDoc
4860 */
4861 KeyEntryStorage.prototype.load = function (name) {
4862 validateName$1(name);
4863 return this.adapter.load(name).then(function (data) {
4864 if (data == null) {
4865 return null;
4866 }
4867 return deserializeKeyEntry(data);
4868 });
4869 };
4870 /**
4871 * @inheritDoc
4872 */
4873 KeyEntryStorage.prototype.remove = function (name) {
4874 validateName$1(name);
4875 return this.adapter.remove(name);
4876 };
4877 /**
4878 * @inheritDoc
4879 */
4880 KeyEntryStorage.prototype.save = function (_a) {
4881 var name = _a.name, value = _a.value, meta = _a.meta;
4882 validateNameProperty(name);
4883 validateValueProperty(value);
4884 var keyEntry = {
4885 name: name,
4886 value: value,
4887 meta: meta,
4888 creationDate: new Date(),
4889 modificationDate: new Date()
4890 };
4891 return this.adapter.store(name, serializeKeyEntry(keyEntry))
4892 .then(function () { return keyEntry; })
4893 .catch(function (error) {
4894 if (error && error.name === 'StorageEntryAlreadyExistsError') {
4895 throw new KeyEntryAlreadyExistsError(name);
4896 }
4897 throw error;
4898 });
4899 };
4900 /**
4901 * @inheritDoc
4902 */
4903 KeyEntryStorage.prototype.list = function () {
4904 return this.adapter.list()
4905 .then(function (entries) { return entries.map(function (entry) { return deserializeKeyEntry(entry); }); });
4906 };
4907 /**
4908 * @inheritDoc
4909 */
4910 KeyEntryStorage.prototype.update = function (_a) {
4911 var _this = this;
4912 var name = _a.name, value = _a.value, meta = _a.meta;
4913 validateNameProperty(name);
4914 if (!(value || meta)) {
4915 throw new TypeError('Invalid argument. Either `value` or `meta` property is required.');
4916 }
4917 return this.adapter.load(name)
4918 .then(function (data) {
4919 if (data === null) {
4920 throw new KeyEntryDoesNotExistError(name);
4921 }
4922 var entry = deserializeKeyEntry(data);
4923 var updatedEntry = Object.assign(entry, {
4924 value: value || entry.value,
4925 meta: meta || entry.meta,
4926 modificationDate: new Date()
4927 });
4928 return _this.adapter.update(name, serializeKeyEntry(updatedEntry))
4929 .then(function () { return updatedEntry; });
4930 });
4931 };
4932 /**
4933 * @inheritDoc
4934 */
4935 KeyEntryStorage.prototype.clear = function () {
4936 return this.adapter.clear();
4937 };
4938 return KeyEntryStorage;
4939 }());
4940 function serializeKeyEntry(keyEntry) {
4941 var value = keyEntry.value, rest = __rest(keyEntry, ["value"]);
4942 var serializableEntry = __assign({}, rest, { value: value.toString('base64') });
4943 return Buffer.from(JSON.stringify(serializableEntry), 'utf8');
4944 }
4945 function deserializeKeyEntry(data) {
4946 var dataStr = data.toString('utf8');
4947 try {
4948 return JSON.parse(dataStr, function (key, value) {
4949 if (key === VALUE_KEY) {
4950 return Buffer.from(value, 'base64');
4951 }
4952 if (key === CREATION_DATE_KEY || key === MODIFICATION_DATE_KEY) {
4953 return new Date(value);
4954 }
4955 return value;
4956 });
4957 }
4958 catch (error) {
4959 throw new InvalidKeyEntryError();
4960 }
4961 }
4962 function resolveAdapter$1(config) {
4963 if (typeof config === 'string') {
4964 return new IndexedDbStorageAdapter({ dir: config, name: config });
4965 }
4966 var adapter = config.adapter, rest = __rest(config, ["adapter"]);
4967 if (adapter != null) {
4968 return adapter;
4969 }
4970 return new IndexedDbStorageAdapter(__assign({}, DEFAULTS$2, rest));
4971 }
4972 var requiredArg = function (name) { return function (value) {
4973 if (!value)
4974 throw new TypeError("Argument '" + name + "' is required.");
4975 }; };
4976 var requiredProp = function (name) { return function (value) {
4977 if (!value)
4978 throw new TypeError("Invalid argument. Property " + name + " is required");
4979 }; };
4980 var validateName$1 = requiredArg('name');
4981 var validateNameProperty = requiredProp('name');
4982 var validateValueProperty = requiredProp('value');
4983
4984 /**
4985 * Class responsible for storage of private keys.
4986 */
4987 var PrivateKeyStorage = /** @class */ (function () {
4988 /**
4989 * Initializes a new instance of `PrivateKeyStorage`.
4990 * @param {IPrivateKeyExporter} privateKeyExporter - Object responsible for
4991 * exporting private key bytes from `IPrivateKey` objects and importing
4992 * private key bytes into `IPrivateKey` objects.
4993 * @param {IKeyEntryStorage} keyEntryStorage - Object responsible for
4994 * persistence of private keys data.
4995 */
4996 function PrivateKeyStorage(privateKeyExporter, keyEntryStorage) {
4997 if (keyEntryStorage === void 0) { keyEntryStorage = new KeyEntryStorage(); }
4998 this.privateKeyExporter = privateKeyExporter;
4999 this.keyEntryStorage = keyEntryStorage;
5000 }
5001 /**
5002 * Persists the given `privateKey` and `meta` under the given `name`.
5003 * If an entry with the same name already exists rejects the returned
5004 * Promise with {@link PrivateKeyExistsError} error.
5005 *
5006 * @param {string} name - Name of the private key.
5007 * @param {IPrivateKey} privateKey - The private key object.
5008 * @param {Object<string, string>} [meta] - Optional metadata to store with the key.
5009 *
5010 * @returns {Promise<void>}
5011 */
5012 PrivateKeyStorage.prototype.store = function (name, privateKey, meta) {
5013 return __awaiter(this, void 0, void 0, function () {
5014 var privateKeyData, error_1;
5015 return __generator(this, function (_a) {
5016 switch (_a.label) {
5017 case 0:
5018 privateKeyData = this.privateKeyExporter.exportPrivateKey(privateKey);
5019 _a.label = 1;
5020 case 1:
5021 _a.trys.push([1, 3, , 4]);
5022 return [4 /*yield*/, this.keyEntryStorage.save({ name: name, value: privateKeyData, meta: meta })];
5023 case 2:
5024 _a.sent();
5025 return [3 /*break*/, 4];
5026 case 3:
5027 error_1 = _a.sent();
5028 if (error_1 && error_1.name === 'KeyEntryAlreadyExistsError') {
5029 throw new PrivateKeyExistsError("Private key with the name " + name + " already exists.");
5030 }
5031 throw error_1;
5032 case 4: return [2 /*return*/];
5033 }
5034 });
5035 });
5036 };
5037 /**
5038 * Retrieves the private key with the given `name` from persistent storage.
5039 * If private with the given name does not exist, resolves the returned
5040 * Promise with `null`.
5041 *
5042 * @param {string} name - Name of the private key to load.
5043 * @returns {Promise<IPrivateKeyEntry|null>}
5044 */
5045 PrivateKeyStorage.prototype.load = function (name) {
5046 return __awaiter(this, void 0, void 0, function () {
5047 var keyEntry, privateKey;
5048 return __generator(this, function (_a) {
5049 switch (_a.label) {
5050 case 0: return [4 /*yield*/, this.keyEntryStorage.load(name)];
5051 case 1:
5052 keyEntry = _a.sent();
5053 if (keyEntry === null) {
5054 return [2 /*return*/, null];
5055 }
5056 privateKey = this.privateKeyExporter.importPrivateKey(keyEntry.value);
5057 return [2 /*return*/, {
5058 privateKey: privateKey,
5059 meta: keyEntry.meta
5060 }];
5061 }
5062 });
5063 });
5064 };
5065 /**
5066 * Removes the private key entry with the given `name` from persistent
5067 * storage.
5068 *
5069 * @param {string} name - Name of the private key to remove.
5070 * @returns {Promise<void>}
5071 */
5072 PrivateKeyStorage.prototype.delete = function (name) {
5073 return __awaiter(this, void 0, void 0, function () {
5074 return __generator(this, function (_a) {
5075 switch (_a.label) {
5076 case 0: return [4 /*yield*/, this.keyEntryStorage.remove(name)];
5077 case 1:
5078 _a.sent();
5079 return [2 /*return*/];
5080 }
5081 });
5082 });
5083 };
5084 return PrivateKeyStorage;
5085 }());
5086
5087 exports.JwtGenerator = JwtGenerator;
5088 exports.JwtVerifier = JwtVerifier;
5089 exports.Jwt = Jwt;
5090 exports.CachingJwtProvider = CachingJwtProvider;
5091 exports.CallbackJwtProvider = CallbackJwtProvider;
5092 exports.ConstAccessTokenProvider = ConstAccessTokenProvider;
5093 exports.GeneratorJwtProvider = GeneratorJwtProvider;
5094 exports.CardManager = CardManager;
5095 exports.VirgilCardVerifier = VirgilCardVerifier;
5096 exports.RawSignedModel = RawSignedModel;
5097 exports.ModelSigner = ModelSigner;
5098 exports.DefaultStorageAdapter = IndexedDbStorageAdapter;
5099 exports.StorageEntryAlreadyExistsError = StorageEntryAlreadyExistsError;
5100 exports.KeyStorage = KeyStorage;
5101 exports.KeyEntryStorage = KeyEntryStorage;
5102 exports.InvalidKeyEntryError = InvalidKeyEntryError;
5103 exports.KeyEntryAlreadyExistsError = KeyEntryAlreadyExistsError;
5104 exports.KeyEntryDoesNotExistError = KeyEntryDoesNotExistError;
5105 exports.PrivateKeyStorage = PrivateKeyStorage;
5106
5107 Object.defineProperty(exports, '__esModule', { value: true });
5108
5109})));