@ideem/zsm-client-sdk 2.6.1 → 2.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -11,7 +11,13 @@ and Universal MFA into a browser application.
11
11
  - None at this time.
12
12
 
13
13
  ----
14
- ## Release 2.6.1 - December 16, 2025 [ NPM PACKAGE RELEASE ] **[ LATEST ]**
14
+ ## Release 2.6.3 - January 6, 2026 [ NPM PACKAGE RELEASE ] **[ LATEST ]**
15
+ - Minor alteration to event coordinator to support legacy versions of Safari (versions 14-18.4)
16
+
17
+ ## Release 2.6.2 - December 19, 2025 [ NPM PACKAGE RELEASE ]
18
+ - Hotfix release to address an issue with the Passkeys+ plugin integration.
19
+
20
+ ## Release 2.6.1 - December 16, 2025 [ NPM PACKAGE RELEASE ]
15
21
  - Minor bug fixes and improvements
16
22
  - Minor alteration to initialization process to remove the need to provide a `userIdentifier` when initializing (all method calls now provide the update).
17
23
  - Improvements to EventCoordinator:
@@ -182,7 +182,7 @@ class EventCoordinator {
182
182
  byStatus(eventStatus) {
183
183
  if (!eventStatus || typeof eventStatus !== 'string' || !eventStatus.length || !["UNREGISTERED", "PENDING", "READY", "ERROR"].includes(eventStatus))
184
184
  throw new Error(`[ZSM EventCoordinator] :: byStatus :: Invalid 'eventStatus' value: "${eventStatus}". Valid statuses are: UNREGISTERED, PENDING, READY, ERROR.`);
185
- return [...this._eventStack.entries().flatMap(([k, v]) => (v === eventStatus) ? [k] : [])];
185
+ return this.entries.flatMap(([k, v]) => v === eventStatus ? [k] : []);
186
186
  }
187
187
 
188
188
  /**
@@ -202,7 +202,8 @@ class EventCoordinator {
202
202
  * @returns {Object} Returns the reset event stack object.
203
203
  */
204
204
  reset() {
205
- this._eventStack.keys().forEach(key=>this._eventStack.set(key,'PENDING'));
205
+ this.keys.forEach(key => this._eventStack.set(key, 'PENDING'));
206
+
206
207
  if(window && window?.queueMicrotask) {
207
208
  queueMicrotask(() => this.dispatchEvent('ZSMClientEventStackReset', { stack: this.object }));
208
209
  } else this.dispatchEvent('ZSMClientEventStackReset', { stack: this.object });
package/PluginManager.js CHANGED
@@ -1,14 +1,15 @@
1
1
  class PluginManager {
2
- #sdkClassMap = new Map(); // Map of SDK class names to their implementations
3
- #classCorpus = new Map(); // Map of plugin identities to their class maps
4
- #status = 'INITIALIZED'; // Indicates the current status of the plugin manager (INITIALIZED, SEEDED, FROZEN)
5
-
2
+ constructor() {
3
+ this._sdkClassMap = new Map(); // Map of SDK class names to their implementations
4
+ this._classCorpus = new Map(); // Map of plugin identities to their class maps
5
+ this._status = 'INITIALIZED'; // Indicates the current status of the plugin manager (INITIALIZED, SEEDED, FROZEN)
6
+ }
6
7
  /**
7
8
  * Returns whether the plugin manager is frozen.
8
9
  * @returns {boolean} True if the plugin manager is frozen, false otherwise.
9
10
  */
10
11
  get isFrozen() {
11
- return this.#status === 'FROZEN';
12
+ return this._status === 'FROZEN';
12
13
  }
13
14
 
14
15
  /**
@@ -20,15 +21,15 @@ class PluginManager {
20
21
  * @throws {Error} If no class is registered for the given name.
21
22
  */
22
23
  classes (classDesc) {
23
- if(this.#status === 'INITIALIZED') throw new Error('[zsmPluginManager] :: classes :: collection accessor cannot be referenced before SOME classes are registered!');
24
+ if(this._status === 'INITIALIZED') throw new Error('[zsmPluginManager] :: classes :: collection accessor cannot be referenced before SOME classes are registered!');
24
25
  if(!classDesc || typeof classDesc !== 'string') throw new Error(`[zsmPluginManager] :: classes :: collection accessor requires a valid class description (received ${typeof classDesc}: ${classDesc})!`);
25
26
  classDesc = classDesc.toUpperCase();
26
27
  if(!this.isFrozen){
27
28
  console.warn('[zsmPluginManager] :: Freezing the plugin manager as the first class has been preemptively requested. No further plugins can be registered after this point.\nIf you feel you received this message unexpectedly, please ensure all plugins are imported before initializing (`new UMFAClient()` or `new FIDO2Client()`) a client.');
28
29
  this.freezePlugins();
29
30
  }
30
- if(!this.#sdkClassMap.has(classDesc)) throw new Error(`[zsmPluginManager] :: classes :: No SDK class registered for: ${classDesc}`);
31
- return this.#sdkClassMap.get(classDesc);
31
+ if(!this._sdkClassMap.has(classDesc)) throw new Error(`[zsmPluginManager] :: classes :: No SDK class registered for: ${classDesc}`);
32
+ return this._sdkClassMap.get(classDesc);
32
33
  }
33
34
 
34
35
  /**
@@ -56,9 +57,9 @@ class PluginManager {
56
57
  if (this.isFrozen) throw new Error('[zsmPluginManager] :: registerPlugin :: Cannot register plugin: PlugInManager is frozen!\nThis typically occurs when a plugin is imported after a client - UMFAClient or FIDO2Client - has already been initialized.\nMake sure to import all plugins before initializing (`new UMFAClient()` or `new FIDO2Client()`) a client.');
57
58
  if (!pluginIdentity || typeof classObj !== 'object' || classObj == null) throw new Error('[zsmPluginManager] :: registerPlugin :: pluginIdentity and class map object required');
58
59
 
59
- this.#status = 'SEEDED';
60
+ this._status = 'SEEDED';
60
61
 
61
- this.#classCorpus.set(pluginIdentity.toUpperCase(), classObj);
62
+ this._classCorpus.set(pluginIdentity.toUpperCase(), classObj);
62
63
  console.info(`[zsmPluginManager] :: PluginManager :: Registered plugin "${pluginIdentity}".`);
63
64
  return true;
64
65
  }
@@ -74,19 +75,19 @@ class PluginManager {
74
75
  // As new plugins are DEVELOPED, they may introduce new classes or modify existing ones, and their extension/override logic must be declared below.
75
76
 
76
77
  // [CORE PACKAGE] Default all of the active classes to the "core" classes (set below this declaration)
77
- const core = this.#classCorpus.get('CORE');
78
+ const core = this._classCorpus.get('CORE');
78
79
  if (!core) throw new Error('[zsmPluginManager] :: freezePlugins :: Core not registered before freeze');
79
80
 
80
81
  const constructedMap = this.seedClassMap(core); // returns Map
81
82
 
82
83
  // [PASSKEYS+ PLUGIN PACKAGE] If the "PASSKEYS+" plugin is registered, supercede the core classes with the passkeys classes
83
- if(this.#classCorpus.has('PASSKEYS+')) {
84
- const passkeysMap = this.#classCorpus.get('PASSKEYS+');
84
+ if(this._classCorpus.has('PASSKEYS+')) {
85
+ const passkeysMap = this._classCorpus.get('PASSKEYS+');
85
86
  if (passkeysMap?.classDefs) for (const [k,v] of Object.entries(passkeysMap.classDefs)) constructedMap.set(k.toUpperCase(), v);
86
87
  }
87
88
 
88
89
  // Apply class decorators (wrappers) AFTER overlays, if present in any of the registrations
89
- const postConstructDecorators = [...this.#classCorpus.values()].filter(entry => entry.mode === 'DECORATOR');
90
+ const postConstructDecorators = [...this._classCorpus.values()].filter(entry => entry.mode === 'DECORATOR');
90
91
  if (postConstructDecorators.length) {
91
92
  for (const modifier of postConstructDecorators) {
92
93
  let { classDesc, postModFn } = modifier;
@@ -101,8 +102,8 @@ class PluginManager {
101
102
  }
102
103
  }
103
104
 
104
- this.#sdkClassMap = constructedMap;
105
- this.#status = 'FROZEN';
105
+ this._sdkClassMap = constructedMap;
106
+ this._status = 'FROZEN';
106
107
  }
107
108
  }
108
109
 
@@ -12,6 +12,11 @@ const tracePrimer = (obj=false) => {
12
12
  return (obj) ? {"trace": traceBase} : traceBase;
13
13
  }
14
14
 
15
+ const canParseURL = (url) => {
16
+ try { new URL(url); return true; } catch { return false; }
17
+ }
18
+
19
+
15
20
  class WebAuthnClientBase {
16
21
  /**
17
22
  * Constructs a WebAuthnClientBase object.
@@ -20,7 +25,7 @@ class WebAuthnClientBase {
20
25
  constructor(config) {
21
26
  // console.log('config :', Object.assign({}, config));
22
27
  // Helper function to standardize URL format (ensuring it's parsable and ends with a '/')
23
- const cleanURL = (url) => URL.canParse(url) ? new URL(url).origin + '/' : false;
28
+ const cleanURL = (url) => canParseURL(url) ? new URL(url).origin + '/' : false;
24
29
 
25
30
  if(config?.region){
26
31
  config.authenticator_host_url ||= config.authenticator_host = `https://zsm-authenticator-${config.region}.useideem.com/`;
package/package.json CHANGED
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name" : "@ideem/zsm-client-sdk",
3
- "version" : "2.6.1",
3
+ "version" : "2.6.3",
4
4
  "description" : "ZSM makes 2FA easy and invisible for everyone, all the time, using advanced cryptography like MPC to establish cryptographic proof of the origin of any transaction or login attempt, while eliminating opportunities for social engineering. ZSM has no reliance on specific hardware. Our cryptographic module has completed FIPS 140-3 NIST approved lab testing, is FIDO2-ready, and is on the Modules In Progress (MIP) list. Superior Usability. no opt-in, no codes, no downloads, no authenticator apps. Better Security.",
5
5
  "author" : "Jason Jurusz <jj@useideem.com>",
6
6
  "keywords" : [ "ideem", "zsm", "zsm-client-sdk", "umfaclient", "fido2client", "library", "umfa", "fido", "fido2", "client", "javascript", "multifactor", "multi-factor", "webauthn", "authentication", "security", "cryptography", "mpc", "fips", "nist", "mip", "passkeys" ],
7
7
  "type" : "module",
8
8
  "main" : "./ZSMClientSDK.js",
9
9
  "exports" : {
10
- ".": {
11
- "import": "./ZSMClientSDK.js",
12
- "default": "./ZSMClientSDK.js"
13
- }
14
- },
10
+ "." : "./ZSMClientSDK.js",
11
+ "./*" : "./*.js",
12
+ "./*.js" : "./*.js"
13
+ },
14
+
15
15
  "scripts" : {
16
16
  "start" : "echo 'This is the Ideem SDK library, not a freestanding application. There is no start script defined. To use, import the library into a browser application.' 1>&2",
17
17
  "showVersion" : "echo \"$(npm pkg get name | tr -d \\\") current version: $(npm pkg get version | tr -d \\\")\""