@1auth/crypto 0.0.0-alpha.57 → 0.0.0-alpha.58

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 (2) hide show
  1. package/index.js +227 -111
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { promisify } from 'node:util'
2
2
  import {
3
3
  randomBytes,
4
- createHash as checksum,
4
+ createHash,
5
5
  createCipheriv,
6
6
  createDecipheriv,
7
7
  createHmac,
@@ -18,39 +18,63 @@ const sign = promisify(signCallback)
18
18
  const verify = promisify(verifyCallback)
19
19
 
20
20
  const defaults = {
21
- // symmetricEncryptionKey: randomBytes(32).toString('base64') // 256 bits
22
- symmetricEncryptionKey: undefined,
23
- symmetricEncryptionMethod: 'chacha20-poly1305', // 2024-05: AES-256 GCM (aes-256-gcm) or ChaCha20-Poly1305 (chacha20-poly1305)
24
- symmetricEncryptionEncoding: 'base64', // https://nodejs.org/api/buffer.html#buffers-and-character-encodings
25
- symmetricSignatureAlgorithm: 'sha3-384',
26
- // symmetricSignatureSecret: randomBytes(32).toString('base64') // 256 bits
27
- symmetricSignatureSecret: undefined,
21
+ symmetricEncryptionKey: undefined, // symmetricRandomEncryptionKey()
22
+ symmetricEncryptionAlgorithm: 'chacha20-poly1305', // 2024-05: AES-256 GCM (aes-256-gcm) or ChaCha20-Poly1305 (chacha20-poly1305)
23
+ symmetricEncryptionEncoding: undefined, // https://nodejs.org/api/buffer.html#buffers-and-character-encodings
24
+ symmetricSignatureHashAlgorithm: undefined, // fallback to defaultHashAlgorithm
25
+ symmetricSignatureSecret: undefined, // symmetricRandomSignatureSecret()
26
+ symmetricSignatureEncoding: undefined, // fallback to defaultEncoding
28
27
  asymmetricKeyNamedCurve: 'P-384', // P-512
29
- asymmetricSignatureAlgorithm: 'sha3-384',
30
- digestAlgorithm: 'sha3-384',
31
- digestEncoding: 'hex',
32
- signatureEncoding: 'base64'
28
+ asymmetricSignatureHashAlgorithm: undefined, // fallback to defaultHashAlgorithm
29
+ asymmetricSignatureEncoding: undefined, // fallback to defaultEncoding
30
+ digestChecksumAlgorithm: undefined, // fallback to defaultHashAlgorithm
31
+ digestChecksumEncoding: undefined,
32
+ digestChecksumSalt: undefined, // randomChecksumSalt()
33
+ digestChecksumPepper: undefined, // randomChecksumPepper()
34
+ defaultEncoding: 'base64',
35
+ defaultHashAlgorithm: 'sha3-384'
33
36
  }
34
37
  const symmetricEncryptionEncodingLengths = {}
35
38
  const options = {}
36
39
  export default (opt = {}) => {
37
40
  Object.assign(options, defaults, opt)
38
- symmetricEncryptionEncodingLengths.iv = randomBytes(12).toString(
39
- options.symmetricEncryptionEncoding
40
- ).length
41
- symmetricEncryptionEncodingLengths.ivAndAuthTag =
42
- symmetricEncryptionEncodingLengths.iv +
43
- randomBytes(16).toString(options.symmetricEncryptionEncoding).length
41
+
42
+ // Check options, set defaults
44
43
  if (!options.symmetricEncryptionKey) {
45
44
  console.warn(
46
- "@1auth/crypto symmetricEncryptionKey is empty, use a stored secret made from randomBytes(32).toString('base64'). Encryption disabled."
45
+ '@1auth/crypto symmetricEncryptionKey is empty, use a stored secret made from randomBytes(32) Encryption disabled.'
47
46
  )
48
47
  }
48
+ options.symmetricEncryptionEncoding ??= options.defaultEncoding
49
+ options.symmetricSignatureHashAlgorithm ??= options.defaultHashAlgorithm
49
50
  if (!options.symmetricSignatureSecret) {
50
51
  console.warn(
51
- "@1auth/crypto symmetricSignatureSecret is empty, use a stored secret made from randomBytes(32).toString('base64'). Signature disabled."
52
+ '@1auth/crypto symmetricSignatureSecret is empty, use a stored secret made from randomBytes(32). Signature disabled.'
52
53
  )
53
54
  }
55
+ options.symmetricSignatureEncoding ??= options.defaultEncoding
56
+ options.asymmetricSignatureHashAlgorithm ??= options.defaultHashAlgorithm
57
+ options.asymmetricSignatureEncoding ??= options.defaultEncoding
58
+ if (!options.digestChecksumSalt) {
59
+ console.warn(
60
+ '@1auth/crypto digestChecksumSalt is empty, use a stored secret made from randomBytes(32). Checksum salting disabled.'
61
+ )
62
+ }
63
+ if (!options.digestChecksumPepper) {
64
+ console.warn(
65
+ '@1auth/crypto digestChecksumPepper is empty, use a stored secret made from randomBytes(12). Checksum peppering disabled.'
66
+ )
67
+ }
68
+ options.digestChecksumAlgorithm ??= options.defaultHashAlgorithm
69
+ options.digestChecksumEncoding ??= options.defaultEncoding
70
+
71
+ // Lengths
72
+ symmetricEncryptionEncodingLengths.iv = randomIV().toString(
73
+ options.symmetricEncryptionEncoding
74
+ ).length
75
+ symmetricEncryptionEncodingLengths.ivAndAuthTag =
76
+ symmetricEncryptionEncodingLengths.iv +
77
+ randomBytes(16).toString(options.symmetricEncryptionEncoding).length
54
78
  }
55
79
 
56
80
  export const getOptions = () => options
@@ -86,13 +110,13 @@ export const entropyToCharacterLength = (bits, characterPoolSize) => {
86
110
  }; */
87
111
 
88
112
  // *** Random generators *** //
89
- // Ref: https://github.com/sindresorhus/crypto-random-string/blob/main/core.js
90
- export const charactersAlphaNumeric = [
91
- ...'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
113
+ export const charactersAlpha = [
114
+ ...'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
92
115
  ]
93
- export const charactersDistinguishable = [...'CDEHKMPRTUWXY012458']
94
116
  export const charactersNumeric = [...'0123456789']
117
+ export const charactersAlphaNumeric = charactersAlpha.concat(charactersNumeric)
95
118
 
119
+ // Ref: https://github.com/sindresorhus/crypto-random-string/blob/main/core.js
96
120
  export const randomCharacters = (
97
121
  length,
98
122
  characters = charactersAlphaNumeric
@@ -145,58 +169,101 @@ export const randomId = {
145
169
  }
146
170
 
147
171
  // *** Digests *** //
148
- export const createChecksum = (value, { algorithm, encoding } = {}) => {
149
- algorithm ??= options.digestAlgorithm
150
- encoding ??= options.digestEncoding
151
- return checksum(algorithm).update(value).digest(encoding)
172
+ export const randomChecksumSalt = () => {
173
+ return randomBytes(32) // 256 bits
152
174
  }
153
- export const createDigest = (value, { algorithm } = {}) => {
154
- algorithm ??= options.digestAlgorithm
155
- const checksum = createChecksum(value, { algorithm })
156
- return `${algorithm}:${checksum}`
175
+ export const randomChecksumPepper = () => {
176
+ return randomIV() // 96
157
177
  }
158
178
 
159
- // TODO evaluate non-iv encryption approach?
160
- // Use encryption as pepper to allow easier rotation of pepper
161
- export const createEncryptedDigest = (value, { algorithm } = {}) => {
162
- algorithm ??= options.digestAlgorithm
163
- const digest = createDigest(value, { algorithm })
164
- // encrypting using the symmetricEncryptionKey instead of
165
- // the row encryptionKey to allow lookup, must have fixed iv
166
- return symmetricEncrypt(digest, {
167
- encryptionKey: options.symmetricEncryptionKey,
168
- sub: '',
169
- encoding: options.symmetricEncryptionEncoding,
170
- iv: Buffer.from(
171
- options.symmetricEncryptionKey.substring(
172
- 0,
173
- symmetricEncryptionEncodingLengths.iv
174
- ),
175
- options.symmetricEncryptionEncoding
176
- )
177
- })
179
+ export const createSaltedValue = (value, { checksumSalt } = {}) => {
180
+ checksumSalt ??= options.digestChecksumSalt
181
+ if (!checksumSalt) {
182
+ return value
183
+ }
184
+ const newValue = value + checksumSalt
185
+ return newValue
178
186
  }
179
-
180
- export const rotateDigestEncryption = (
181
- encryptedValue,
182
- encryptionKey,
183
- newEncryptionKey
187
+ export const createPepperedValue = (
188
+ value,
189
+ { checksumPepper, encryptionKey } = {}
184
190
  ) => {
185
- const digest = symmetricDecrypt(encryptedValue, {
191
+ checksumPepper ??= options.digestChecksumPepper
192
+ encryptionKey ??= options.symmetricEncryptionKey
193
+ if (!checksumPepper || !encryptionKey) {
194
+ return value
195
+ }
196
+ const newValue = symmetricEncrypt(value, {
186
197
  encryptionKey,
187
198
  sub: '',
188
- encoding: options.symmetricEncryptionEncoding
199
+ iv: checksumPepper
189
200
  })
201
+ return newValue
202
+ }
190
203
 
191
- return symmetricEncrypt(digest, {
192
- encryptionKey: newEncryptionKey,
193
- sub: '',
194
- encoding: options.symmetricEncryptionEncoding,
195
- iv: Buffer.from(
196
- newEncryptionKey.substring(0, symmetricEncryptionEncodingLengths.iv),
197
- options.symmetricEncryptionEncoding
198
- )
204
+ export const createChecksum = (value, { algorithm, encoding } = {}) => {
205
+ algorithm ??= options.digestChecksumAlgorithm
206
+ encoding ??= options.digestChecksumEncoding
207
+ return createHash(algorithm).update(value).digest(encoding)
208
+ }
209
+ export const createSeasonedChecksum = (
210
+ value,
211
+ { algorithm, encoding, checksumSalt, checksumPepper } = {}
212
+ ) => {
213
+ return createChecksum(
214
+ createPepperedValue(createSaltedValue(value, { checksumSalt }), {
215
+ checksumPepper
216
+ }),
217
+ {
218
+ algorithm,
219
+ encoding
220
+ }
221
+ )
222
+ }
223
+
224
+ export const createDigest = (value, { algorithm, encoding } = {}) => {
225
+ algorithm ??= options.digestChecksumAlgorithm
226
+ const checksum = createChecksum(value, { algorithm, encoding })
227
+ return `${algorithm}:${checksum}`
228
+ }
229
+ export const createSaltedDigest = (
230
+ value,
231
+ { algorithm, encoding, checksumSalt } = {}
232
+ ) => {
233
+ algorithm ??= options.digestChecksumAlgorithm
234
+ const checksum = createChecksum(createSaltedValue(value, { checksumSalt }), {
235
+ algorithm,
236
+ encoding
199
237
  })
238
+ return `${algorithm}:${checksum}`
239
+ }
240
+ export const createPepperedDigest = (
241
+ value,
242
+ { algorithm, encoding, checksumPepper, encryptionKey } = {}
243
+ ) => {
244
+ algorithm ??= options.digestChecksumAlgorithm
245
+ const checksum = createChecksum(
246
+ createPepperedValue(value, { checksumPepper, encryptionKey }),
247
+ {
248
+ algorithm,
249
+ encoding
250
+ }
251
+ )
252
+ return `${algorithm}:${checksum}`
253
+ }
254
+ export const createSeasonedDigest = (
255
+ value,
256
+ { algorithm, encoding, checksumSalt, checksumPepper, encryptionKey } = {}
257
+ ) => {
258
+ algorithm ??= options.digestChecksumAlgorithm
259
+ const checksum = createSeasonedChecksum(value, {
260
+ algorithm,
261
+ encoding,
262
+ checksumSalt,
263
+ checksumPepper,
264
+ encryptionKey
265
+ })
266
+ return `${algorithm}:${checksum}`
200
267
  }
201
268
 
202
269
  // *** Hashing *** //
@@ -222,31 +289,41 @@ export const verifySecretHash = async (hash, value) => {
222
289
  const authTagLength = 16
223
290
 
224
291
  export const symmetricRandomEncryptionKey = () => {
225
- return randomBytes(32).toString('base64') // 256 bits
292
+ return randomBytes(32) // 256 bits
226
293
  }
227
294
 
228
- export const symmetricGenerateEncryptionKey = (sub) => {
229
- if (!options.symmetricEncryptionKey) {
295
+ export const randomIV = () => {
296
+ return randomBytes(12) // 96 bits
297
+ }
298
+
299
+ export const symmetricGenerateEncryptionKey = (
300
+ sub,
301
+ { encryptionKey, signatureSecret } = {}
302
+ ) => {
303
+ encryptionKey ??= options.symmetricEncryptionKey
304
+ signatureSecret ??= options.symemeticSignatureSecret
305
+
306
+ if (!encryptionKey) {
230
307
  return { encryptionKey: '', encryptedKey: '' }
231
308
  }
232
- const encryptionKey = symmetricRandomEncryptionKey()
233
- const encryptedKey = symmetricEncrypt(encryptionKey, {
234
- encryptionKey: options.symmetricEncryptionKey,
235
- sub,
236
- decoding: 'base64',
237
- encoding: options.symmetricEncryptionEncoding
309
+ const rowEncryptionKey = symmetricRandomEncryptionKey()
310
+ const rowEncryptedKey = symmetricEncrypt(rowEncryptionKey, {
311
+ encryptionKey,
312
+ signatureSecret,
313
+ sub
238
314
  })
239
- return { encryptionKey, encryptedKey }
315
+ return { encryptionKey: rowEncryptionKey, encryptedKey: rowEncryptedKey }
240
316
  }
241
317
 
242
318
  // sub add context to encryption
243
319
  export const symmetricEncryptFields = (
244
320
  values,
245
- { encryptedKey, encryptionKey, sub },
321
+ { encryptedKey, encryptionKey, signatureSecret, sub },
246
322
  fields = []
247
323
  ) => {
248
324
  if (encryptedKey) {
249
325
  encryptionKey ??= symmetricDecryptKey(encryptedKey, {
326
+ signatureSecret,
250
327
  sub
251
328
  })
252
329
  }
@@ -255,6 +332,7 @@ export const symmetricEncryptFields = (
255
332
  for (const key of fields) {
256
333
  encryptedValues[key] &&= symmetricEncrypt(encryptedValues[key], {
257
334
  encryptionKey,
335
+ signatureSecret,
258
336
  sub
259
337
  })
260
338
  }
@@ -267,23 +345,23 @@ export const symmetricEncrypt = (
267
345
  ) => {
268
346
  if (encryptedKey) {
269
347
  encryptionKey ??= symmetricDecryptKey(encryptedKey, {
348
+ signatureSecret,
270
349
  sub
271
350
  })
272
351
  }
273
352
  if (!encryptionKey || !data) return data
274
353
  decoding ??= 'utf8'
275
354
  encoding ??= options.symmetricEncryptionEncoding
276
- iv ??= randomBytes(12) // 96 bits
277
-
355
+ iv ??= randomIV()
278
356
  const cipher = createCipheriv(
279
- options.symmetricEncryptionMethod,
280
- Buffer.from(encryptionKey, 'base64'),
357
+ options.symmetricEncryptionAlgorithm,
358
+ encryptionKey,
281
359
  iv,
282
360
  {
283
361
  authTagLength
284
362
  }
285
363
  )
286
- cipher.setAAD(Buffer.from(sub ?? '', 'utf8'))
364
+ cipher.setAAD(sub)
287
365
  const encryptedData =
288
366
  cipher.update(data, decoding, encoding) + cipher.final(encoding)
289
367
  const authTag = cipher.getAuthTag()
@@ -302,6 +380,7 @@ export const symmetricDecryptFields = (
302
380
  ) => {
303
381
  if (encryptedKey) {
304
382
  encryptionKey ??= symmetricDecryptKey(encryptedKey, {
383
+ signatureSecret,
305
384
  sub
306
385
  })
307
386
  }
@@ -310,19 +389,28 @@ export const symmetricDecryptFields = (
310
389
  for (const key of fields) {
311
390
  values[key] &&= symmetricDecrypt(values[key], {
312
391
  encryptionKey,
392
+ signatureSecret,
313
393
  sub
314
394
  })
315
395
  }
316
396
  return values
317
397
  }
318
398
 
319
- export const symmetricDecryptKey = (encryptedKey, { sub } = {}) => {
320
- return symmetricDecrypt(encryptedKey, {
321
- encryptionKey: options.symmetricEncryptionKey,
322
- sub,
323
- decoding: options.symmetricEncryptionEncoding,
324
- encoding: 'base64'
325
- })
399
+ export const symmetricDecryptKey = (
400
+ encryptedKey,
401
+ { sub, encryptionKey, signatureSecret } = {}
402
+ ) => {
403
+ encryptionKey ??= options.symmetricEncryptionKey
404
+ signatureSecret ??= options.symemeticSignatureSecret
405
+ return Buffer.from(
406
+ symmetricDecrypt(encryptedKey, {
407
+ encryptionKey,
408
+ signatureSecret,
409
+ sub,
410
+ encoding: options.symmetricEncryptionEncoding
411
+ }),
412
+ options.symmetricEncryptionEncoding
413
+ )
326
414
  }
327
415
 
328
416
  export const symmetricDecrypt = (
@@ -331,6 +419,7 @@ export const symmetricDecrypt = (
331
419
  ) => {
332
420
  if (encryptedKey) {
333
421
  encryptionKey ??= symmetricDecryptKey(encryptedKey, {
422
+ signatureSecret,
334
423
  sub
335
424
  })
336
425
  }
@@ -347,7 +436,6 @@ export const symmetricDecrypt = (
347
436
  if (encryptedDataPacket === false) {
348
437
  throw new Error('Signature incorrect')
349
438
  }
350
-
351
439
  const iv = Buffer.from(
352
440
  encryptedDataPacket.substring(0, symmetricEncryptionEncodingLengths.iv),
353
441
  decoding
@@ -367,14 +455,14 @@ export const symmetricDecrypt = (
367
455
  )
368
456
 
369
457
  const decipher = createDecipheriv(
370
- options.symmetricEncryptionMethod,
371
- Buffer.from(encryptionKey, 'base64'),
458
+ options.symmetricEncryptionAlgorithm,
459
+ encryptionKey,
372
460
  iv,
373
461
  {
374
462
  authTagLength
375
463
  }
376
464
  )
377
- decipher.setAAD(Buffer.from(sub ?? '', 'utf8'))
465
+ decipher.setAAD(Buffer.from(sub, 'utf8'))
378
466
 
379
467
  decipher.setAuthTag(authTag)
380
468
  const data =
@@ -385,10 +473,10 @@ export const symmetricDecrypt = (
385
473
 
386
474
  // *** Symmetric Signatures *** //
387
475
  export const symmetricRandomSignatureSecret = () => {
388
- return randomBytes(32).toString('base64') // 256 bits
476
+ return randomBytes(32) // 256 bits
389
477
  }
390
478
 
391
- export const symmetricGenerateSignatureSecret = (sub) => {
479
+ export const symmetricGenerateSignatureSecret = () => {
392
480
  if (!options.symmetricSignatureSecret) {
393
481
  return { signatureSecret: '' }
394
482
  }
@@ -401,12 +489,11 @@ export const symmetricSignatureSign = (
401
489
  signatureSecret,
402
490
  { algorithm } = {}
403
491
  ) => {
404
- // if (typeof data !== 'string') throw new TypeError('data must me a string')
405
492
  signatureSecret ??= options.symmetricSignatureSecret
406
- algorithm ??= options.symmetricSignatureAlgorithm
493
+ algorithm ??= options.symmetricSignatureHashAlgorithm
407
494
  const signature = createHmac(algorithm, signatureSecret)
408
495
  .update(data)
409
- .digest(options.signatureEncoding)
496
+ .digest(options.symmetricSignatureEncoding)
410
497
  .replace(/=+$/, '')
411
498
 
412
499
  const signedData = data + '.' + signature
@@ -423,19 +510,48 @@ export const symmetricSignatureVerify = (
423
510
  const signedDataExpected = symmetricSignatureSign(data, signatureSecret, {
424
511
  algorithm
425
512
  })
426
-
427
513
  return safeEqual(signedData, signedDataExpected) && data
428
514
  }
429
515
 
516
+ // Allow rotation of global encryption key, global signature secret, and row encryption key
430
517
  export const symmetricRotation = (
431
- encryptedValues,
432
- oldOptions, // { encryptedKey, encryptionKey, signatureSecret, sub }, // old
433
- newOptions, // { encryptedKey, encryptionKey, signatureSecret, sub, decoding, encoding, iv }, // new
434
- fields = []
518
+ oldEncryptedValues,
519
+ oldOptions, // { encryptionKey, signatureSecret, sub, decoding, encoding }, // old
520
+ oldFields = [],
521
+ newOptions, // { encryptionKey, signatureSecret, sub, decoding, encoding }, // new
522
+ newFields = [],
523
+ transform = (data) => {
524
+ return data
525
+ }
435
526
  ) => {
436
- const data = symmetricDecryptFields(encryptedValues, oldOptions, fields)
437
- const newEncryptedData = symmetricEncryptFields(data, newOptions, fields)
438
- return newEncryptedData
527
+ if (oldOptions.sub !== newOptions.sub) throw new Error('Mismatching `sub`')
528
+
529
+ // decrypt old encryption key
530
+ const { encryptionKey: oldEncryptedKey } = oldEncryptedValues
531
+ delete oldEncryptedValues.encryptionKey
532
+
533
+ oldOptions.encryptionKey = symmetricDecryptKey(oldEncryptedKey, oldOptions)
534
+
535
+ // decrypt
536
+ const data = transform(
537
+ symmetricDecryptFields(oldEncryptedValues, oldOptions, oldFields)
538
+ )
539
+
540
+ // rotate encryptionKey
541
+ const { encryptionKey: newEncryptionKey, encryptedKey: newEncryptedKey } =
542
+ symmetricGenerateEncryptionKey(oldOptions.sub, newOptions)
543
+
544
+ newOptions.encryptionKey = newEncryptionKey
545
+
546
+ // encrypt
547
+ const newEncryptedValues = symmetricEncryptFields(
548
+ data,
549
+ newOptions,
550
+ newFields
551
+ )
552
+ newEncryptedValues.encryptionKey = newEncryptedKey
553
+
554
+ return newEncryptedValues
439
555
  }
440
556
 
441
557
  // *** Asymmetric Signatures *** //
@@ -452,7 +568,7 @@ export const makeAsymmetricKeys = async () => {
452
568
  type: 'sec1',
453
569
  format: 'pem'
454
570
  // Encryption done at another level for consistency
455
- // cipher: options.asymmetricEncryptionMethod,
571
+ // cipher: options.asymmetricEncryptionAlgorithm,
456
572
  // passphrase: encryptionKey,
457
573
  }
458
574
  })
@@ -464,9 +580,9 @@ export const makeAsymmetricSignature = async (
464
580
  privateKey,
465
581
  { algorithm } = {}
466
582
  ) => {
467
- algorithm ??= options.asymmetricSignatureAlgorithm
583
+ algorithm ??= options.asymmetricSignatureHashAlgorithm
468
584
  return (await sign(algorithm, Buffer.from(data), privateKey)).toString(
469
- options.signatureEncoding
585
+ options.asymmetricSignatureEncoding
470
586
  )
471
587
  }
472
588
  export const verifyAsymmetricSignature = async (
@@ -475,12 +591,12 @@ export const verifyAsymmetricSignature = async (
475
591
  signature,
476
592
  { algorithm } = {}
477
593
  ) => {
478
- algorithm ??= options.asymmetricSignatureAlgorithm
594
+ algorithm ??= options.asymmetricSignatureHashAlgorithm
479
595
  return await verify(
480
596
  algorithm,
481
597
  Buffer.from(data),
482
598
  publicKey,
483
- Buffer.from(signature, options.signatureEncoding)
599
+ Buffer.from(signature, options.asymmetricSignatureEncoding)
484
600
  )
485
601
  }
486
602
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1auth/crypto",
3
- "version": "0.0.0-alpha.57",
3
+ "version": "0.0.0-alpha.58",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "engines": {