@ideem/zsm-client-sdk 2.2.5 → 2.3.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/README.md +6 -0
- package/RELEASE_NOTES.txt +108 -0
- package/ZSMClientSDK.js +408 -0
- package/package.json +16 -11
- package/worker.js +2308 -0
- package/zsm-client-sdk.js +0 -1872
package/README.md
CHANGED
|
@@ -29,3 +29,9 @@ An example application demonstrating how to integrate this SDK into an applicati
|
|
|
29
29
|
|
|
30
30
|
## Support
|
|
31
31
|
You can receive support and get your questions answered by emailing <a href="mailto:support@useideem.com">support@useideem.com</a>.
|
|
32
|
+
|
|
33
|
+
### License
|
|
34
|
+
Please refer to the LICENSE file in this directory for the license governing the use of this SDK.
|
|
35
|
+
|
|
36
|
+
### Release Notes
|
|
37
|
+
Please refer to the RELEASE_NOTES.txt file in this directory for the release notes of this SDK.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
ZSM Client SDK for Browser Apps
|
|
2
|
+
Latest version: v2.3.0
|
|
3
|
+
Latest release date: March 24, 2025
|
|
4
|
+
|
|
5
|
+
The ZSM Client SDK for Browser Apps provides the resources needed to integrate Ideem's FIDO2 Authenticator
|
|
6
|
+
and Universal MFA into a browser application.
|
|
7
|
+
|
|
8
|
+
## Resources:
|
|
9
|
+
- UMFA Documentation: https://docs.useideem.com/umfa_sdk/browser/index.html
|
|
10
|
+
- FIDO2 Documentation: https://docs.useideem.com/fido2_sdk/browser/index.html
|
|
11
|
+
- Support: support@useideem.com
|
|
12
|
+
|
|
13
|
+
## Known Issues
|
|
14
|
+
- None
|
|
15
|
+
|
|
16
|
+
----
|
|
17
|
+
|
|
18
|
+
## Release 2.3.0 - Mar 24, 2025 [ NPM PACKAGE RELEASE ] **[ LATEST ]**
|
|
19
|
+
- Minor bug fixes and improvements
|
|
20
|
+
- Updates to documentation
|
|
21
|
+
- Introduces web-worker-driven JS SDK Client for browser-based applications
|
|
22
|
+
- Significant performance improvements to the UMFA JS Client
|
|
23
|
+
- Updates native mobile SDKs to support the new optimized flows
|
|
24
|
+
- Adds unenroll/webauthnDelete functionality to UMFAClient and FIDO2Client (browser, mobile, and native)
|
|
25
|
+
- Updates data parsing and replication in SQL and Oracle environments
|
|
26
|
+
|
|
27
|
+
## Release 2.2.12 - Mar 14, 2025
|
|
28
|
+
- Minor bug fixes and improvements
|
|
29
|
+
- Updates to documentation
|
|
30
|
+
- Improves server-side TLS handling performance
|
|
31
|
+
- Adds optimized flows to the UMFA CLI Client
|
|
32
|
+
|
|
33
|
+
## Release 2.2.11 - Mar 5, 2025
|
|
34
|
+
- Minor bug fixes and improvements
|
|
35
|
+
- Updates to documentation
|
|
36
|
+
- Updates to UMFA CLI for enhanced trace reporting
|
|
37
|
+
- Updates Affinity rules
|
|
38
|
+
- Native Webauthn apps and sdk updates
|
|
39
|
+
- Improves package and file versioning for safer deployments
|
|
40
|
+
|
|
41
|
+
## Release 2.2.10 - Feb 27, 2025
|
|
42
|
+
- Minor bug fixes and improvements
|
|
43
|
+
- Updates to documentation
|
|
44
|
+
- Performance upgrades to AS2 environment
|
|
45
|
+
- Extended Trace Map and Host URL Parameter Renames
|
|
46
|
+
- Updates to Android-based tls security
|
|
47
|
+
- CLI updates for compression formats
|
|
48
|
+
|
|
49
|
+
## Release 2.2.9 - Feb 14, 2025
|
|
50
|
+
- Minor bug fixes and improvements
|
|
51
|
+
- Updates to documentation
|
|
52
|
+
- Adjustments to deployment process
|
|
53
|
+
- React Native SDK updates
|
|
54
|
+
- Extended trace mapping implementation
|
|
55
|
+
|
|
56
|
+
## Release 2.2.8 - Feb 7, 2025 [ NPM PACKAGE RELEASE ]
|
|
57
|
+
- Minor bug fixes and improvements
|
|
58
|
+
- Updates to documentation
|
|
59
|
+
- Adds support for the latest version of the React Native SDK
|
|
60
|
+
- Adds 2 New production-ready environments
|
|
61
|
+
- Updates binaries for use with M-class Macs
|
|
62
|
+
- Improves WASM binary benchmarks
|
|
63
|
+
|
|
64
|
+
## Release 2.2.7 - Jan 31, 2025
|
|
65
|
+
- Minor bug fixes and improvements
|
|
66
|
+
- Updates to documentation
|
|
67
|
+
- Removed validate token message from UMFA demo transcript
|
|
68
|
+
- Fixes condition in which mobile portrait view loses contact with clear and docs buttons.
|
|
69
|
+
- Removed dependency on colored crate
|
|
70
|
+
- Added new API for enhanced security features
|
|
71
|
+
|
|
72
|
+
## Release 2.2.6 - January 24, 2024 [ NPM PACKAGE RELEASE ]
|
|
73
|
+
- Minor bug fixes and improvements
|
|
74
|
+
- Updates to documentation
|
|
75
|
+
- Increased high-latency tolerance timeout from a 65-second max to a 300-second max.
|
|
76
|
+
- Expand Performance Logging
|
|
77
|
+
|
|
78
|
+
## Release 2.2.4 - January 22, 2024 [ NPM PACKAGE RELEASE ]
|
|
79
|
+
- Minor bug fixes and improvements
|
|
80
|
+
- Updates to documentation
|
|
81
|
+
- AS2 support added
|
|
82
|
+
|
|
83
|
+
## Release 2.2.3 - January 20, 2024 [ NPM PACKAGE RELEASE ]
|
|
84
|
+
- Minor bug fixes and improvements
|
|
85
|
+
- Updates to documentation
|
|
86
|
+
- Stability and format improvements
|
|
87
|
+
|
|
88
|
+
## Release v2.2.2 - January 13, 2024 [ NPM PACKAGE RELEASE ]
|
|
89
|
+
- Minor bug fixes and improvements
|
|
90
|
+
- Updates to documentation
|
|
91
|
+
- Deployment via NPM
|
|
92
|
+
- Addition of Vue support (foundation for other web frameworks)
|
|
93
|
+
- Addition of checkEnrollment() and enroll() APIs
|
|
94
|
+
- Addition of SDK-to-server API Key for reporting purposes (not security)
|
|
95
|
+
- Removal of validateToken() API. Token validation is to be via server-to-server for security reasons.
|
|
96
|
+
|
|
97
|
+
## Release v2.2.1 - December 9, 2024 [ NPM PACKAGE RELEASE ]
|
|
98
|
+
- Performance and stability improvements
|
|
99
|
+
- WASM size reduction
|
|
100
|
+
- Reduced expiration time to 30 seconds for the JWT returned by Authenticate
|
|
101
|
+
- Restructured SDK files to be more organized
|
|
102
|
+
- Modified application configuration approach to use a configuration json file,
|
|
103
|
+
but can also be overridden in the code.
|
|
104
|
+
- Improvements to Demo apps at https://demo.useideem.com
|
|
105
|
+
|
|
106
|
+
## Release v2.2.0 - November 19, 2024 [ NPM PACKAGE RELEASE ]
|
|
107
|
+
- Addition of FIDO2 Authenticator interfaces
|
|
108
|
+
- Addition of Universal MFA interfaces
|
package/ZSMClientSDK.js
ADDED
|
@@ -0,0 +1,408 @@
|
|
|
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"); })();
|
|
7
|
+
|
|
8
|
+
// Error class for worker errors
|
|
9
|
+
class WorkerError extends Error {
|
|
10
|
+
constructor(name, message, ...details) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.name = name ? `Worker ${name} Error` : 'Worker Error';
|
|
13
|
+
if (details.length) this.details = details;
|
|
14
|
+
if (Error.captureStackTrace) {
|
|
15
|
+
Error.captureStackTrace(this, WorkerError);
|
|
16
|
+
} else {
|
|
17
|
+
this.stack = (new Error(message)).stack;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
class ZSMClientBase {
|
|
23
|
+
constructor(config) {
|
|
24
|
+
this.config = config;
|
|
25
|
+
this.clientWorker = null;
|
|
26
|
+
this.timeoutTimer = null;
|
|
27
|
+
GLOBAL.zsmClient = null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async init(clientType = 'UMFAClient', config = this.config) {
|
|
31
|
+
if(GLOBAL.clientWorker) GLOBAL.clientWorker.terminate();
|
|
32
|
+
const workerPath = GLOBAL?.workerPath ? GLOBAL.workerPath
|
|
33
|
+
: config?.workerPath ? config.workerPath
|
|
34
|
+
: './worker.js';
|
|
35
|
+
const pathResolver = (import.meta && import.meta?.resolve) ? import.meta?.resolve(workerPath)
|
|
36
|
+
: (import.meta && import.meta?.url) ? import.meta?.url.replace(/\/[^\/]+$/, '/' + workerPath)
|
|
37
|
+
: document?.currentScript ? document?.currentScript?.src?.replace(/\/[^\/]+$/, '/' + workerPath)
|
|
38
|
+
: workerPath;
|
|
39
|
+
GLOBAL.clientWorker = this.clientWorker = new Worker(new URL(pathResolver));
|
|
40
|
+
GLOBAL.zsmClient = this;
|
|
41
|
+
await this.callWorkerFunction("init", {config, clientType}, false);
|
|
42
|
+
return this;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async callWorkerFunction(functionName, data, acknowledgementExpected=true) {
|
|
46
|
+
return new Promise((resolve, reject) => {
|
|
47
|
+
this.clientWorker.postMessage({functionName, data });
|
|
48
|
+
if(acknowledgementExpected) this.timeoutTimer = GLOBAL.setTimeout(() => reject(new WorkerError('Transaction', 'Transaction timed out after 10 seconds!')), 10000);
|
|
49
|
+
|
|
50
|
+
this.clientWorker.onmessage = (event) => {
|
|
51
|
+
GLOBAL.clearTimeout(this.timeoutTimer);
|
|
52
|
+
|
|
53
|
+
let workerResponse = event.data;
|
|
54
|
+
if(GLOBAL.showWorkerTelemetry && (workerResponse.result || workerResponse.error)) {
|
|
55
|
+
console.groupCollapsed(`%cWorker posted to Main Thread a response to invocation:`, 'font-weight:bold; color:#F60;', functionName)
|
|
56
|
+
console.log(`%c Function Invoked:`, 'font-weight:100; color:#AAA;', workerResponse.functionName);
|
|
57
|
+
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));
|
|
59
|
+
console.log(`%c Response Object:`, 'font-weight:100; color:#AAA;', workerResponse);
|
|
60
|
+
console.groupEnd();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (workerResponse instanceof Error || workerResponse.error || !workerResponse.success) {
|
|
64
|
+
return reject(workerResponse.error);
|
|
65
|
+
}
|
|
66
|
+
resolve(workerResponse.result);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
this.clientWorker.onerror = (err) => { GLOBAL.clearTimeout(this.timeoutTimer); reject(new WorkerError('', err.message)); };
|
|
70
|
+
this.clientWorker.onmessageerror = (err) => { GLOBAL.clearTimeout(this.timeoutTimer); reject(new WorkerError('Message', err.message)); };
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
class UMFAClient extends ZSMClientBase {
|
|
76
|
+
constructor(config) {
|
|
77
|
+
super(config);
|
|
78
|
+
this.init = super.init.bind(this);
|
|
79
|
+
this.callWorkerFunction = super.callWorkerFunction.bind(this);
|
|
80
|
+
this.checkEnrollment = this.checkEnrollment.bind(this);
|
|
81
|
+
this.enroll = this.enroll.bind(this);
|
|
82
|
+
this.authenticate = this.authenticate.bind(this);
|
|
83
|
+
this.optimizedEnroll = this.optimizedEnroll.bind(this);
|
|
84
|
+
this.optimizedAuthenticate = this.optimizedAuthenticate.bind(this);
|
|
85
|
+
this.init('UMFAClient');
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async checkEnrollment(user) { return await this.callWorkerFunction('checkEnrollment', user); }
|
|
89
|
+
async enroll(user) { return await this.callWorkerFunction('enroll', user); }
|
|
90
|
+
async authenticate(user) { return await this.callWorkerFunction('authenticate', user); }
|
|
91
|
+
async optimizedEnroll(user) { return await this.callWorkerFunction('optimizedEnroll', user); }
|
|
92
|
+
async optimizedAuthenticate(user) { return await this.callWorkerFunction('optimizedAuthenticate', user); }
|
|
93
|
+
async unenroll(user) { return await this.callWorkerFunction('unenroll', user); }
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
class FIDO2Client extends ZSMClientBase {
|
|
97
|
+
constructor(config) {
|
|
98
|
+
super(config);
|
|
99
|
+
this.init = super.init.bind(this);
|
|
100
|
+
this.callWorkerFunction = super.callWorkerFunction.bind(this);
|
|
101
|
+
this.checkEnrollment = this.checkEnrollment.bind(this);
|
|
102
|
+
this.checkIdentity = this.checkIdentity.bind(this);
|
|
103
|
+
this.webauthnCreate = this.webauthnCreate.bind(this);
|
|
104
|
+
this.webauthnGet = this.webauthnGet.bind(this);
|
|
105
|
+
this.webauthnRetrieve = this.webauthnRetrieve.bind(this);
|
|
106
|
+
this.webauthnDelete = this.webauthnDelete.bind(this);
|
|
107
|
+
this.init('FIDO2Client');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async checkIdentity(user, auto=true) { return await this.callWorkerFunction('checkIdentity', [user, auto]); }
|
|
111
|
+
async checkEnrollment(user) { return await this.callWorkerFunction('checkEnrollment', user); }
|
|
112
|
+
async webauthnCreate(user) { return await this.callWorkerFunction('webauthnCreate', user); }
|
|
113
|
+
async webauthnGet(user) { return await this.callWorkerFunction('webauthnGet', user); }
|
|
114
|
+
async webauthnRetrieve(user) { return await this.callWorkerFunction('webauthnRetrieve', user); }
|
|
115
|
+
async webauthnDelete(user) { return await this.callWorkerFunction('webauthnDelete', user); }
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function amendPerformanceLoggingToClass(cls) {
|
|
119
|
+
GLOBAL.sessionStamp = new Date();
|
|
120
|
+
GLOBAL.sessionStamp = new Date(GLOBAL.sessionStamp.getTime() - (GLOBAL.sessionStamp.getTimezoneOffset() * 60000)).toISOString().slice(11, -5);
|
|
121
|
+
GLOBAL.exportCount = 0;
|
|
122
|
+
|
|
123
|
+
if(GLOBAL.logStack == null) {
|
|
124
|
+
GLOBAL.logStack = [];
|
|
125
|
+
GLOBAL.getLogs = () => GLOBAL.logStack.sort((a, b) => a.stamp - b.stamp);
|
|
126
|
+
GLOBAL.clearLogs = () => {GLOBAL.logStack = []; };
|
|
127
|
+
GLOBAL.showLogs = () => {
|
|
128
|
+
if(!GLOBAL.logStack || GLOBAL.logStack.length === 0) return console.info('There are no logs currently in the stack!');
|
|
129
|
+
|
|
130
|
+
const getTime = (ISOStamp) => new Date(ISOStamp).toISOString().split('T')[1].slice(0,-1);
|
|
131
|
+
|
|
132
|
+
(function parseLog(stack=[...GLOBAL.logStack], parentEndTime = Infinity) {
|
|
133
|
+
while (stack.length > 0 && stack[0].startTime < parentEndTime) {
|
|
134
|
+
let markS, markE, spanName, indE, duration, stamps;
|
|
135
|
+
markS = stack.shift();
|
|
136
|
+
spanName = markS.name.slice(0, -6);
|
|
137
|
+
indE = stack.findIndex(log => log.name === spanName + "-END");
|
|
138
|
+
if (indE !== -1) markE = stack.splice(indE, 1)[0];
|
|
139
|
+
duration = (markE != null) ? (markE.startTime - markS.startTime).toFixed(4) + 'ms' : 'ONGOING';
|
|
140
|
+
stamps = (markE != null) ? getTime(markS.stamp) + " - " + getTime(markE.stamp) : getTime(markS.stamp) + " - ...";
|
|
141
|
+
|
|
142
|
+
console.groupCollapsed(spanName.replace(/-/g, ' :: ') + ' :: ' + duration + " (" + stamps + ")");
|
|
143
|
+
parseLog(stack, markE.startTime);
|
|
144
|
+
console.groupEnd();
|
|
145
|
+
}
|
|
146
|
+
})()
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
GLOBAL.addPerfMarker = (tag) => {
|
|
150
|
+
const {name, startTime} = performance.mark(tag).toJSON();
|
|
151
|
+
GLOBAL.logStack.push({
|
|
152
|
+
type : "MAINTHREAD",
|
|
153
|
+
order : GLOBAL.logStack.length,
|
|
154
|
+
name,
|
|
155
|
+
absTime : startTime,
|
|
156
|
+
stamp : performance.timeOrigin + startTime
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return class extends cls {
|
|
162
|
+
constructor(...args) {
|
|
163
|
+
super(...args);
|
|
164
|
+
|
|
165
|
+
Object.getOwnPropertyNames(this).forEach(propName => {
|
|
166
|
+
if (propName === "constructor" || typeof this[propName] !== "function") return;
|
|
167
|
+
|
|
168
|
+
const originalMethod = this[propName];
|
|
169
|
+
let markerTagPrefix = `[MAINTHREAD]-${cls.name}-${propName}`;
|
|
170
|
+
this[propName] = function(...args) {
|
|
171
|
+
if(propName === "callWorkerFunction") markerTagPrefix = `[MAINTHREAD]-${cls.name}-${propName}-${args[0]}`;
|
|
172
|
+
GLOBAL.addPerfMarker(markerTagPrefix + "-START");
|
|
173
|
+
const result = originalMethod.apply(this, args);
|
|
174
|
+
if (result && typeof result.then === 'function') {
|
|
175
|
+
return result.finally(() => GLOBAL.addPerfMarker(markerTagPrefix + "-END"));
|
|
176
|
+
} else {
|
|
177
|
+
GLOBAL.addPerfMarker(markerTagPrefix + "-END");
|
|
178
|
+
return result;
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
//
|
|
187
|
+
if(typeof UMFAClient !== "undefined" && UMFAClient instanceof Function) UMFAClient = amendPerformanceLoggingToClass(UMFAClient);
|
|
188
|
+
if(typeof FIDO2Client !== "undefined" && FIDO2Client instanceof Function) FIDO2Client = amendPerformanceLoggingToClass(FIDO2Client);
|
|
189
|
+
|
|
190
|
+
let masterLogs = [];
|
|
191
|
+
if(window){
|
|
192
|
+
let tzO = new Date().getTimezoneOffset() * 60000;
|
|
193
|
+
|
|
194
|
+
GLOBAL.getAllLogs = async (showCSV) => {
|
|
195
|
+
let res = await zsmClient.callWorkerFunction("getLogs");
|
|
196
|
+
let {logs, timeOrigin} = JSON.parse(res);
|
|
197
|
+
let timeDifferential = performance.timeOrigin - timeOrigin;
|
|
198
|
+
console.log('timeDifferential :', timeDifferential);
|
|
199
|
+
if(!showCSV) {
|
|
200
|
+
console.groupCollapsed('RAW logs');
|
|
201
|
+
GLOBAL.logStack.forEach(mainRecord => console.info('mainRecord :', mainRecord));
|
|
202
|
+
logs.forEach(workerRecord => {
|
|
203
|
+
workerRecord.absTime = workerRecord.absTime - timeDifferential;
|
|
204
|
+
console.info('workerRecord :', workerRecord);
|
|
205
|
+
});
|
|
206
|
+
console.groupEnd();
|
|
207
|
+
}
|
|
208
|
+
let allLogs = [...GLOBAL.logStack, ...logs];
|
|
209
|
+
allLogs = allLogs.sort((a, b) => a.absTime - b.absTime);
|
|
210
|
+
allLogs = allLogs.map((log, i) => Object.assign(log, {stamp: log.absTime + performance.timeOrigin, order:i}));
|
|
211
|
+
if(!showCSV) {
|
|
212
|
+
console.groupCollapsed('ALL logs (Combined and Sorted)');
|
|
213
|
+
masterLogs = [...masterLogs, ...allLogs];
|
|
214
|
+
allLogs.forEach(log => console.info('log :', log));
|
|
215
|
+
console.groupEnd();
|
|
216
|
+
}
|
|
217
|
+
return allLogs;
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
GLOBAL.showLogs = async (showCSV=false) => {
|
|
221
|
+
const getTime = (ISOStamp) => {
|
|
222
|
+
try{
|
|
223
|
+
return new Date((+ISOStamp - tzO)).toISOString().slice(11,-1);
|
|
224
|
+
}catch(e){
|
|
225
|
+
console.error('Error parsing ISOStamp:', ISOStamp, e);
|
|
226
|
+
return ISOStamp;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
const stripStartEnd = (name) => name.replace(/-(START|END)$/gi, '');
|
|
230
|
+
|
|
231
|
+
function recursivelyMoveChildLogsIntoStartNode(stack) {
|
|
232
|
+
let processedLogs = [];
|
|
233
|
+
while (stack.length > 0) {
|
|
234
|
+
let startingMarker = stack.shift();
|
|
235
|
+
if(/-END$/i.test(startingMarker.name)) {
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
let endingMarker = stack.findIndex(log => log.name === stripStartEnd(startingMarker.name) + '-END'),
|
|
239
|
+
dateTimeStamps = [],
|
|
240
|
+
stackSubset = [],
|
|
241
|
+
totalDuration = 0,
|
|
242
|
+
networkLatency = 0,
|
|
243
|
+
computeDuration = 0;
|
|
244
|
+
|
|
245
|
+
if(!~endingMarker) {
|
|
246
|
+
stackSubset = stack;
|
|
247
|
+
endingMarker = stack.length;
|
|
248
|
+
totalDuration = 'ONGOING';
|
|
249
|
+
dateTimeStamps.push(getTime(startingMarker.stamp), '...?');
|
|
250
|
+
|
|
251
|
+
}else{
|
|
252
|
+
stackSubset = stack.splice(0, endingMarker+1);
|
|
253
|
+
endingMarker = stackSubset[stackSubset.length-1];
|
|
254
|
+
totalDuration = endingMarker.absTime - startingMarker.absTime;
|
|
255
|
+
dateTimeStamps.push(getTime(startingMarker.stamp), getTime(endingMarker.stamp));
|
|
256
|
+
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
processedLogs.push(Object.assign(startingMarker, {
|
|
260
|
+
name: stripStartEnd(startingMarker.name),
|
|
261
|
+
children: recursivelyMoveChildLogsIntoStartNode(stackSubset),
|
|
262
|
+
totalDuration,
|
|
263
|
+
dateTimeStamps,
|
|
264
|
+
networkLatency,
|
|
265
|
+
computeDuration
|
|
266
|
+
}));
|
|
267
|
+
}
|
|
268
|
+
return processedLogs;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function recursivelyComputeCumulativeNetworkLatency(node) {
|
|
272
|
+
let nodeLatency = 0;
|
|
273
|
+
if(node.clientToServerLatency) nodeLatency += node.clientToServerLatency;
|
|
274
|
+
if(node.serverToClientLatency) nodeLatency += node.serverToClientLatency;
|
|
275
|
+
|
|
276
|
+
if (Array.isArray(node.children) && node.children.length > 0) {
|
|
277
|
+
node.children.forEach(child => {
|
|
278
|
+
nodeLatency += recursivelyComputeCumulativeNetworkLatency(child);
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
node.networkLatency = nodeLatency;
|
|
282
|
+
return nodeLatency;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function calculateComputeDurationForNode(node) {
|
|
286
|
+
if(!node.children) return node.computeDuration = totalDuration;
|
|
287
|
+
node.computeDuration = (node.children.reduce((acc,child)=>{
|
|
288
|
+
return acc - child.totalDuration;
|
|
289
|
+
}, node.totalDuration))
|
|
290
|
+
node.children.forEach(calculateComputeDurationForNode)
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
let exportableStack = [];
|
|
294
|
+
|
|
295
|
+
function recursivelyOutputLogsToConsole(stack, depth = 0) {
|
|
296
|
+
let outputColors={
|
|
297
|
+
'MAINTHREAD': '#509',
|
|
298
|
+
'WORKER': '#009',
|
|
299
|
+
'RELPARTYSERVER': '#076',
|
|
300
|
+
'CRYPTOSERVER': '#700',
|
|
301
|
+
'RELPARTY': '#076',
|
|
302
|
+
'CRYPTO': '#700',
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
function formatNumberColumn(num, NaNValue='0.000') {
|
|
306
|
+
let opValue = isNaN(num) ? NaNValue : Math.abs(num).toFixed(3);
|
|
307
|
+
let lPadStr = ' '.repeat(12 - opValue.length);
|
|
308
|
+
return lPadStr + opValue;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
stack.forEach(item => {
|
|
312
|
+
let spacePadding = ' '.repeat(100);
|
|
313
|
+
let exportableRecord = {}
|
|
314
|
+
let sequence = item.order;
|
|
315
|
+
let nameElements = item.name.replace(/[\[\]]/g, '').split(/(SERVER)?-/);
|
|
316
|
+
let threadName = (nameElements[0] + spacePadding).slice(0, 14);
|
|
317
|
+
let processName = (nameElements[1] ? nameElements[1] : item.name + spacePadding).slice(0, 70-(depth*2));
|
|
318
|
+
let totalDuration = formatNumberColumn(item?.totalDuration, 'ONGOING');
|
|
319
|
+
let computeDuration = (/ONGOING/.test(totalDuration)) ? formatNumberColumn('ONGOING', 'ONGOING') : formatNumberColumn(item?.computeDuration);
|
|
320
|
+
let networkLatency = (/ONGOING/.test(totalDuration)) ? formatNumberColumn('ONGOING', 'ONGOING') : formatNumberColumn(item?.networkLatency);
|
|
321
|
+
let cumulativeCompute;
|
|
322
|
+
if(/ONGOING/.test(totalDuration)) cumulativeCompute = formatNumberColumn('ONGOING', 'ONGOING');
|
|
323
|
+
else {
|
|
324
|
+
if(totalDuration < (Math.abs(networkLatency) + Math.abs(computeDuration))) totalDuration = formatNumberColumn(Math.abs(networkLatency) + Math.abs(computeDuration));
|
|
325
|
+
cumulativeCompute = formatNumberColumn((totalDuration - networkLatency - computeDuration), 'ONGOING');
|
|
326
|
+
}
|
|
327
|
+
let indentionPads = depth > 0 ? ' '.repeat(depth-1) + ' ' : ' ';
|
|
328
|
+
let detailPads = depth > 0 ? ' '.repeat(depth-1) + ' '.repeat(threadName.length) + ' ' : ' ' + ' '.repeat(threadName.length);
|
|
329
|
+
let timeSpan = item?.dateTimeStamps ? (' ' + item.dateTimeStamps[0]) : 'N/A';
|
|
330
|
+
|
|
331
|
+
if(!showCSV) {
|
|
332
|
+
let outputLine = ` ${threadName}${indentionPads} ${processName} ${totalDuration} ${networkLatency} ${cumulativeCompute} ${computeDuration} ${timeSpan}`;
|
|
333
|
+
console.groupCollapsed(`%c${outputLine}`, `color: ${outputColors[item.type]}; font-weight: 500;`);
|
|
334
|
+
console.info(`%c${detailPads} Sequence: `, `color: ${outputColors[item.type]}; font-weight: 700;`, sequence);
|
|
335
|
+
console.info(`%c${detailPads} Thread Name: `, `color: ${outputColors[item.type]}; font-weight: 700;`, threadName.trim());
|
|
336
|
+
console.info(`%c${detailPads} Process Name: `, `color: ${outputColors[item.type]}; font-weight: 700;`, processName.trim());
|
|
337
|
+
console.info(`%c${detailPads} Abs. Performance Mark: `, `color: ${outputColors[item.type]}; font-weight: 700;`, (item?.absTime??'') + 'ms from timeOrigin');
|
|
338
|
+
console.info(`%c${detailPads} TimeStamp (Start): `, `color: ${outputColors[item.type]}; font-weight: 700;`, (item?.dateTimeStamps[0]??''));
|
|
339
|
+
console.info(`%c${detailPads} TimeStamp (End): `, `color: ${outputColors[item.type]}; font-weight: 700;`, (item?.dateTimeStamps[1]??''));
|
|
340
|
+
console.info(`%c${detailPads} Cumulative Tot. Duration: `, `color: ${outputColors[item.type]}; font-weight: 700;`, (/ONGOING/.test(totalDuration) ? 'ONGOING' : totalDuration.trim() + 'ms'));
|
|
341
|
+
console.info(`%c${detailPads} Cumulative Network Latency: `, `color: ${outputColors[item.type]}; font-weight: 700;`, (/ONGOING/.test(networkLatency) ? 'ONGOING' : networkLatency.trim() + 'ms'));
|
|
342
|
+
console.info(`%c${detailPads} Cumulative Compute Duration: `, `color: ${outputColors[item.type]}; font-weight: 700;`, (/ONGOING/.test(cumulativeCompute) ? 'ONGOING' : cumulativeCompute.trim() + 'ms'));
|
|
343
|
+
console.info(`%c${detailPads} Process Compute Duration: `, `color: ${outputColors[item.type]}; font-weight: 700;`, (/ONGOING/.test(computeDuration) ? 'ONGOING' : computeDuration.trim() + 'ms'));
|
|
344
|
+
console.info(`%c${detailPads} ================================================================`, `color: ${outputColors[item.type]}; font-weight: 700;`, "\n\n");
|
|
345
|
+
console.groupEnd();
|
|
346
|
+
} else {
|
|
347
|
+
exportableRecord = {
|
|
348
|
+
sequence : sequence,
|
|
349
|
+
threadName : threadName.trim(),
|
|
350
|
+
processName : processName.trim(),
|
|
351
|
+
absTime : (item?.absTime) ? (item.absTime.toFixed(5)) : '',
|
|
352
|
+
totalDuration : (/ONGOING/.test(totalDuration) ? 'ONGOING' : +(totalDuration.trim())),
|
|
353
|
+
networkLatency : (/ONGOING/.test(networkLatency) ? 'ONGOING' : +(networkLatency.trim())),
|
|
354
|
+
cumulativeCompute : (/ONGOING/.test(cumulativeCompute) ? 'ONGOING' : +(cumulativeCompute.trim())),
|
|
355
|
+
computeDuration : (/ONGOING/.test(computeDuration) ? 'ONGOING' : +(computeDuration.trim())),
|
|
356
|
+
startTime : (item?.dateTimeStamps[0]??''),
|
|
357
|
+
endTime : (item?.dateTimeStamps[1]??''),
|
|
358
|
+
spawnsChildren : item?.children ? item.children.length : 0
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
exportableStack.push(exportableRecord);
|
|
362
|
+
}
|
|
363
|
+
if(item.children.length > 0) recursivelyOutputLogsToConsole(item.children, depth + 1);
|
|
364
|
+
});
|
|
365
|
+
return exportableStack.length ? exportableStack : undefined;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
let allLogs = await GLOBAL.getAllLogs(showCSV);
|
|
369
|
+
let processedStack = recursivelyMoveChildLogsIntoStartNode(allLogs);
|
|
370
|
+
processedStack.forEach(root => recursivelyComputeCumulativeNetworkLatency(root));
|
|
371
|
+
processedStack.forEach(root => calculateComputeDurationForNode(root));
|
|
372
|
+
if(!showCSV) console.info(`%c${' THREAD PROCESS NAME DURATION NETWORK TOT.COMP. COMPUTE START TIME'}`, 'color: #000; font-weight: 700;');
|
|
373
|
+
let exportableData = recursivelyOutputLogsToConsole(processedStack);
|
|
374
|
+
if(!showCSV || !exportableData) return;
|
|
375
|
+
let csvData = exportableData.flatMap((log, i) => {
|
|
376
|
+
let retVal = [Object.values(log)];
|
|
377
|
+
retVal[0][0] = i + 1;
|
|
378
|
+
retVal = ['"' + retVal[0].join('","') + '"'];
|
|
379
|
+
if(i === 0) retVal.unshift('"' + Object.keys(log).join('","') + '"');
|
|
380
|
+
return retVal;
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
try {
|
|
384
|
+
GLOBAL.exportCount++;
|
|
385
|
+
console.groupCollapsed(`CSV Data Exported as %c${GLOBAL.sessionStamp}-${(GLOBAL.exportCount)}.csv`, 'color: #F60; font-weight: 700;');
|
|
386
|
+
let blobdtMIME = new Blob([csvData.join('\n')], { type: "text/csv" });
|
|
387
|
+
let url = URL.createObjectURL(blobdtMIME)
|
|
388
|
+
let anchor = document.createElement("a")
|
|
389
|
+
anchor.id = "download"
|
|
390
|
+
anchor.setAttribute("download", `${GLOBAL.sessionStamp}-${(GLOBAL.exportCount)}.csv`);
|
|
391
|
+
anchor.href = url;
|
|
392
|
+
anchor.click();
|
|
393
|
+
console.info(`CSV Data:\n${csvData.join('\n')}\n...EOS`);
|
|
394
|
+
URL.revokeObjectURL(url);
|
|
395
|
+
GLOBAL.logStack = [];
|
|
396
|
+
zsmClient.callWorkerFunction("clearLogs", true);
|
|
397
|
+
console.groupEnd();
|
|
398
|
+
} catch (error) {
|
|
399
|
+
console.error('Error during download:', error);
|
|
400
|
+
console.groupEnd();
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
return exportableData;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
export { UMFAClient, FIDO2Client };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ideem/zsm-client-sdk",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.3.0",
|
|
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": [
|
|
7
7
|
"ideem",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
],
|
|
23
23
|
"scripts": {
|
|
24
24
|
"start": "echo 'This is a library, not an application. No start script defined. To use, import the library.'",
|
|
25
|
-
"inc": "npm version patch && cd ..; sleep 1; npm pack ./
|
|
25
|
+
"inc": "npm version patch && cd ..; sleep 1; npm pack ./pkg_files"
|
|
26
26
|
},
|
|
27
27
|
"collaborators": [
|
|
28
28
|
"Joel Teply <joel@useideem.com>",
|
|
@@ -30,20 +30,25 @@
|
|
|
30
30
|
"Brian Koziel <brian@useideem.com>",
|
|
31
31
|
"@JJ <jj@useideem.com>"
|
|
32
32
|
],
|
|
33
|
-
"main": "zsm-client-sdk.js",
|
|
34
|
-
"module": "zsm-client-sdk.js",
|
|
35
|
-
"browser": "zsm-client-sdk.js",
|
|
36
33
|
"license": "SEE LICENSE IN LICENSE",
|
|
37
34
|
"repository": {
|
|
38
35
|
"type": "git",
|
|
39
|
-
"url": "
|
|
36
|
+
"url": "github:useideem/vHSM"
|
|
40
37
|
},
|
|
41
|
-
"bugs": "https://github.com/useideem/vHSM/issues",
|
|
42
38
|
"homepage": "http://useideem.com",
|
|
39
|
+
"bugs": "https://github.com/useideem/vHSM/issues",
|
|
43
40
|
"files": [
|
|
44
|
-
"
|
|
41
|
+
"worker.js",
|
|
42
|
+
"ZSMClientSDK.js",
|
|
43
|
+
"RELEASE_NOTES.txt",
|
|
44
|
+
"LICENSE",
|
|
45
|
+
"README.md"
|
|
45
46
|
],
|
|
46
47
|
"engines": {
|
|
47
|
-
"node": ">=
|
|
48
|
-
}
|
|
48
|
+
"node": ">=12.0.0"
|
|
49
|
+
},
|
|
50
|
+
"sideEffects": [
|
|
51
|
+
"worker.js",
|
|
52
|
+
"ZSMClientSDK.js"
|
|
53
|
+
]
|
|
49
54
|
}
|