@ideem/zsm-client-sdk 2.3.0 → 2.4.0
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/RELEASE_NOTES.txt +9 -1
- package/ZSMClientSDK.js +135 -70
- package/package.json +1 -1
- package/worker.js +1748 -1553
package/RELEASE_NOTES.txt
CHANGED
|
@@ -15,7 +15,15 @@ and Universal MFA into a browser application.
|
|
|
15
15
|
|
|
16
16
|
----
|
|
17
17
|
|
|
18
|
-
## Release 2.
|
|
18
|
+
## Release 2.4.0 - May 1, 2025 [ NPM PACKAGE RELEASE ] **[ LATEST ]**
|
|
19
|
+
- Minor bug fixes and improvements
|
|
20
|
+
- Updates to documentation
|
|
21
|
+
- Adds event emitters to the UMFAClient and FIDO2Client for on-the-fly initializations
|
|
22
|
+
- Adds extended multi-tenancy support for the UMFAClient and FIDO2Client
|
|
23
|
+
- Adds increased detail to performance logging
|
|
24
|
+
- Extends secure local storage support
|
|
25
|
+
|
|
26
|
+
## Release 2.3.0 - Mar 24, 2025
|
|
19
27
|
- Minor bug fixes and improvements
|
|
20
28
|
- Updates to documentation
|
|
21
29
|
- Introduces web-worker-driven JS SDK Client for browser-based applications
|
package/ZSMClientSDK.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// Alias environment-specific global object
|
|
2
|
-
const GLOBAL = typeof globalThis !== "undefined" ? globalThis
|
|
3
|
-
: typeof self !== "undefined" ? self
|
|
4
|
-
: typeof window !== "undefined" ? window
|
|
5
|
-
: typeof global !== "undefined" ? global
|
|
6
|
-
: (() => { throw new Error("Unable to determine global scope"); })();
|
|
2
|
+
const GLOBAL = typeof globalThis !== "undefined" ? globalThis
|
|
3
|
+
: typeof self !== "undefined" ? self
|
|
4
|
+
: typeof window !== "undefined" ? window
|
|
5
|
+
: typeof global !== "undefined" ? global
|
|
6
|
+
: (() => { throw new Error("Unable to determine global scope"); })();
|
|
7
7
|
|
|
8
8
|
// Error class for worker errors
|
|
9
9
|
class WorkerError extends Error {
|
|
@@ -26,49 +26,84 @@ class ZSMClientBase {
|
|
|
26
26
|
this.timeoutTimer = null;
|
|
27
27
|
GLOBAL.zsmClient = null;
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @name init
|
|
32
|
+
* @description Initializes the ZSMClient instance and sets up the worker.
|
|
33
|
+
* @param {String} clientType The type of client to initialize [default: 'UMFAClient']
|
|
34
|
+
* @param {Object} config The configuration object for the client [default: this.config]
|
|
35
|
+
* @returns {Promise<ZSMClientBase>} A promise that resolves to the initialized ZSMClient instance.
|
|
36
|
+
*/
|
|
37
|
+
async init(clientType='UMFAClient', config=this.config) {
|
|
31
38
|
if(GLOBAL.clientWorker) GLOBAL.clientWorker.terminate();
|
|
32
39
|
const workerPath = GLOBAL?.workerPath ? GLOBAL.workerPath
|
|
33
|
-
|
|
34
|
-
|
|
40
|
+
: config?.workerPath ? config.workerPath
|
|
41
|
+
: './worker.js';
|
|
35
42
|
const pathResolver = (import.meta && import.meta?.resolve) ? import.meta?.resolve(workerPath)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
43
|
+
: (import.meta && import.meta?.url) ? import.meta?.url.replace(/\/[^\/]+$/, '/' + workerPath)
|
|
44
|
+
: document?.currentScript ? document?.currentScript?.src?.replace(/\/[^\/]+$/, '/' + workerPath)
|
|
45
|
+
: workerPath;
|
|
39
46
|
GLOBAL.clientWorker = this.clientWorker = new Worker(new URL(pathResolver));
|
|
40
47
|
GLOBAL.zsmClient = this;
|
|
41
48
|
await this.callWorkerFunction("init", {config, clientType}, false);
|
|
42
49
|
return this;
|
|
43
50
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @name callWorkerFunction
|
|
54
|
+
* @description Calls a function in the worker and returns a promise that resolves with the result.
|
|
55
|
+
* @param {String} functionName The name of the function to call in the worker.
|
|
56
|
+
* @param {Object} data The data to pass to the worker function.
|
|
57
|
+
* @param {Boolean} responseExpected Whether an acknowledgement is expected [Default: true]
|
|
58
|
+
* @returns {Promise<Object>} A promise that resolves with the result of the worker function.
|
|
59
|
+
*/
|
|
60
|
+
async callWorkerFunction(functionName, data, responseExpected=true) {
|
|
61
|
+
let workerPromise = new Promise((resolve, reject) => {
|
|
47
62
|
this.clientWorker.postMessage({functionName, data });
|
|
48
|
-
if(
|
|
49
|
-
|
|
63
|
+
if(responseExpected) this.timeoutTimer = GLOBAL.setTimeout(() => reject(new WorkerError('Transaction', 'Transaction timed out after 60 seconds!')), 60000);
|
|
64
|
+
|
|
50
65
|
this.clientWorker.onmessage = (event) => {
|
|
51
66
|
GLOBAL.clearTimeout(this.timeoutTimer);
|
|
52
|
-
|
|
67
|
+
|
|
53
68
|
let workerResponse = event.data;
|
|
69
|
+
|
|
54
70
|
if(GLOBAL.showWorkerTelemetry && (workerResponse.result || workerResponse.error)) {
|
|
55
71
|
console.groupCollapsed(`%cWorker posted to Main Thread a response to invocation:`, 'font-weight:bold; color:#F60;', functionName)
|
|
56
72
|
console.log(`%c Function Invoked:`, 'font-weight:100; color:#AAA;', workerResponse.functionName);
|
|
57
73
|
console.log(`%c Success Status:`, 'font-weight:100; color:#AAA;', workerResponse.success ? 'true' : 'false');
|
|
58
|
-
console.log(`%c Result value:`, 'font-weight:100; color:#AAA;', (workerResponse.success ? workerResponse.result : workerResponse.error));
|
|
74
|
+
console.log(`%c Result value:`, 'font-weight:100; color:#AAA;', (workerResponse.success ? workerResponse.result : workerResponse.error));
|
|
59
75
|
console.log(`%c Response Object:`, 'font-weight:100; color:#AAA;', workerResponse);
|
|
60
76
|
console.groupEnd();
|
|
61
77
|
}
|
|
62
|
-
|
|
78
|
+
|
|
63
79
|
if (workerResponse instanceof Error || workerResponse.error || !workerResponse.success) {
|
|
64
80
|
return reject(workerResponse.error);
|
|
65
81
|
}
|
|
66
82
|
resolve(workerResponse.result);
|
|
67
83
|
};
|
|
68
|
-
|
|
84
|
+
|
|
69
85
|
this.clientWorker.onerror = (err) => { GLOBAL.clearTimeout(this.timeoutTimer); reject(new WorkerError('', err.message)); };
|
|
70
86
|
this.clientWorker.onmessageerror = (err) => { GLOBAL.clearTimeout(this.timeoutTimer); reject(new WorkerError('Message', err.message)); };
|
|
71
87
|
});
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @event workerEvent
|
|
91
|
+
* @description Event triggered when the worker posts an event to the main thread.
|
|
92
|
+
* @param {String} eventName The name of the event.
|
|
93
|
+
* @param {Object} eventData The data associated with the event.
|
|
94
|
+
* @returns {void}
|
|
95
|
+
* @emits {CustomEvent} event The event object containing the received event name and data.
|
|
96
|
+
* @example GLOBAL.addEventListener('workerEvent', (event) => {
|
|
97
|
+
* @ console.log('Received event from worker:', event.detail.eventName, event.detail.eventData);
|
|
98
|
+
* @ });
|
|
99
|
+
*/
|
|
100
|
+
this.clientWorker.addEventListener('message', (event) => {
|
|
101
|
+
if(!event.data || !event.data.eventName) return;
|
|
102
|
+
const { eventName, eventData } = event.data;
|
|
103
|
+
if(GLOBAL.showWorkerTelemetry) console.log(`%cWorker posted to Main Thread an event:`, 'font-weight:bold; color:#F60;', eventName, eventData);
|
|
104
|
+
GLOBAL.dispatchEvent(new CustomEvent(eventName, { detail: eventData }));
|
|
105
|
+
});
|
|
106
|
+
return workerPromise;
|
|
72
107
|
}
|
|
73
108
|
}
|
|
74
109
|
|
|
@@ -84,18 +119,18 @@ class UMFAClient extends ZSMClientBase {
|
|
|
84
119
|
this.optimizedAuthenticate = this.optimizedAuthenticate.bind(this);
|
|
85
120
|
this.init('UMFAClient');
|
|
86
121
|
}
|
|
87
|
-
|
|
122
|
+
|
|
88
123
|
async checkEnrollment(user) { return await this.callWorkerFunction('checkEnrollment', user); }
|
|
89
124
|
async enroll(user) { return await this.callWorkerFunction('enroll', user); }
|
|
90
125
|
async authenticate(user) { return await this.callWorkerFunction('authenticate', user); }
|
|
91
126
|
async optimizedEnroll(user) { return await this.callWorkerFunction('optimizedEnroll', user); }
|
|
92
|
-
async optimizedAuthenticate(user) { return await this.callWorkerFunction('optimizedAuthenticate', user); }
|
|
127
|
+
async optimizedAuthenticate(user) { return await this.callWorkerFunction('optimizedAuthenticate', user); }
|
|
93
128
|
async unenroll(user) { return await this.callWorkerFunction('unenroll', user); }
|
|
94
129
|
}
|
|
95
130
|
|
|
96
131
|
class FIDO2Client extends ZSMClientBase {
|
|
97
132
|
constructor(config) {
|
|
98
|
-
super(config);
|
|
133
|
+
super(config);
|
|
99
134
|
this.init = super.init.bind(this);
|
|
100
135
|
this.callWorkerFunction = super.callWorkerFunction.bind(this);
|
|
101
136
|
this.checkEnrollment = this.checkEnrollment.bind(this);
|
|
@@ -106,7 +141,7 @@ class FIDO2Client extends ZSMClientBase {
|
|
|
106
141
|
this.webauthnDelete = this.webauthnDelete.bind(this);
|
|
107
142
|
this.init('FIDO2Client');
|
|
108
143
|
}
|
|
109
|
-
|
|
144
|
+
|
|
110
145
|
async checkIdentity(user, auto=true) { return await this.callWorkerFunction('checkIdentity', [user, auto]); }
|
|
111
146
|
async checkEnrollment(user) { return await this.callWorkerFunction('checkEnrollment', user); }
|
|
112
147
|
async webauthnCreate(user) { return await this.callWorkerFunction('webauthnCreate', user); }
|
|
@@ -119,16 +154,16 @@ function amendPerformanceLoggingToClass(cls) {
|
|
|
119
154
|
GLOBAL.sessionStamp = new Date();
|
|
120
155
|
GLOBAL.sessionStamp = new Date(GLOBAL.sessionStamp.getTime() - (GLOBAL.sessionStamp.getTimezoneOffset() * 60000)).toISOString().slice(11, -5);
|
|
121
156
|
GLOBAL.exportCount = 0;
|
|
122
|
-
|
|
157
|
+
|
|
123
158
|
if(GLOBAL.logStack == null) {
|
|
124
159
|
GLOBAL.logStack = [];
|
|
125
160
|
GLOBAL.getLogs = () => GLOBAL.logStack.sort((a, b) => a.stamp - b.stamp);
|
|
126
161
|
GLOBAL.clearLogs = () => {GLOBAL.logStack = []; };
|
|
127
162
|
GLOBAL.showLogs = () => {
|
|
128
163
|
if(!GLOBAL.logStack || GLOBAL.logStack.length === 0) return console.info('There are no logs currently in the stack!');
|
|
129
|
-
|
|
164
|
+
|
|
130
165
|
const getTime = (ISOStamp) => new Date(ISOStamp).toISOString().split('T')[1].slice(0,-1);
|
|
131
|
-
|
|
166
|
+
|
|
132
167
|
(function parseLog(stack=[...GLOBAL.logStack], parentEndTime = Infinity) {
|
|
133
168
|
while (stack.length > 0 && stack[0].startTime < parentEndTime) {
|
|
134
169
|
let markS, markE, spanName, indE, duration, stamps;
|
|
@@ -138,14 +173,14 @@ function amendPerformanceLoggingToClass(cls) {
|
|
|
138
173
|
if (indE !== -1) markE = stack.splice(indE, 1)[0];
|
|
139
174
|
duration = (markE != null) ? (markE.startTime - markS.startTime).toFixed(4) + 'ms' : 'ONGOING';
|
|
140
175
|
stamps = (markE != null) ? getTime(markS.stamp) + " - " + getTime(markE.stamp) : getTime(markS.stamp) + " - ...";
|
|
141
|
-
|
|
176
|
+
|
|
142
177
|
console.groupCollapsed(spanName.replace(/-/g, ' :: ') + ' :: ' + duration + " (" + stamps + ")");
|
|
143
178
|
parseLog(stack, markE.startTime);
|
|
144
179
|
console.groupEnd();
|
|
145
180
|
}
|
|
146
181
|
})()
|
|
147
182
|
}
|
|
148
|
-
|
|
183
|
+
|
|
149
184
|
GLOBAL.addPerfMarker = (tag) => {
|
|
150
185
|
const {name, startTime} = performance.mark(tag).toJSON();
|
|
151
186
|
GLOBAL.logStack.push({
|
|
@@ -157,14 +192,14 @@ function amendPerformanceLoggingToClass(cls) {
|
|
|
157
192
|
});
|
|
158
193
|
}
|
|
159
194
|
}
|
|
160
|
-
|
|
195
|
+
|
|
161
196
|
return class extends cls {
|
|
162
197
|
constructor(...args) {
|
|
163
198
|
super(...args);
|
|
164
|
-
|
|
199
|
+
|
|
165
200
|
Object.getOwnPropertyNames(this).forEach(propName => {
|
|
166
201
|
if (propName === "constructor" || typeof this[propName] !== "function") return;
|
|
167
|
-
|
|
202
|
+
|
|
168
203
|
const originalMethod = this[propName];
|
|
169
204
|
let markerTagPrefix = `[MAINTHREAD]-${cls.name}-${propName}`;
|
|
170
205
|
this[propName] = function(...args) {
|
|
@@ -190,12 +225,11 @@ if(typeof FIDO2Client !== "undefined" && FIDO2Client instanceof Function) FIDO2C
|
|
|
190
225
|
let masterLogs = [];
|
|
191
226
|
if(window){
|
|
192
227
|
let tzO = new Date().getTimezoneOffset() * 60000;
|
|
193
|
-
|
|
228
|
+
|
|
194
229
|
GLOBAL.getAllLogs = async (showCSV) => {
|
|
195
|
-
let res = await zsmClient.callWorkerFunction("getLogs");
|
|
230
|
+
let res = await zsmClient.callWorkerFunction("getLogs");
|
|
196
231
|
let {logs, timeOrigin} = JSON.parse(res);
|
|
197
232
|
let timeDifferential = performance.timeOrigin - timeOrigin;
|
|
198
|
-
console.log('timeDifferential :', timeDifferential);
|
|
199
233
|
if(!showCSV) {
|
|
200
234
|
console.groupCollapsed('RAW logs');
|
|
201
235
|
GLOBAL.logStack.forEach(mainRecord => console.info('mainRecord :', mainRecord));
|
|
@@ -214,20 +248,32 @@ if(window){
|
|
|
214
248
|
allLogs.forEach(log => console.info('log :', log));
|
|
215
249
|
console.groupEnd();
|
|
216
250
|
}
|
|
251
|
+
console.groupCollapsed('ALL logs (Combined and Sorted)');
|
|
252
|
+
allLogs = allLogs.map(log => {
|
|
253
|
+
if(!localStorage) return log;
|
|
254
|
+
let activeEnv = localStorage.getItem('activeEnv');
|
|
255
|
+
if(!activeEnv) return log;
|
|
256
|
+
if(! /RELPARTYSERVER|CRYPTOSERVER/.test(log.type)) return log;
|
|
257
|
+
// log.type += '-' + activeEnv.toUpperCase();
|
|
258
|
+
return log;
|
|
259
|
+
});
|
|
260
|
+
allLogs.forEach(log => console.info('log :', log));
|
|
261
|
+
console.groupEnd();
|
|
262
|
+
|
|
217
263
|
return allLogs;
|
|
218
264
|
};
|
|
219
|
-
|
|
265
|
+
|
|
220
266
|
GLOBAL.showLogs = async (showCSV=false) => {
|
|
221
|
-
const getTime = (ISOStamp) => {
|
|
267
|
+
const getTime = (ISOStamp, timeOnly=true) => {
|
|
222
268
|
try{
|
|
223
|
-
return new Date((+ISOStamp - tzO)).toISOString().slice(11,-1);
|
|
269
|
+
return timeOnly ? new Date((+ISOStamp - tzO)).toISOString().slice(11,-1) : new Date(+ISOStamp - tzO).toISOString();
|
|
224
270
|
}catch(e){
|
|
225
271
|
console.error('Error parsing ISOStamp:', ISOStamp, e);
|
|
226
272
|
return ISOStamp;
|
|
227
273
|
}
|
|
228
274
|
}
|
|
229
275
|
const stripStartEnd = (name) => name.replace(/-(START|END)$/gi, '');
|
|
230
|
-
|
|
276
|
+
|
|
231
277
|
function recursivelyMoveChildLogsIntoStartNode(stack) {
|
|
232
278
|
let processedLogs = [];
|
|
233
279
|
while (stack.length > 0) {
|
|
@@ -237,42 +283,46 @@ if(window){
|
|
|
237
283
|
}
|
|
238
284
|
let endingMarker = stack.findIndex(log => log.name === stripStartEnd(startingMarker.name) + '-END'),
|
|
239
285
|
dateTimeStamps = [],
|
|
286
|
+
fullDateStamps = [],
|
|
240
287
|
stackSubset = [],
|
|
241
288
|
totalDuration = 0,
|
|
242
289
|
networkLatency = 0,
|
|
243
290
|
computeDuration = 0;
|
|
244
|
-
|
|
291
|
+
|
|
245
292
|
if(!~endingMarker) {
|
|
246
293
|
stackSubset = stack;
|
|
247
294
|
endingMarker = stack.length;
|
|
248
295
|
totalDuration = 'ONGOING';
|
|
249
296
|
dateTimeStamps.push(getTime(startingMarker.stamp), '...?');
|
|
250
|
-
|
|
297
|
+
fullDateStamps.push(getTime(startingMarker.stamp, false), '...?');
|
|
298
|
+
|
|
251
299
|
}else{
|
|
252
300
|
stackSubset = stack.splice(0, endingMarker+1);
|
|
253
301
|
endingMarker = stackSubset[stackSubset.length-1];
|
|
254
302
|
totalDuration = endingMarker.absTime - startingMarker.absTime;
|
|
255
303
|
dateTimeStamps.push(getTime(startingMarker.stamp), getTime(endingMarker.stamp));
|
|
256
|
-
|
|
304
|
+
fullDateStamps.push(getTime(startingMarker.stamp, false), getTime(endingMarker.stamp, false));
|
|
305
|
+
|
|
257
306
|
}
|
|
258
|
-
|
|
307
|
+
|
|
259
308
|
processedLogs.push(Object.assign(startingMarker, {
|
|
260
309
|
name: stripStartEnd(startingMarker.name),
|
|
261
310
|
children: recursivelyMoveChildLogsIntoStartNode(stackSubset),
|
|
262
|
-
totalDuration,
|
|
311
|
+
totalDuration,
|
|
263
312
|
dateTimeStamps,
|
|
313
|
+
fullDateStamps,
|
|
264
314
|
networkLatency,
|
|
265
315
|
computeDuration
|
|
266
316
|
}));
|
|
267
317
|
}
|
|
268
318
|
return processedLogs;
|
|
269
319
|
}
|
|
270
|
-
|
|
320
|
+
|
|
271
321
|
function recursivelyComputeCumulativeNetworkLatency(node) {
|
|
272
322
|
let nodeLatency = 0;
|
|
273
323
|
if(node.clientToServerLatency) nodeLatency += node.clientToServerLatency;
|
|
274
324
|
if(node.serverToClientLatency) nodeLatency += node.serverToClientLatency;
|
|
275
|
-
|
|
325
|
+
|
|
276
326
|
if (Array.isArray(node.children) && node.children.length > 0) {
|
|
277
327
|
node.children.forEach(child => {
|
|
278
328
|
nodeLatency += recursivelyComputeCumulativeNetworkLatency(child);
|
|
@@ -281,7 +331,7 @@ if(window){
|
|
|
281
331
|
node.networkLatency = nodeLatency;
|
|
282
332
|
return nodeLatency;
|
|
283
333
|
}
|
|
284
|
-
|
|
334
|
+
|
|
285
335
|
function calculateComputeDurationForNode(node) {
|
|
286
336
|
if(!node.children) return node.computeDuration = totalDuration;
|
|
287
337
|
node.computeDuration = (node.children.reduce((acc,child)=>{
|
|
@@ -289,9 +339,9 @@ if(window){
|
|
|
289
339
|
}, node.totalDuration))
|
|
290
340
|
node.children.forEach(calculateComputeDurationForNode)
|
|
291
341
|
}
|
|
292
|
-
|
|
342
|
+
|
|
293
343
|
let exportableStack = [];
|
|
294
|
-
|
|
344
|
+
|
|
295
345
|
function recursivelyOutputLogsToConsole(stack, depth = 0) {
|
|
296
346
|
let outputColors={
|
|
297
347
|
'MAINTHREAD': '#509',
|
|
@@ -301,20 +351,20 @@ if(window){
|
|
|
301
351
|
'RELPARTY': '#076',
|
|
302
352
|
'CRYPTO': '#700',
|
|
303
353
|
};
|
|
304
|
-
|
|
354
|
+
|
|
305
355
|
function formatNumberColumn(num, NaNValue='0.000') {
|
|
306
356
|
let opValue = isNaN(num) ? NaNValue : Math.abs(num).toFixed(3);
|
|
307
357
|
let lPadStr = ' '.repeat(12 - opValue.length);
|
|
308
358
|
return lPadStr + opValue;
|
|
309
359
|
}
|
|
310
|
-
|
|
360
|
+
|
|
311
361
|
stack.forEach(item => {
|
|
312
362
|
let spacePadding = ' '.repeat(100);
|
|
313
363
|
let exportableRecord = {}
|
|
314
364
|
let sequence = item.order;
|
|
315
|
-
let nameElements = item.name.
|
|
316
|
-
let threadName = (nameElements[0] + spacePadding).slice(0, 14);
|
|
317
|
-
let processName = (nameElements[1]
|
|
365
|
+
let nameElements = (item.name.match(/\[(.*?)\]-(.*)$/) || new Array(3).fill('')).slice(1,3);
|
|
366
|
+
let threadName = (nameElements[0] + spacePadding).replace('SERVER', '').slice(0, 14);
|
|
367
|
+
let processName = (nameElements[1] + spacePadding).slice(0, 70-(depth*2));
|
|
318
368
|
let totalDuration = formatNumberColumn(item?.totalDuration, 'ONGOING');
|
|
319
369
|
let computeDuration = (/ONGOING/.test(totalDuration)) ? formatNumberColumn('ONGOING', 'ONGOING') : formatNumberColumn(item?.computeDuration);
|
|
320
370
|
let networkLatency = (/ONGOING/.test(totalDuration)) ? formatNumberColumn('ONGOING', 'ONGOING') : formatNumberColumn(item?.networkLatency);
|
|
@@ -324,11 +374,17 @@ if(window){
|
|
|
324
374
|
if(totalDuration < (Math.abs(networkLatency) + Math.abs(computeDuration))) totalDuration = formatNumberColumn(Math.abs(networkLatency) + Math.abs(computeDuration));
|
|
325
375
|
cumulativeCompute = formatNumberColumn((totalDuration - networkLatency - computeDuration), 'ONGOING');
|
|
326
376
|
}
|
|
327
|
-
let
|
|
328
|
-
|
|
377
|
+
let indentionDepth = depth;
|
|
378
|
+
if (/^CRYPTO/.test(threadName)) {
|
|
379
|
+
indentionDepth = depth + 2;
|
|
380
|
+
processName = processName.slice(0, -4);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
let indentionPads = depth > 0 ? ' '.repeat(indentionDepth-1) + ' ' : ' ';
|
|
384
|
+
let detailPads = depth > 0 ? ' '.repeat(indentionDepth-1) + ' '.repeat(threadName.length) + ' ' : ' ' + ' '.repeat(threadName.length);
|
|
329
385
|
let timeSpan = item?.dateTimeStamps ? (' ' + item.dateTimeStamps[0]) : 'N/A';
|
|
330
|
-
|
|
331
|
-
if(!showCSV) {
|
|
386
|
+
|
|
387
|
+
// if(!showCSV) {
|
|
332
388
|
let outputLine = ` ${threadName}${indentionPads} ${processName} ${totalDuration} ${networkLatency} ${cumulativeCompute} ${computeDuration} ${timeSpan}`;
|
|
333
389
|
console.groupCollapsed(`%c${outputLine}`, `color: ${outputColors[item.type]}; font-weight: 500;`);
|
|
334
390
|
console.info(`%c${detailPads} Sequence: `, `color: ${outputColors[item.type]}; font-weight: 700;`, sequence);
|
|
@@ -343,7 +399,13 @@ if(window){
|
|
|
343
399
|
console.info(`%c${detailPads} Process Compute Duration: `, `color: ${outputColors[item.type]}; font-weight: 700;`, (/ONGOING/.test(computeDuration) ? 'ONGOING' : computeDuration.trim() + 'ms'));
|
|
344
400
|
console.info(`%c${detailPads} ================================================================`, `color: ${outputColors[item.type]}; font-weight: 700;`, "\n\n");
|
|
345
401
|
console.groupEnd();
|
|
346
|
-
} else {
|
|
402
|
+
// } else if(!showCSV || showCSV) {
|
|
403
|
+
let activeEnv = '';
|
|
404
|
+
let pageHost = window.location.host;
|
|
405
|
+
|
|
406
|
+
if(localStorage && localStorage.getItem('activeEnv')) {
|
|
407
|
+
activeEnv = (/RELPARTY|CRYPTO/.test(threadName)) ? localStorage.getItem('activeEnv') : 'N/A';
|
|
408
|
+
}
|
|
347
409
|
exportableRecord = {
|
|
348
410
|
sequence : sequence,
|
|
349
411
|
threadName : threadName.trim(),
|
|
@@ -353,24 +415,27 @@ if(window){
|
|
|
353
415
|
networkLatency : (/ONGOING/.test(networkLatency) ? 'ONGOING' : +(networkLatency.trim())),
|
|
354
416
|
cumulativeCompute : (/ONGOING/.test(cumulativeCompute) ? 'ONGOING' : +(cumulativeCompute.trim())),
|
|
355
417
|
computeDuration : (/ONGOING/.test(computeDuration) ? 'ONGOING' : +(computeDuration.trim())),
|
|
356
|
-
startTime : (item?.
|
|
357
|
-
endTime : (item?.
|
|
358
|
-
spawnsChildren : item?.children ? item.children.length : 0
|
|
418
|
+
startTime : (item?.fullDateStamps[0]?.replace(/[TZ]/g, ' ').trim() ?? ''),
|
|
419
|
+
endTime : (item?.fullDateStamps[1]?.replace(/[TZ]/g, ' ').trim() ?? ''),
|
|
420
|
+
spawnsChildren : item?.children ? item.children.length : 0,
|
|
421
|
+
host : pageHost,
|
|
422
|
+
remoteAPIEnv : activeEnv,
|
|
359
423
|
};
|
|
360
|
-
|
|
424
|
+
|
|
361
425
|
exportableStack.push(exportableRecord);
|
|
362
|
-
}
|
|
426
|
+
// }
|
|
363
427
|
if(item.children.length > 0) recursivelyOutputLogsToConsole(item.children, depth + 1);
|
|
364
428
|
});
|
|
365
429
|
return exportableStack.length ? exportableStack : undefined;
|
|
366
430
|
}
|
|
367
|
-
|
|
431
|
+
|
|
368
432
|
let allLogs = await GLOBAL.getAllLogs(showCSV);
|
|
369
433
|
let processedStack = recursivelyMoveChildLogsIntoStartNode(allLogs);
|
|
370
434
|
processedStack.forEach(root => recursivelyComputeCumulativeNetworkLatency(root));
|
|
371
435
|
processedStack.forEach(root => calculateComputeDurationForNode(root));
|
|
372
436
|
if(!showCSV) console.info(`%c${' THREAD PROCESS NAME DURATION NETWORK TOT.COMP. COMPUTE START TIME'}`, 'color: #000; font-weight: 700;');
|
|
373
437
|
let exportableData = recursivelyOutputLogsToConsole(processedStack);
|
|
438
|
+
console.log('exportableData :', exportableData);
|
|
374
439
|
if(!showCSV || !exportableData) return;
|
|
375
440
|
let csvData = exportableData.flatMap((log, i) => {
|
|
376
441
|
let retVal = [Object.values(log)];
|
|
@@ -379,7 +444,7 @@ if(window){
|
|
|
379
444
|
if(i === 0) retVal.unshift('"' + Object.keys(log).join('","') + '"');
|
|
380
445
|
return retVal;
|
|
381
446
|
});
|
|
382
|
-
|
|
447
|
+
|
|
383
448
|
try {
|
|
384
449
|
GLOBAL.exportCount++;
|
|
385
450
|
console.groupCollapsed(`CSV Data Exported as %c${GLOBAL.sessionStamp}-${(GLOBAL.exportCount)}.csv`, 'color: #F60; font-weight: 700;');
|
|
@@ -394,15 +459,15 @@ if(window){
|
|
|
394
459
|
URL.revokeObjectURL(url);
|
|
395
460
|
GLOBAL.logStack = [];
|
|
396
461
|
zsmClient.callWorkerFunction("clearLogs", true);
|
|
397
|
-
console.groupEnd();
|
|
462
|
+
console.groupEnd();
|
|
398
463
|
} catch (error) {
|
|
399
464
|
console.error('Error during download:', error);
|
|
400
465
|
console.groupEnd();
|
|
401
466
|
}
|
|
402
|
-
|
|
467
|
+
|
|
403
468
|
return exportableData;
|
|
404
469
|
}
|
|
405
|
-
|
|
470
|
+
|
|
406
471
|
}
|
|
407
472
|
|
|
408
473
|
export { UMFAClient, FIDO2Client };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ideem/zsm-client-sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
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": "@JJ (Jason Jurusz) <jj@useideem.com>/<nerdy.deeds@done.cheap>",
|
|
6
6
|
"keywords": [
|