lib0 0.2.81 → 0.2.82

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/buffer.d.ts +2 -0
  2. package/buffer.d.ts.map +1 -1
  3. package/buffer.js +11 -0
  4. package/buffer.test.d.ts +1 -0
  5. package/buffer.test.d.ts.map +1 -1
  6. package/coverage/tmp/coverage-24019-1692125647663-0.json +1 -0
  7. package/crypto/ecdsa.d.ts.map +1 -1
  8. package/crypto/ecdsa.js +18 -19
  9. package/crypto/jwt.d.ts +6 -0
  10. package/crypto/jwt.d.ts.map +1 -0
  11. package/crypto/jwt.js +52 -0
  12. package/crypto.test.d.ts +1 -0
  13. package/crypto.test.d.ts.map +1 -1
  14. package/deno.json +1 -0
  15. package/dist/aes-gcm.cjs +1 -1
  16. package/dist/{broadcastchannel-7801969a.cjs → broadcastchannel-036aba21.cjs} +2 -2
  17. package/dist/{broadcastchannel-7801969a.cjs.map → broadcastchannel-036aba21.cjs.map} +1 -1
  18. package/dist/broadcastchannel.cjs +2 -2
  19. package/dist/{buffer-c5d69c70.cjs → buffer-bc255c75.cjs} +16 -1
  20. package/dist/{buffer-c5d69c70.cjs.map → buffer-bc255c75.cjs.map} +1 -1
  21. package/dist/buffer.cjs +3 -1
  22. package/dist/buffer.cjs.map +1 -1
  23. package/dist/buffer.d.ts +2 -0
  24. package/dist/buffer.d.ts.map +1 -1
  25. package/dist/buffer.test.d.ts +1 -0
  26. package/dist/buffer.test.d.ts.map +1 -1
  27. package/dist/crypto/ecdsa.d.ts.map +1 -1
  28. package/dist/crypto/jwt.d.ts +6 -0
  29. package/dist/crypto/jwt.d.ts.map +1 -0
  30. package/dist/crypto.test.d.ts +1 -0
  31. package/dist/crypto.test.d.ts.map +1 -1
  32. package/dist/decoding.cjs +1 -1
  33. package/dist/ecdsa.cjs +20 -21
  34. package/dist/ecdsa.cjs.map +1 -1
  35. package/dist/encoding.cjs +1 -1
  36. package/dist/index.cjs +3 -3
  37. package/dist/jwt.cjs +73 -0
  38. package/dist/jwt.cjs.map +1 -0
  39. package/dist/{prng-1149c8c4.cjs → prng-d6655349.cjs} +2 -2
  40. package/dist/{prng-1149c8c4.cjs.map → prng-d6655349.cjs.map} +1 -1
  41. package/dist/prng.cjs +2 -2
  42. package/dist/rabin-gf2-polynomial.cjs +1 -1
  43. package/dist/rabin-uncached.cjs +1 -1
  44. package/dist/rabin.cjs +1 -1
  45. package/dist/testing.cjs +2 -2
  46. package/package.json +7 -1
  47. package/coverage/tmp/coverage-1990-1692039209642-0.json +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ecdsa.d.ts","sourceRoot":"","sources":["ecdsa.js"],"names":[],"mappings":"AAyBO,0BAJI,SAAS,QACT,UAAU,GACT,YAAY,UAAU,CAAC,CAWlC;AAYM,4BALI,SAAS,aACT,UAAU,QACV,UAAU,GACT,YAAY,OAAO,CAAC,CAY/B;AAQM;IAHmB,WAAW;IACZ,MAAM;2BAU5B;AAQI,kCALI,GAAG;IAEY,WAAW;IACZ,MAAM;uBAQ9B;AAUM,kCALI,GAAG;IAEY,WAAW;IACZ,MAAM;uBAGsE;qBAzFxF,MAAM,MAAM,GAAC,QAAQ,CAAC"}
1
+ {"version":3,"file":"ecdsa.d.ts","sourceRoot":"","sources":["ecdsa.js"],"names":[],"mappings":"AA8BO,0BAJI,SAAS,QACT,UAAU,GACT,YAAY,UAAU,CAAC,CAOa;AAYzC,4BALI,SAAS,aACT,UAAU,QACV,UAAU,GACT,YAAY,OAAO,CAAC,CAQ7B;AAaI;IAHmB,WAAW;IACZ,MAAM;2BAO5B;AAQI,kCALI,GAAG;IAEY,WAAW;IACZ,MAAM;uBAQ9B;AAUM,kCALI,GAAG;IAEY,WAAW;IACZ,MAAM;uBAGmD;qBAxFrE,MAAM,MAAM,GAAC,QAAQ,CAAC"}
package/crypto/ecdsa.js CHANGED
@@ -14,6 +14,11 @@ export { exportKeyJwk, exportKeyRaw } from './common.js'
14
14
  */
15
15
  const defaultUsages = ['sign', 'verify']
16
16
 
17
+ const defaultSignAlgorithm = {
18
+ name: 'ECDSA',
19
+ hash: 'SHA-384'
20
+ }
21
+
17
22
  /**
18
23
  * @experimental The API is not final!
19
24
  *
@@ -23,16 +28,12 @@ const defaultUsages = ['sign', 'verify']
23
28
  * @param {Uint8Array} data
24
29
  * @return {PromiseLike<Uint8Array>} signature
25
30
  */
26
- export const sign = (key, data) => {
27
- return webcrypto.subtle.sign(
28
- {
29
- name: 'ECDSA',
30
- hash: { name: 'SHA-384' }
31
- },
31
+ export const sign = (key, data) =>
32
+ webcrypto.subtle.sign(
33
+ defaultSignAlgorithm,
32
34
  key,
33
35
  data
34
36
  ).then(signature => new Uint8Array(signature))
35
- }
36
37
 
37
38
  /**
38
39
  * @experimental The API is not final!
@@ -44,16 +45,17 @@ export const sign = (key, data) => {
44
45
  * @param {Uint8Array} data
45
46
  * @return {PromiseLike<boolean>} signature
46
47
  */
47
- export const verify = (key, signature, data) => {
48
- return webcrypto.subtle.verify(
49
- {
50
- name: 'ECDSA',
51
- hash: { name: 'SHA-384' }
52
- },
48
+ export const verify = (key, signature, data) =>
49
+ webcrypto.subtle.verify(
50
+ defaultSignAlgorithm,
53
51
  key,
54
52
  signature,
55
53
  data
56
54
  )
55
+
56
+ const defaultKeyAlgorithm = {
57
+ name: 'ECDSA',
58
+ namedCurve: 'P-384'
57
59
  }
58
60
 
59
61
  /* c8 ignore next */
@@ -64,10 +66,7 @@ export const verify = (key, signature, data) => {
64
66
  */
65
67
  export const generateKeyPair = ({ extractable = false, usages = defaultUsages } = {}) =>
66
68
  webcrypto.subtle.generateKey(
67
- {
68
- name: 'ECDSA',
69
- namedCurve: 'P-384'
70
- },
69
+ defaultKeyAlgorithm,
71
70
  extractable,
72
71
  usages
73
72
  )
@@ -83,7 +82,7 @@ export const importKeyJwk = (jwk, { extractable = false, usages } = {}) => {
83
82
  /* c8 ignore next 2 */
84
83
  usages = jwk.key_ops || defaultUsages
85
84
  }
86
- return webcrypto.subtle.importKey('jwk', jwk, { name: 'ECDSA', namedCurve: 'P-384' }, extractable, /** @type {Usages} */ (usages))
85
+ return webcrypto.subtle.importKey('jwk', jwk, defaultKeyAlgorithm, extractable, /** @type {Usages} */ (usages))
87
86
  }
88
87
 
89
88
  /**
@@ -95,4 +94,4 @@ export const importKeyJwk = (jwk, { extractable = false, usages } = {}) => {
95
94
  * @param {Usages} [opts.usages]
96
95
  */
97
96
  export const importKeyRaw = (raw, { extractable = false, usages = defaultUsages } = {}) =>
98
- webcrypto.subtle.importKey('raw', raw, { name: 'ECDSA', namedCurve: 'P-384' }, extractable, usages)
97
+ webcrypto.subtle.importKey('raw', raw, defaultKeyAlgorithm, extractable, usages)
@@ -0,0 +1,6 @@
1
+ export function encodeJwt(privateKey: CryptoKey, payload: Object): PromiseLike<string>;
2
+ export function verifyJwt(publicKey: CryptoKey, jwt: string): Promise<{
3
+ header: any;
4
+ payload: any;
5
+ }>;
6
+ //# sourceMappingURL=jwt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["jwt.js"],"names":[],"mappings":"AAoBO,sCAHI,SAAS,WACT,MAAM,uBAgBhB;AAMM,qCAHI,SAAS,OACT,MAAM;;;GAahB"}
package/crypto/jwt.js ADDED
@@ -0,0 +1,52 @@
1
+ import * as error from '../error.js'
2
+ import * as buffer from '../buffer.js'
3
+ import * as string from '../string.js'
4
+ import * as json from '../json.js'
5
+ import * as ecdsa from '../crypto/ecdsa.js'
6
+
7
+ /**
8
+ * @param {Object} data
9
+ */
10
+ const _stringify = data => buffer.toBase64UrlEncoded(string.encodeUtf8(json.stringify(data)))
11
+
12
+ /**
13
+ * @param {string} base64url
14
+ */
15
+ const _parse = base64url => json.parse(string.decodeUtf8(buffer.fromBase64UrlEncoded(base64url)))
16
+
17
+ /**
18
+ * @param {CryptoKey} privateKey
19
+ * @param {Object} payload
20
+ */
21
+ export const encodeJwt = (privateKey, payload) => {
22
+ const { name: algName, namedCurve: algCurve } = /** @type {any} */ (privateKey.algorithm)
23
+ /* c8 ignore next 3 */
24
+ if (algName !== 'ECDSA' || algCurve !== 'P-384') {
25
+ error.unexpectedCase()
26
+ }
27
+ const header = {
28
+ alg: 'ES384',
29
+ typ: 'JWT'
30
+ }
31
+ const jwt = _stringify(header) + '.' + _stringify(payload)
32
+ return ecdsa.sign(privateKey, string.encodeUtf8(jwt)).then(signature =>
33
+ jwt + '.' + buffer.toBase64UrlEncoded(signature)
34
+ )
35
+ }
36
+
37
+ /**
38
+ * @param {CryptoKey} publicKey
39
+ * @param {string} jwt
40
+ */
41
+ export const verifyJwt = async (publicKey, jwt) => {
42
+ const [headerBase64, payloadBase64, signatureBase64] = jwt.split('.')
43
+ const verified = await ecdsa.verify(publicKey, buffer.fromBase64UrlEncoded(signatureBase64), string.encodeUtf8(headerBase64 + '.' + payloadBase64))
44
+ /* c8 ignore next 3 */
45
+ if (!verified) {
46
+ throw new Error('Invalid JWT')
47
+ }
48
+ return {
49
+ header: _parse(headerBase64),
50
+ payload: _parse(payloadBase64)
51
+ }
52
+ }
package/crypto.test.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export function testJwt(_tc: t.TestCase): Promise<void>;
1
2
  export function testEncryption(tc: t.TestCase): Promise<void>;
2
3
  export function testReapeatEncryption(tc: t.TestCase): Promise<void>;
3
4
  export function testImportExport(tc: t.TestCase): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"crypto.test.d.ts","sourceRoot":"","sources":["crypto.test.js"],"names":[],"mappings":"AAUO,mCAFI,EAAE,QAAQ,iBAoCpB;AAKM,0CAFI,EAAE,QAAQ,iBA8BpB;AAKM,qCAFI,EAAE,QAAQ,iBAgDpB;AAKM,8CAFI,EAAE,QAAQ,iBAwCpB;AAKM,iDAFI,EAAE,QAAQ,iBA0EpB;AAKM,gCAFI,EAAE,QAAQ,iBAapB;mBArQkB,cAAc"}
1
+ {"version":3,"file":"crypto.test.d.ts","sourceRoot":"","sources":["crypto.test.js"],"names":[],"mappings":"AAYO,6BAFI,EAAE,QAAQ,iBAgBpB;AAKM,mCAFI,EAAE,QAAQ,iBAoCpB;AAKM,0CAFI,EAAE,QAAQ,iBA8BpB;AAKM,qCAFI,EAAE,QAAQ,iBAgDpB;AAKM,8CAFI,EAAE,QAAQ,iBAwCpB;AAKM,iDAFI,EAAE,QAAQ,iBA0EpB;AAKM,gCAFI,EAAE,QAAQ,iBAapB;mBAzRkB,cAAc"}
package/deno.json CHANGED
@@ -5,6 +5,7 @@
5
5
  "lib0/crypto/aes-gcm": "./crypto/aes-gcm.js",
6
6
  "lib0/crypto/rsa-oaep": "./crypto/rsa-oaep.js",
7
7
  "lib0/crypto/ecdsa": "./crypto/ecdsa.js",
8
+ "lib0/crypto/jwt": "./crypto/jwt.js",
8
9
  "lib0/webcrypto": "./webcrypto.deno.js"
9
10
  }
10
11
  }
package/dist/aes-gcm.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var encoding = require('./buffer-c5d69c70.cjs');
5
+ var encoding = require('./buffer-bc255c75.cjs');
6
6
  var webcrypto = require('lib0/webcrypto');
7
7
  var string = require('./string-6d104757.cjs');
8
8
  var common = require('./common.cjs');
@@ -2,7 +2,7 @@
2
2
 
3
3
  var map = require('./map-9a5915e4.cjs');
4
4
  var set = require('./set-0f209abb.cjs');
5
- var encoding = require('./buffer-c5d69c70.cjs');
5
+ var encoding = require('./buffer-bc255c75.cjs');
6
6
  var storage = require('./storage.cjs');
7
7
 
8
8
  /* eslint-env browser */
@@ -125,4 +125,4 @@ exports.broadcastchannel = broadcastchannel;
125
125
  exports.publish = publish;
126
126
  exports.subscribe = subscribe;
127
127
  exports.unsubscribe = unsubscribe;
128
- //# sourceMappingURL=broadcastchannel-7801969a.cjs.map
128
+ //# sourceMappingURL=broadcastchannel-036aba21.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"broadcastchannel-7801969a.cjs","sources":["../broadcastchannel.js"],"sourcesContent":["/* eslint-env browser */\n\n/**\n * Helpers for cross-tab communication using broadcastchannel with LocalStorage fallback.\n *\n * ```js\n * // In browser window A:\n * broadcastchannel.subscribe('my events', data => console.log(data))\n * broadcastchannel.publish('my events', 'Hello world!') // => A: 'Hello world!' fires synchronously in same tab\n *\n * // In browser window B:\n * broadcastchannel.publish('my events', 'hello from tab B') // => A: 'hello from tab B'\n * ```\n *\n * @module broadcastchannel\n */\n\n// @todo before next major: use Uint8Array instead as buffer object\n\nimport * as map from './map.js'\nimport * as set from './set.js'\nimport * as buffer from './buffer.js'\nimport * as storage from './storage.js'\n\n/**\n * @typedef {Object} Channel\n * @property {Set<function(any, any):any>} Channel.subs\n * @property {any} Channel.bc\n */\n\n/**\n * @type {Map<string, Channel>}\n */\nconst channels = new Map()\n\n/* c8 ignore start */\nclass LocalStoragePolyfill {\n /**\n * @param {string} room\n */\n constructor (room) {\n this.room = room\n /**\n * @type {null|function({data:ArrayBuffer}):void}\n */\n this.onmessage = null\n /**\n * @param {any} e\n */\n this._onChange = e => e.key === room && this.onmessage !== null && this.onmessage({ data: buffer.fromBase64(e.newValue || '') })\n storage.onChange(this._onChange)\n }\n\n /**\n * @param {ArrayBuffer} buf\n */\n postMessage (buf) {\n storage.varStorage.setItem(this.room, buffer.toBase64(buffer.createUint8ArrayFromArrayBuffer(buf)))\n }\n\n close () {\n storage.offChange(this._onChange)\n }\n}\n/* c8 ignore stop */\n\n// Use BroadcastChannel or Polyfill\n/* c8 ignore next */\nconst BC = typeof BroadcastChannel === 'undefined' ? LocalStoragePolyfill : BroadcastChannel\n\n/**\n * @param {string} room\n * @return {Channel}\n */\nconst getChannel = room =>\n map.setIfUndefined(channels, room, () => {\n const subs = set.create()\n const bc = new BC(room)\n /**\n * @param {{data:ArrayBuffer}} e\n */\n /* c8 ignore next */\n bc.onmessage = e => subs.forEach(sub => sub(e.data, 'broadcastchannel'))\n return {\n bc, subs\n }\n })\n\n/**\n * Subscribe to global `publish` events.\n *\n * @function\n * @param {string} room\n * @param {function(any, any):any} f\n */\nexport const subscribe = (room, f) => {\n getChannel(room).subs.add(f)\n return f\n}\n\n/**\n * Unsubscribe from `publish` global events.\n *\n * @function\n * @param {string} room\n * @param {function(any, any):any} f\n */\nexport const unsubscribe = (room, f) => {\n const channel = getChannel(room)\n const unsubscribed = channel.subs.delete(f)\n if (unsubscribed && channel.subs.size === 0) {\n channel.bc.close()\n channels.delete(room)\n }\n return unsubscribed\n}\n\n/**\n * Publish data to all subscribers (including subscribers on this tab)\n *\n * @function\n * @param {string} room\n * @param {any} data\n * @param {any} [origin]\n */\nexport const publish = (room, data, origin = null) => {\n const c = getChannel(room)\n c.bc.postMessage(data)\n c.subs.forEach(sub => sub(data, origin))\n}\n"],"names":["buffer.fromBase64","storage.onChange","storage.varStorage","buffer.toBase64","buffer.createUint8ArrayFromArrayBuffer","storage.offChange","map.setIfUndefined","set.create"],"mappings":"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"}
1
+ {"version":3,"file":"broadcastchannel-036aba21.cjs","sources":["../broadcastchannel.js"],"sourcesContent":["/* eslint-env browser */\n\n/**\n * Helpers for cross-tab communication using broadcastchannel with LocalStorage fallback.\n *\n * ```js\n * // In browser window A:\n * broadcastchannel.subscribe('my events', data => console.log(data))\n * broadcastchannel.publish('my events', 'Hello world!') // => A: 'Hello world!' fires synchronously in same tab\n *\n * // In browser window B:\n * broadcastchannel.publish('my events', 'hello from tab B') // => A: 'hello from tab B'\n * ```\n *\n * @module broadcastchannel\n */\n\n// @todo before next major: use Uint8Array instead as buffer object\n\nimport * as map from './map.js'\nimport * as set from './set.js'\nimport * as buffer from './buffer.js'\nimport * as storage from './storage.js'\n\n/**\n * @typedef {Object} Channel\n * @property {Set<function(any, any):any>} Channel.subs\n * @property {any} Channel.bc\n */\n\n/**\n * @type {Map<string, Channel>}\n */\nconst channels = new Map()\n\n/* c8 ignore start */\nclass LocalStoragePolyfill {\n /**\n * @param {string} room\n */\n constructor (room) {\n this.room = room\n /**\n * @type {null|function({data:ArrayBuffer}):void}\n */\n this.onmessage = null\n /**\n * @param {any} e\n */\n this._onChange = e => e.key === room && this.onmessage !== null && this.onmessage({ data: buffer.fromBase64(e.newValue || '') })\n storage.onChange(this._onChange)\n }\n\n /**\n * @param {ArrayBuffer} buf\n */\n postMessage (buf) {\n storage.varStorage.setItem(this.room, buffer.toBase64(buffer.createUint8ArrayFromArrayBuffer(buf)))\n }\n\n close () {\n storage.offChange(this._onChange)\n }\n}\n/* c8 ignore stop */\n\n// Use BroadcastChannel or Polyfill\n/* c8 ignore next */\nconst BC = typeof BroadcastChannel === 'undefined' ? LocalStoragePolyfill : BroadcastChannel\n\n/**\n * @param {string} room\n * @return {Channel}\n */\nconst getChannel = room =>\n map.setIfUndefined(channels, room, () => {\n const subs = set.create()\n const bc = new BC(room)\n /**\n * @param {{data:ArrayBuffer}} e\n */\n /* c8 ignore next */\n bc.onmessage = e => subs.forEach(sub => sub(e.data, 'broadcastchannel'))\n return {\n bc, subs\n }\n })\n\n/**\n * Subscribe to global `publish` events.\n *\n * @function\n * @param {string} room\n * @param {function(any, any):any} f\n */\nexport const subscribe = (room, f) => {\n getChannel(room).subs.add(f)\n return f\n}\n\n/**\n * Unsubscribe from `publish` global events.\n *\n * @function\n * @param {string} room\n * @param {function(any, any):any} f\n */\nexport const unsubscribe = (room, f) => {\n const channel = getChannel(room)\n const unsubscribed = channel.subs.delete(f)\n if (unsubscribed && channel.subs.size === 0) {\n channel.bc.close()\n channels.delete(room)\n }\n return unsubscribed\n}\n\n/**\n * Publish data to all subscribers (including subscribers on this tab)\n *\n * @function\n * @param {string} room\n * @param {any} data\n * @param {any} [origin]\n */\nexport const publish = (room, data, origin = null) => {\n const c = getChannel(room)\n c.bc.postMessage(data)\n c.subs.forEach(sub => sub(data, origin))\n}\n"],"names":["buffer.fromBase64","storage.onChange","storage.varStorage","buffer.toBase64","buffer.createUint8ArrayFromArrayBuffer","storage.offChange","map.setIfUndefined","set.create"],"mappings":"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"}
@@ -4,9 +4,9 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  require('./map-9a5915e4.cjs');
6
6
  require('./set-0f209abb.cjs');
7
- require('./buffer-c5d69c70.cjs');
7
+ require('./buffer-bc255c75.cjs');
8
8
  require('./storage.cjs');
9
- var broadcastchannel = require('./broadcastchannel-7801969a.cjs');
9
+ var broadcastchannel = require('./broadcastchannel-036aba21.cjs');
10
10
  require('./string-6d104757.cjs');
11
11
  require('./array-704ca50e.cjs');
12
12
  require('./environment-ad129e4d.cjs');
@@ -1781,6 +1781,17 @@ const toBase64 = environment.isBrowser ? toBase64Browser : toBase64Node;
1781
1781
  /* c8 ignore next */
1782
1782
  const fromBase64 = environment.isBrowser ? fromBase64Browser : fromBase64Node;
1783
1783
 
1784
+ /**
1785
+ * Implements base64url - see https://datatracker.ietf.org/doc/html/rfc4648#section-5
1786
+ * @param {Uint8Array} buf
1787
+ */
1788
+ const toBase64UrlEncoded = buf => toBase64(buf).replaceAll('+', '-').replaceAll('/', '_').replaceAll('=', '');
1789
+
1790
+ /**
1791
+ * @param {string} base64
1792
+ */
1793
+ const fromBase64UrlEncoded = base64 => fromBase64(base64.replaceAll('-', '+').replaceAll('_', '/'));
1794
+
1784
1795
  /**
1785
1796
  * Base64 is always a more efficient choice. This exists for utility purposes only.
1786
1797
  *
@@ -1859,6 +1870,8 @@ var buffer = /*#__PURE__*/Object.freeze({
1859
1870
  createUint8ArrayFromArrayBuffer: createUint8ArrayFromArrayBuffer,
1860
1871
  toBase64: toBase64,
1861
1872
  fromBase64: fromBase64,
1873
+ toBase64UrlEncoded: toBase64UrlEncoded,
1874
+ fromBase64UrlEncoded: fromBase64UrlEncoded,
1862
1875
  toHexString: toHexString,
1863
1876
  fromHexString: fromHexString,
1864
1877
  copyUint8Array: copyUint8Array,
@@ -1901,6 +1914,7 @@ exports.encode = encode;
1901
1914
  exports.encodeAny = encodeAny;
1902
1915
  exports.encoding = encoding;
1903
1916
  exports.fromBase64 = fromBase64;
1917
+ exports.fromBase64UrlEncoded = fromBase64UrlEncoded;
1904
1918
  exports.fromHexString = fromHexString;
1905
1919
  exports.hasContent = hasContent$1;
1906
1920
  exports.hasContent$1 = hasContent;
@@ -1936,6 +1950,7 @@ exports.setUint8 = setUint8;
1936
1950
  exports.shiftNBitsLeft = shiftNBitsLeft;
1937
1951
  exports.skip8 = skip8;
1938
1952
  exports.toBase64 = toBase64;
1953
+ exports.toBase64UrlEncoded = toBase64UrlEncoded;
1939
1954
  exports.toHexString = toHexString;
1940
1955
  exports.toUint8Array = toUint8Array;
1941
1956
  exports.verifyLen = verifyLen;
@@ -1958,4 +1973,4 @@ exports.writeVarInt = writeVarInt;
1958
1973
  exports.writeVarString = writeVarString;
1959
1974
  exports.writeVarUint = writeVarUint;
1960
1975
  exports.writeVarUint8Array = writeVarUint8Array;
1961
- //# sourceMappingURL=buffer-c5d69c70.cjs.map
1976
+ //# sourceMappingURL=buffer-bc255c75.cjs.map