favalib 0.0.10 → 0.0.12

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 (43) hide show
  1. package/build/Command/commandConstructors.d.mts +2 -2
  2. package/build/Command/commandConstructors.mjs +2 -2
  3. package/build/Command/commands/ChangeDeviceInfoCommand.d.mts +6 -6
  4. package/build/Command/commands/ChangeDeviceInfoCommand.mjs +3 -3
  5. package/build/TwoFaLib.d.mts +3 -3
  6. package/build/TwoFaLib.mjs +16 -12
  7. package/build/interfaces/CommandTypes.d.mts +4 -4
  8. package/build/interfaces/OpenPgpLib.d.mts +20 -0
  9. package/build/interfaces/OpenPgpLib.mjs +1 -0
  10. package/build/interfaces/PlatformProviders.d.mts +26 -0
  11. package/build/interfaces/PlatformProviders.mjs +1 -0
  12. package/build/interfaces/QrCodeLib.d.mts +19 -0
  13. package/build/interfaces/QrCodeLib.mjs +1 -0
  14. package/build/main.d.mts +2 -1
  15. package/build/platformProviders/browser/index.d.mts +6 -0
  16. package/build/platformProviders/browser/index.mjs +13 -0
  17. package/build/platformProviders/browser/openPgpLib.d.mts +20 -0
  18. package/build/platformProviders/browser/openPgpLib.mjs +44 -0
  19. package/build/platformProviders/browser/qrCodeLib.d.mts +25 -0
  20. package/build/platformProviders/browser/qrCodeLib.mjs +69 -0
  21. package/build/{CryptoProviders/node/index.mjs → platformProviders/node/cryptoLib.mjs} +1 -1
  22. package/build/platformProviders/node/index.d.mts +6 -0
  23. package/build/platformProviders/node/index.mjs +13 -0
  24. package/build/platformProviders/node/openPgpLib.d.mts +20 -0
  25. package/build/platformProviders/node/openPgpLib.mjs +44 -0
  26. package/build/platformProviders/node/qrCodeLib.d.mts +28 -0
  27. package/build/platformProviders/node/qrCodeLib.mjs +54 -0
  28. package/build/subclasses/ExportImportManager.mjs +3 -3
  29. package/build/subclasses/LibraryLoader.d.mts +26 -12
  30. package/build/subclasses/LibraryLoader.mjs +26 -34
  31. package/build/subclasses/SyncManager.mjs +7 -6
  32. package/build/utils/creationUtils.d.mts +3 -3
  33. package/build/utils/creationUtils.mjs +7 -5
  34. package/build/utils/exportImportUtils.d.mts +5 -3
  35. package/build/utils/exportImportUtils.mjs +2 -12
  36. package/build/utils/qrUtils.d.mts +0 -16
  37. package/build/utils/qrUtils.mjs +2 -68
  38. package/build/utils/syncUtils.d.mts +3 -2
  39. package/build/utils/syncUtils.mjs +3 -19
  40. package/package.json +8 -8
  41. /package/build/{CryptoProviders/browser/index.d.mts → platformProviders/browser/cryptoLib.d.mts} +0 -0
  42. /package/build/{CryptoProviders/browser/index.mjs → platformProviders/browser/cryptoLib.mjs} +0 -0
  43. /package/build/{CryptoProviders/node/index.d.mts → platformProviders/node/cryptoLib.d.mts} +0 -0
@@ -0,0 +1,54 @@
1
+ import { TwoFALibError } from '../../TwoFALibError.mjs';
2
+ import { isUint8Array } from 'uint8array-extras';
3
+ /**
4
+ * Gets the ImageData from an image, for Node.js environments.
5
+ * This ImageData is then further processed to get QR codes.
6
+ * @param inputImage - The image to get the ImageData from.
7
+ * @returns A promise that resolves to the ImageData.
8
+ */
9
+ export const getImageDataFromInput = async (inputImage) => {
10
+ if (inputImage instanceof File) {
11
+ throw new TwoFALibError('Getting data from QR where image type is "File" is not supported in the node environment');
12
+ }
13
+ const canvasLib = await import('canvas');
14
+ const { createCanvas, loadImage } = canvasLib;
15
+ // eslint-disable-next-line no-restricted-globals
16
+ const input = isUint8Array(inputImage) ? Buffer.from(inputImage) : inputImage;
17
+ const image = await loadImage(input); // canvaslib expects a buffer
18
+ const canvas = createCanvas(image.width, image.height);
19
+ const ctx = canvas.getContext('2d');
20
+ ctx.drawImage(image, 0, 0);
21
+ return ctx.getImageData(0, 0, image.width, image.height);
22
+ };
23
+ /**
24
+ * Node.js implementation of QR code library wrapper
25
+ */
26
+ export class NodeQrCodeLib {
27
+ constructor() {
28
+ this.qrCodeModule = null;
29
+ }
30
+ /**
31
+ * Gets the QR code module, loading it if necessary
32
+ * @returns Promise that resolves to the QR code module
33
+ */
34
+ async getQrCodeModule() {
35
+ if (!this.qrCodeModule) {
36
+ const qrcode = await import('qrcode');
37
+ this.qrCodeModule = qrcode.default;
38
+ }
39
+ return this.qrCodeModule;
40
+ }
41
+ /**
42
+ * @inheritdoc
43
+ */
44
+ async toDataURL(text) {
45
+ const qrCode = await this.getQrCodeModule();
46
+ return qrCode.toDataURL(text);
47
+ }
48
+ /**
49
+ * @inheritdoc
50
+ */
51
+ async getImageDataFromInput(imageInput) {
52
+ return getImageDataFromInput(imageInput);
53
+ }
54
+ }
@@ -51,7 +51,7 @@ class ExportImportManager {
51
51
  }
52
52
  if (passphrase) {
53
53
  await validatePassphraseStrength(this.libraryLoader, passphrase, this.passphraseExtraDict);
54
- return encryptExport(await this.libraryLoader.getOpenPGPLib(), exportData, passphrase);
54
+ return encryptExport(this.libraryLoader.getOpenPGPLib(), exportData, passphrase);
55
55
  }
56
56
  return exportData;
57
57
  }
@@ -59,7 +59,7 @@ class ExportImportManager {
59
59
  return generateTextExport(this.vaultDataManager.getAllEntries());
60
60
  }
61
61
  async generateHtmlExport() {
62
- const qrGeneratorLib = await this.libraryLoader.getQrGeneratorLib();
62
+ const qrGeneratorLib = this.libraryLoader.getQrGeneratorLib();
63
63
  return generateHtmlExport(qrGeneratorLib, this.vaultDataManager.getAllEntries());
64
64
  }
65
65
  /**
@@ -71,7 +71,7 @@ class ExportImportManager {
71
71
  */
72
72
  async importFromTextFile(fileContents, passphrase) {
73
73
  if (passphrase) {
74
- const decrypted = await decryptExport(await this.libraryLoader.getOpenPGPLib(), fileContents, passphrase);
74
+ const decrypted = await decryptExport(this.libraryLoader.getOpenPGPLib(), fileContents, passphrase);
75
75
  return this.importFromTextFile(decrypted);
76
76
  }
77
77
  const lines = fileContents.trim().split('\n');
@@ -1,52 +1,66 @@
1
1
  import type CryptoLib from '../interfaces/CryptoLib.mjs';
2
+ import type { PlatformProviders } from '../interfaces/PlatformProviders.mjs';
3
+ import type { QrCodeLib } from '../interfaces/QrCodeLib.mjs';
4
+ import type { OpenPgpLib } from '../interfaces/OpenPgpLib.mjs';
2
5
  /**
3
6
  * Class responsible for loading various external (big) libraries required by the application.
4
7
  * All libraries (except CryptoLib) are loaded on demand. This helps to reduce the initial bundle size.
5
8
  */
6
9
  declare class LibraryLoader {
10
+ private platformProviders;
7
11
  private cryptoLib;
8
12
  private openPgpLib?;
9
13
  private qrGeneratorLib?;
10
14
  private jsQrLib?;
11
- private canvasLib?;
12
15
  private urlParserLib?;
13
16
  private zxcvbn?;
17
+ private webSocketLib?;
14
18
  /**
15
19
  * Constructs a new instance of LibraryLoader.
16
- * @param cryptoLib - An instance of CryptoLib that is required for library operations.
17
- * @throws {InitializationError} If the provided CryptoLib instance is invalid.
20
+ * @param platformProviders - Platform-specific providers containing CryptoLib and other providers.
21
+ * @throws {InitializationError} If the provided platform providers are invalid.
18
22
  */
19
- constructor(cryptoLib: CryptoLib);
23
+ constructor(platformProviders: PlatformProviders);
20
24
  /**
21
25
  * @returns The CryptoLib instance.
22
26
  */
23
27
  getCryptoLib(): CryptoLib;
28
+ /**
29
+ * @returns The PlatformProviders instance.
30
+ */
31
+ getPlatformProviders(): PlatformProviders;
24
32
  /**
25
33
  * Loads and returns the OpenPGP library on demand.
26
34
  * @returns A promise that resolves to the OpenPGP library.
27
35
  */
28
- getOpenPGPLib(): Promise<typeof import("openpgp")>;
36
+ getOpenPGPLib(): OpenPgpLib;
29
37
  /**
30
38
  * Loads and returns the QR Generator library on demand.
31
39
  * @returns A promise that resolves to the QR Generator library.
32
40
  */
33
- getQrGeneratorLib(): Promise<typeof import("qrcode")>;
41
+ getQrGeneratorLib(): QrCodeLib;
34
42
  /**
35
43
  * Loads and returns the JsQR library on demand.
36
44
  * @returns A promise that resolves to the JsQR library.
37
45
  */
38
46
  getJsQrLib(): Promise<typeof import("jsqr").default>;
39
- /**
40
- * Loads and returns the Canvas library on demand.
41
- * @returns A promise that resolves to the Canvas library.
42
- * @throws {TwoFALibError} If the library cannot be loaded in a browser environment.
43
- */
44
- getCanvasLib(): Promise<typeof import("canvas")>;
45
47
  /**
46
48
  * Loads and returns the URL Parser library on demand.
47
49
  * @returns A promise that resolves to the URL Parser library.
48
50
  */
49
51
  getUrlParserLib(): Promise<typeof import("whatwg-url")>;
52
+ /**
53
+ * Loads and returns the WebSocket library on demand.
54
+ * @returns The WebSocket library.
55
+ */
56
+ getWebSocketLib(): {
57
+ new (url: string | URL, protocols?: string | string[]): WebSocket;
58
+ prototype: WebSocket;
59
+ readonly CONNECTING: 0;
60
+ readonly OPEN: 1;
61
+ readonly CLOSING: 2;
62
+ readonly CLOSED: 3;
63
+ };
50
64
  /**
51
65
  * Loads and returns the Zxcvbn library on demand.
52
66
  * @returns A promise that resolves to the Zxcvbn library.
@@ -1,4 +1,4 @@
1
- import { InitializationError, TwoFALibError } from '../TwoFALibError.mjs';
1
+ import { InitializationError } from '../TwoFALibError.mjs';
2
2
  /**
3
3
  * Class responsible for loading various external (big) libraries required by the application.
4
4
  * All libraries (except CryptoLib) are loaded on demand. This helps to reduce the initial bundle size.
@@ -6,14 +6,15 @@ import { InitializationError, TwoFALibError } from '../TwoFALibError.mjs';
6
6
  class LibraryLoader {
7
7
  /**
8
8
  * Constructs a new instance of LibraryLoader.
9
- * @param cryptoLib - An instance of CryptoLib that is required for library operations.
10
- * @throws {InitializationError} If the provided CryptoLib instance is invalid.
9
+ * @param platformProviders - Platform-specific providers containing CryptoLib and other providers.
10
+ * @throws {InitializationError} If the provided platform providers are invalid.
11
11
  */
12
- constructor(cryptoLib) {
13
- if (!cryptoLib) {
14
- throw new InitializationError('CryptoLib is required');
12
+ constructor(platformProviders) {
13
+ if (!platformProviders?.CryptoLib) {
14
+ throw new InitializationError('PlatformProviders with CryptoLib is required');
15
15
  }
16
- this.cryptoLib = cryptoLib;
16
+ this.platformProviders = platformProviders;
17
+ this.cryptoLib = new platformProviders.CryptoLib();
17
18
  }
18
19
  /**
19
20
  * @returns The CryptoLib instance.
@@ -21,28 +22,26 @@ class LibraryLoader {
21
22
  getCryptoLib() {
22
23
  return this.cryptoLib;
23
24
  }
25
+ /**
26
+ * @returns The PlatformProviders instance.
27
+ */
28
+ getPlatformProviders() {
29
+ return this.platformProviders;
30
+ }
24
31
  /**
25
32
  * Loads and returns the OpenPGP library on demand.
26
33
  * @returns A promise that resolves to the OpenPGP library.
27
34
  */
28
- async getOpenPGPLib() {
29
- if (!this.openPgpLib) {
30
- const module = await import('openpgp');
31
- // enable Authenticated Encryption with Associated Data
32
- module.config.aeadProtect = true;
33
- this.openPgpLib = module;
34
- }
35
+ getOpenPGPLib() {
36
+ this.openPgpLib ??= new this.platformProviders.OpenPgpLib();
35
37
  return this.openPgpLib;
36
38
  }
37
39
  /**
38
40
  * Loads and returns the QR Generator library on demand.
39
41
  * @returns A promise that resolves to the QR Generator library.
40
42
  */
41
- async getQrGeneratorLib() {
42
- if (!this.qrGeneratorLib) {
43
- const module = await import('qrcode');
44
- this.qrGeneratorLib = module.default;
45
- }
43
+ getQrGeneratorLib() {
44
+ this.qrGeneratorLib ??= new this.platformProviders.QrCodeLib();
46
45
  return this.qrGeneratorLib;
47
46
  }
48
47
  /**
@@ -56,21 +55,6 @@ class LibraryLoader {
56
55
  }
57
56
  return this.jsQrLib;
58
57
  }
59
- /**
60
- * Loads and returns the Canvas library on demand.
61
- * @returns A promise that resolves to the Canvas library.
62
- * @throws {TwoFALibError} If the library cannot be loaded in a browser environment.
63
- */
64
- async getCanvasLib() {
65
- if (typeof window !== 'undefined') {
66
- throw new TwoFALibError('Canvas lib can not be loaded in browser env');
67
- }
68
- if (!this.canvasLib) {
69
- const module = await import('canvas');
70
- this.canvasLib = module.default;
71
- }
72
- return this.canvasLib;
73
- }
74
58
  /**
75
59
  * Loads and returns the URL Parser library on demand.
76
60
  * @returns A promise that resolves to the URL Parser library.
@@ -82,6 +66,14 @@ class LibraryLoader {
82
66
  }
83
67
  return this.urlParserLib;
84
68
  }
69
+ /**
70
+ * Loads and returns the WebSocket library on demand.
71
+ * @returns The WebSocket library.
72
+ */
73
+ getWebSocketLib() {
74
+ this.webSocketLib ??= this.platformProviders.WebSocketLib();
75
+ return this.webSocketLib;
76
+ }
85
77
  /**
86
78
  * Loads and returns the Zxcvbn library on demand.
87
79
  * @returns A promise that resolves to the Zxcvbn library.
@@ -141,12 +141,13 @@ class SyncManager {
141
141
  * Initializes the WebSocket connection to the server.
142
142
  */
143
143
  initServerConnection() {
144
- const ws = new WebSocket(this.serverUrl);
144
+ const WebSocketLib = this.libraryLoader.getWebSocketLib();
145
+ const ws = new WebSocketLib(this.serverUrl);
145
146
  // eslint-disable-next-line @typescript-eslint/no-this-alias
146
147
  const syncManager = this;
147
- ws.addEventListener('error', (event) => {
148
- // eslint-disable-next-line @typescript-eslint/no-base-to-string
149
- syncManager.log('warning', `Error in websocket: ${event.toString()}`);
148
+ ws.addEventListener('error', () => {
149
+ // no error information seems to be available...
150
+ syncManager.log('warning', `Error in websocket.`);
150
151
  });
151
152
  ws.addEventListener('message', function message(message) {
152
153
  try {
@@ -326,7 +327,7 @@ class SyncManager {
326
327
  };
327
328
  let returnQr = null;
328
329
  if (returnAs.qr) {
329
- const qrGeneratorLib = await this.libraryLoader.getQrGeneratorLib();
330
+ const qrGeneratorLib = this.libraryLoader.getQrGeneratorLib();
330
331
  returnQr = await qrGeneratorLib.toDataURL(JSON.stringify(returnData));
331
332
  }
332
333
  const returnText = returnAs.text
@@ -352,7 +353,7 @@ class SyncManager {
352
353
  if (this.activeAddDeviceFlow) {
353
354
  throw new SyncAddDeviceFlowConflictError();
354
355
  }
355
- const { addDevicePassword, initiatorDeviceId, timestamp, pass1Result } = await decodeInitiatorData(initiatorData, initiatorDataType, await this.libraryLoader.getJsQrLib(), this.libraryLoader.getCanvasLib.bind(this));
356
+ const { addDevicePassword, initiatorDeviceId, timestamp, pass1Result } = await decodeInitiatorData(initiatorData, initiatorDataType, await this.libraryLoader.getJsQrLib(), this.libraryLoader.getQrGeneratorLib());
356
357
  if (!addDevicePassword ||
357
358
  !initiatorDeviceId ||
358
359
  !timestamp ||
@@ -1,5 +1,5 @@
1
1
  import type { ZxcvbnResult } from '@zxcvbn-ts/core';
2
- import type CryptoLib from '../interfaces/CryptoLib.mjs';
2
+ import type { PlatformProviders } from '../interfaces/PlatformProviders.mjs';
3
3
  import type { Passphrase } from '../interfaces/CryptoLib.mjs';
4
4
  import type { DeviceType } from '../interfaces/SyncTypes.mjs';
5
5
  import TwoFaLib from '../TwoFaLib.mjs';
@@ -25,14 +25,14 @@ export declare const getPassphraseStrength: (libraryLoader: LibraryLoader, passp
25
25
  export declare const validatePassphraseStrength: (libraryLoader: LibraryLoader, passphrase: Passphrase, passphraseExtraDict: PassphraseExtraDict) => Promise<void>;
26
26
  /**
27
27
  * Returns utility functions useful in creating a new twoFaLib vault
28
- * @param cryptoLib - An instance of CryptoLib that is compatible with the environment.
28
+ * @param platformProviders - The platform-specific providers containing CryptoLib and other providers.
29
29
  * @param deviceType - A unique identifier for this device type (e.g. 2fa-cli).
30
30
  * @param passphraseExtraDict - Additional words to be used for passphrase strength evaluation.
31
31
  * @param saveFunction - The function to save the data.
32
32
  * @param serverUrl - The server URL for syncing.
33
33
  * @returns An object with methods to evaluate passphrase strength and create a new TwoFaLib vault.
34
34
  */
35
- export declare const getTwoFaLibVaultCreationUtils: (cryptoLib: CryptoLib, deviceType: DeviceType, passphraseExtraDict: PassphraseExtraDict, saveFunction?: SaveFunction, serverUrl?: string) => {
35
+ export declare const getTwoFaLibVaultCreationUtils: (platformProviders: PlatformProviders, deviceType: DeviceType, passphraseExtraDict: PassphraseExtraDict, saveFunction?: SaveFunction, serverUrl?: string) => {
36
36
  getPassphraseStrength: (passphrase: Passphrase, passphraseExtraDict: PassphraseExtraDict) => Promise<ZxcvbnResult>;
37
37
  createNewTwoFaLibVault: (passphrase: Passphrase) => Promise<{
38
38
  twoFaLib: TwoFaLib;
@@ -62,10 +62,11 @@ export const validatePassphraseStrength = async (libraryLoader, passphrase, pass
62
62
  */
63
63
  const createNewTwoFaLibVault = async (libraryLoader, deviceType, serverUrl, passphraseExtraDict, saveFunction, passphrase) => {
64
64
  const cryptoLib = libraryLoader.getCryptoLib();
65
+ const platformProviders = libraryLoader.getPlatformProviders();
65
66
  const { publicKey, privateKey, symmetricKey, encryptedPrivateKey, encryptedSymmetricKey, salt, } = await cryptoLib.createKeys(passphrase);
66
67
  await validatePassphraseStrength(libraryLoader, passphrase, passphraseExtraDict);
67
68
  const deviceId = genUuidV4();
68
- const twoFaLib = new TwoFaLib(deviceType, cryptoLib, passphraseExtraDict, privateKey, symmetricKey, encryptedPrivateKey, encryptedSymmetricKey, salt, publicKey, {
69
+ const twoFaLib = new TwoFaLib(deviceType, platformProviders, passphraseExtraDict, privateKey, symmetricKey, encryptedPrivateKey, encryptedSymmetricKey, salt, publicKey, {
69
70
  deviceId,
70
71
  }, [], saveFunction, {
71
72
  serverUrl,
@@ -93,6 +94,7 @@ const createNewTwoFaLibVault = async (libraryLoader, deviceType, serverUrl, pass
93
94
  */
94
95
  const loadTwoFaLibFromLockedRepesentation = async (libraryLoader, deviceType, passphraseExtraDict, saveFunction, lockedRepresentationString, passphrase) => {
95
96
  const cryptoLib = libraryLoader.getCryptoLib();
97
+ const platformProviders = libraryLoader.getPlatformProviders();
96
98
  const lockedRepresentation = JSON.parse(lockedRepresentationString);
97
99
  if (!lockedRepresentation ||
98
100
  !lockedRepresentation.encryptedPrivateKey ||
@@ -109,22 +111,22 @@ const loadTwoFaLibFromLockedRepesentation = async (libraryLoader, deviceType, pa
109
111
  !vaultState.sync?.devices) {
110
112
  throw new InitializationError('encryptedVaultState is incomplete or corrupted');
111
113
  }
112
- return new TwoFaLib(deviceType, cryptoLib, passphraseExtraDict, privateKey, symmetricKey, lockedRepresentation.encryptedPrivateKey, lockedRepresentation.encryptedSymmetricKey, lockedRepresentation.salt, publicKey, {
114
+ return new TwoFaLib(deviceType, platformProviders, passphraseExtraDict, privateKey, symmetricKey, lockedRepresentation.encryptedPrivateKey, lockedRepresentation.encryptedSymmetricKey, lockedRepresentation.salt, publicKey, {
113
115
  deviceId: vaultState.deviceId,
114
116
  deviceFriendlyName: vaultState.deviceFriendlyName,
115
117
  }, vaultState.vault, saveFunction, vaultState.sync);
116
118
  };
117
119
  /**
118
120
  * Returns utility functions useful in creating a new twoFaLib vault
119
- * @param cryptoLib - An instance of CryptoLib that is compatible with the environment.
121
+ * @param platformProviders - The platform-specific providers containing CryptoLib and other providers.
120
122
  * @param deviceType - A unique identifier for this device type (e.g. 2fa-cli).
121
123
  * @param passphraseExtraDict - Additional words to be used for passphrase strength evaluation.
122
124
  * @param saveFunction - The function to save the data.
123
125
  * @param serverUrl - The server URL for syncing.
124
126
  * @returns An object with methods to evaluate passphrase strength and create a new TwoFaLib vault.
125
127
  */
126
- export const getTwoFaLibVaultCreationUtils = (cryptoLib, deviceType, passphraseExtraDict, saveFunction, serverUrl) => {
127
- const libraryLoader = new LibraryLoader(cryptoLib);
128
+ export const getTwoFaLibVaultCreationUtils = (platformProviders, deviceType, passphraseExtraDict, saveFunction, serverUrl) => {
129
+ const libraryLoader = new LibraryLoader(platformProviders);
128
130
  return {
129
131
  getPassphraseStrength: getPassphraseStrength.bind(null, libraryLoader),
130
132
  createNewTwoFaLibVault: createNewTwoFaLibVault.bind(null, libraryLoader, deviceType, serverUrl, passphraseExtraDict, saveFunction),
@@ -1,6 +1,8 @@
1
1
  import type { NewEntry } from '../interfaces/Entry.mjs';
2
2
  import type Entry from '../interfaces/Entry.mjs';
3
3
  import type { EntryId } from '../interfaces/Entry.mjs';
4
+ import type { QrCodeLib } from '../interfaces/QrCodeLib.mjs';
5
+ import type { OpenPgpLib } from '../interfaces/OpenPgpLib.mjs';
4
6
  /**
5
7
  * Parses an OTP URI and extracts the relevant information to create a new entry.
6
8
  * @param UrlParser - The URL parsing library.
@@ -15,7 +17,7 @@ export declare const parseOtpUri: (UrlParser: typeof import("whatwg-url"), otpUr
15
17
  * @param entries - An array of OTP entries.
16
18
  * @returns A promise that resolves to the HTML string.
17
19
  */
18
- export declare const generateHtmlExport: (qrGeneratorLib: typeof import("qrcode"), entries: Entry[]) => Promise<string>;
20
+ export declare const generateHtmlExport: (qrGeneratorLib: QrCodeLib, entries: Entry[]) => Promise<string>;
19
21
  /**
20
22
  * Generates a text export of OTP URIs for the provided entries.
21
23
  * @param entries - An array of OTP entries.
@@ -42,7 +44,7 @@ export declare const processImportLines: (lines: string[], importFromUri: (uri:
42
44
  * @param password - The password to use for encryption.
43
45
  * @returns A promise that resolves to the encrypted data.
44
46
  */
45
- export declare const encryptExport: (openPgpLib: typeof import("openpgp"), data: string, password: string) => Promise<string>;
47
+ export declare const encryptExport: (openPgpLib: OpenPgpLib, data: string, password: string) => Promise<string>;
46
48
  /**
47
49
  * Decrypts the given data using OpenPGP.
48
50
  * @param openPgpLib - The OpenPGP library.
@@ -50,4 +52,4 @@ export declare const encryptExport: (openPgpLib: typeof import("openpgp"), data:
50
52
  * @param password - The password to use for decryption.
51
53
  * @returns A promise that resolves to the decrypted data.
52
54
  */
53
- export declare const decryptExport: (openPgpLib: typeof import("openpgp"), data: string, password: string) => Promise<string>;
55
+ export declare const decryptExport: (openPgpLib: OpenPgpLib, data: string, password: string) => Promise<string>;
@@ -162,13 +162,7 @@ export const processImportLines = async (lines, importFromUri) => {
162
162
  * @returns A promise that resolves to the encrypted data.
163
163
  */
164
164
  export const encryptExport = async (openPgpLib, data, password) => {
165
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
166
- const encrypted = await openPgpLib.encrypt({
167
- message: await openPgpLib.createMessage({ text: data }),
168
- passwords: [password],
169
- format: 'armored',
170
- });
171
- return encrypted;
165
+ return openPgpLib.encrypt(data, password);
172
166
  };
173
167
  /**
174
168
  * Decrypts the given data using OpenPGP.
@@ -178,9 +172,5 @@ export const encryptExport = async (openPgpLib, data, password) => {
178
172
  * @returns A promise that resolves to the decrypted data.
179
173
  */
180
174
  export const decryptExport = async (openPgpLib, data, password) => {
181
- const decrypted = await openPgpLib.decrypt({
182
- message: await openPgpLib.readMessage({ armoredMessage: data }),
183
- passwords: [password],
184
- });
185
- return decrypted.data;
175
+ return openPgpLib.decrypt(data, password);
186
176
  };
@@ -1,20 +1,4 @@
1
- import type { ImageData } from 'canvas';
2
1
  import LibraryLoader from '../subclasses/LibraryLoader.mjs';
3
- /**
4
- * Gets the ImageData from an image, for browser environments.
5
- * This ImageData is then further processed to get QR codes.
6
- * @param input - The image to get the ImageData from.
7
- * @returns A promise that resolves to the ImageData.
8
- */
9
- export declare const getImageDataBrowser: (input: string | File) => Promise<ImageData>;
10
- /**
11
- * Gets the ImageData from an image, for Node.js environments.
12
- * This ImageData is then further processed to get QR codes.
13
- * @param canvasLib - The Canvas library.
14
- * @param inputImage - The image to get the ImageData from.
15
- * @returns A promise that resolves to the ImageData.
16
- */
17
- export declare const getImageDataNode: (canvasLib: typeof import("canvas"), inputImage: Uint8Array | string) => Promise<ImageData>;
18
2
  /**
19
3
  * Import an entry from a QR code image.
20
4
  * @param libraryLoader - An instance of LibraryLoader.
@@ -1,59 +1,4 @@
1
- import { isUint8Array } from 'uint8array-extras';
2
1
  import { TwoFALibError } from '../TwoFALibError.mjs';
3
- /**
4
- * Gets the ImageData from an image, for browser environments.
5
- * This ImageData is then further processed to get QR codes.
6
- * @param input - The image to get the ImageData from.
7
- * @returns A promise that resolves to the ImageData.
8
- */
9
- export const getImageDataBrowser = (input) => {
10
- return new Promise((resolve, reject) => {
11
- const img = new Image();
12
- img.onload = () => {
13
- const canvas = document.createElement('canvas');
14
- canvas.width = img.width;
15
- canvas.height = img.height;
16
- const ctx = canvas.getContext('2d');
17
- if (!ctx) {
18
- reject(new TwoFALibError('Could not create canvas context'));
19
- return;
20
- }
21
- ctx.drawImage(img, 0, 0);
22
- resolve(ctx.getImageData(0, 0, img.width, img.height));
23
- };
24
- img.onerror = () => reject(new TwoFALibError('Failed to load image'));
25
- if (typeof input === 'string') {
26
- // URL or Data URL
27
- img.src = input;
28
- }
29
- else {
30
- // File object
31
- const reader = new FileReader();
32
- reader.onload = (e) => {
33
- img.src = e.target?.result;
34
- };
35
- reader.onerror = () => reject(new TwoFALibError('Failed to read file'));
36
- reader.readAsDataURL(input);
37
- }
38
- });
39
- };
40
- /**
41
- * Gets the ImageData from an image, for Node.js environments.
42
- * This ImageData is then further processed to get QR codes.
43
- * @param canvasLib - The Canvas library.
44
- * @param inputImage - The image to get the ImageData from.
45
- * @returns A promise that resolves to the ImageData.
46
- */
47
- export const getImageDataNode = async (canvasLib, inputImage) => {
48
- const { createCanvas, loadImage } = canvasLib;
49
- // eslint-disable-next-line no-restricted-globals
50
- const input = isUint8Array(inputImage) ? Buffer.from(inputImage) : inputImage;
51
- const image = await loadImage(input); // canvaslib expects a buffer
52
- const canvas = createCanvas(image.width, image.height);
53
- const ctx = canvas.getContext('2d');
54
- ctx.drawImage(image, 0, 0);
55
- return ctx.getImageData(0, 0, image.width, image.height);
56
- };
57
2
  /**
58
3
  * Import an entry from a QR code image.
59
4
  * @param libraryLoader - An instance of LibraryLoader.
@@ -63,19 +8,8 @@ export const getImageDataNode = async (canvasLib, inputImage) => {
63
8
  */
64
9
  export const getDataFromQRImage = async (libraryLoader, imageInput) => {
65
10
  const jsQr = await libraryLoader.getJsQrLib();
66
- let imageData;
67
- if (typeof window !== 'undefined') {
68
- // Browser environment
69
- imageData = await getImageDataBrowser(imageInput);
70
- }
71
- else {
72
- if (imageInput instanceof File) {
73
- throw new TwoFALibError('Getting data from QR where image type is "File" is not supported in the node environment');
74
- }
75
- // Node.js environment
76
- const canvasLib = await libraryLoader.getCanvasLib();
77
- imageData = await getImageDataNode(canvasLib, imageInput);
78
- }
11
+ const qrLib = libraryLoader.getQrGeneratorLib();
12
+ const imageData = await qrLib.getImageDataFromInput(imageInput);
79
13
  const qrCodeResult = jsQr(imageData.data, imageData.width, imageData.height);
80
14
  if (!qrCodeResult) {
81
15
  throw new TwoFALibError("Couldn't read QR code data from image");
@@ -1,13 +1,14 @@
1
1
  import { InitiateAddDeviceFlowResult } from '../interfaces/SyncTypes.mjs';
2
+ import type { QrCodeLib } from '../interfaces/QrCodeLib.mjs';
2
3
  /**
3
4
  * Decodes the initiator data from a string or QR code.
4
5
  * @param initiatorData - The initiator data to decode.
5
6
  * @param initiatorDataType The type of the initiatorData, determines how it should be decoded
6
7
  * @param jsQr - The QR code decoder.
7
- * @param getCanvasLib - A function to get the Canvas library.
8
+ * @param qrCodeLib - The extended QR code library with platform-specific image processing.
8
9
  * @returns A promise that resolves to the decoded initiator data.
9
10
  */
10
- export declare const decodeInitiatorData: (initiatorData: string | Uint8Array | File, initiatorDataType: "text" | "qr", jsQr: typeof import("jsqr").default, getCanvasLib: () => Promise<typeof import("canvas")>) => Promise<InitiateAddDeviceFlowResult>;
11
+ export declare const decodeInitiatorData: (initiatorData: string | Uint8Array | File, initiatorDataType: "text" | "qr", jsQr: typeof import("jsqr").default, qrCodeLib: QrCodeLib) => Promise<InitiateAddDeviceFlowResult>;
11
12
  /**
12
13
  * Converts a JSONified Uint8Array to a Uint8Array.
13
14
  * A JSONified Uint8Array is the output of JSON.stringify on a Uint8Array.
@@ -1,33 +1,17 @@
1
1
  import { base64ToString } from 'uint8array-extras';
2
- import { getImageDataBrowser, getImageDataNode } from './qrUtils.mjs';
3
2
  import { SyncError } from '../TwoFALibError.mjs';
4
3
  /**
5
4
  * Decodes the initiator data from a string or QR code.
6
5
  * @param initiatorData - The initiator data to decode.
7
6
  * @param initiatorDataType The type of the initiatorData, determines how it should be decoded
8
7
  * @param jsQr - The QR code decoder.
9
- * @param getCanvasLib - A function to get the Canvas library.
8
+ * @param qrCodeLib - The extended QR code library with platform-specific image processing.
10
9
  * @returns A promise that resolves to the decoded initiator data.
11
10
  */
12
- export const decodeInitiatorData = async (initiatorData, initiatorDataType, jsQr, getCanvasLib) => {
11
+ export const decodeInitiatorData = async (initiatorData, initiatorDataType, jsQr, qrCodeLib) => {
13
12
  if (initiatorDataType === 'qr') {
14
13
  try {
15
- let imageData;
16
- if (typeof window !== 'undefined') {
17
- if (initiatorData instanceof Uint8Array) {
18
- throw new SyncError('Invalid initiator data type, should be a string or File in browser environment');
19
- }
20
- // Browser environment
21
- imageData = await getImageDataBrowser(initiatorData);
22
- }
23
- else {
24
- if (!(initiatorData instanceof Uint8Array)) {
25
- throw new SyncError('Invalid initiator data type, should be a Uint8Array in Node.js environment');
26
- }
27
- // Node.js environment
28
- const canvasLib = await getCanvasLib();
29
- imageData = await getImageDataNode(canvasLib, initiatorData);
30
- }
14
+ const imageData = await qrCodeLib.getImageDataFromInput(initiatorData);
31
15
  const qrCodeResult = jsQr(imageData.data, imageData.width, imageData.height);
32
16
  if (!qrCodeResult) {
33
17
  throw new SyncError('Invalid QR code');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "favalib",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "exports": {
@@ -8,13 +8,13 @@
8
8
  "import": "./build/main.mjs",
9
9
  "types": "./build/main.d.mts"
10
10
  },
11
- "./cryptoProviders/browser": {
12
- "import": "./build/CryptoProviders/browser/index.mjs",
13
- "types": "./build/CryptoProviders/browser/index.d.mts"
11
+ "./platformProviders/browser": {
12
+ "import": "./build/platformProviders/browser/index.mjs",
13
+ "types": "./build/platformProviders/browser/index.d.mts"
14
14
  },
15
- "./cryptoProviders/node": {
16
- "import": "./build/CryptoProviders/node/index.mjs",
17
- "types": "./build/CryptoProviders/node/index.d.mts"
15
+ "./platformProviders/node": {
16
+ "import": "./build/platformProviders/node/index.mjs",
17
+ "types": "./build/platformProviders/node/index.d.mts"
18
18
  }
19
19
  },
20
20
  "types": "./build/main.d.mts",
@@ -39,6 +39,7 @@
39
39
  "@zxcvbn-ts/language-common": "^3.0.4",
40
40
  "@zxcvbn-ts/language-en": "^3.0.2",
41
41
  "canvas": "^3.1.0",
42
+ "esbuild": "^0.25.8",
42
43
  "hash-wasm": "^4.12.0",
43
44
  "jpake-ts": "^1.0.1",
44
45
  "jsqr": "^1.4.0",
@@ -48,7 +49,6 @@
48
49
  "totp-generator": "^1.0.0",
49
50
  "typescript-event-target": "^1.1.1",
50
51
  "uint8array-extras": "^1.4.0",
51
- "unws": "^0.3.2",
52
52
  "uuid": "^11.1.0",
53
53
  "whatwg-url": "^14.2.0",
54
54
  "ws": "^8.18.2"