@tern-secure/shared 1.3.0-canary.v20251108045933 → 1.3.0-canary.v20251127221555
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/dist/chunk-2QSK7ZVG.mjs +25 -0
- package/dist/chunk-2QSK7ZVG.mjs.map +1 -0
- package/dist/{chunk-33U3M4YY.mjs → chunk-IGYBIQYE.mjs} +14 -7
- package/dist/chunk-IGYBIQYE.mjs.map +1 -0
- package/dist/chunk-N2V3PKFE.mjs +61 -0
- package/dist/chunk-N2V3PKFE.mjs.map +1 -0
- package/dist/errors.js +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/errors.mjs +1 -1
- package/dist/errors.mjs.map +1 -1
- package/dist/loadScript.js +68 -6
- package/dist/loadScript.js.map +1 -1
- package/dist/loadScript.mjs +2 -1
- package/dist/loadTernUIScript.d.mts +14 -6
- package/dist/loadTernUIScript.d.ts +14 -6
- package/dist/loadTernUIScript.js +122 -29
- package/dist/loadTernUIScript.js.map +1 -1
- package/dist/loadTernUIScript.mjs +43 -23
- package/dist/loadTernUIScript.mjs.map +1 -1
- package/dist/react/index.d.mts +19 -1
- package/dist/react/index.d.ts +19 -1
- package/dist/react/index.js +26 -1
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +23 -1
- package/dist/react/index.mjs.map +1 -1
- package/dist/resolveVersion.d.mts +2 -1
- package/dist/resolveVersion.d.ts +2 -1
- package/dist/resolveVersion.js +16 -2
- package/dist/resolveVersion.js.map +1 -1
- package/dist/resolveVersion.mjs +3 -1
- package/dist/retry.mjs +3 -56
- package/dist/retry.mjs.map +1 -1
- package/dist/url.d.mts +2 -1
- package/dist/url.d.ts +2 -1
- package/dist/url.js +4 -0
- package/dist/url.js.map +1 -1
- package/dist/url.mjs +3 -0
- package/dist/url.mjs.map +1 -1
- package/package.json +3 -2
- package/dist/chunk-33U3M4YY.mjs.map +0 -1
- package/dist/chunk-PHCVLVZY.mjs +0 -12
- package/dist/chunk-PHCVLVZY.mjs.map +0 -1
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// src/resolveVersion.ts
|
|
2
|
+
var resolveVersion = (ternUIVersion, packageVersion = "1.1.0-canary.v20251127221555") => {
|
|
3
|
+
if (ternUIVersion) {
|
|
4
|
+
return ternUIVersion;
|
|
5
|
+
}
|
|
6
|
+
const prereleaseTag = getPrereleaseTag(packageVersion);
|
|
7
|
+
if (prereleaseTag) {
|
|
8
|
+
if (prereleaseTag === "snapshot") {
|
|
9
|
+
return "1.1.0-canary.v20251127221555";
|
|
10
|
+
}
|
|
11
|
+
return prereleaseTag;
|
|
12
|
+
}
|
|
13
|
+
return getMajorVersion(packageVersion);
|
|
14
|
+
};
|
|
15
|
+
var getPrereleaseTag = (packageVersion) => {
|
|
16
|
+
var _a;
|
|
17
|
+
return (_a = packageVersion.trim().replace(/^v/, "").match(/-(.+?)(\.|$)/)) == null ? void 0 : _a[1];
|
|
18
|
+
};
|
|
19
|
+
var getMajorVersion = (packageVersion) => packageVersion.trim().replace(/^v/, "").split(".")[0];
|
|
20
|
+
|
|
21
|
+
export {
|
|
22
|
+
resolveVersion,
|
|
23
|
+
getMajorVersion
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=chunk-2QSK7ZVG.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/resolveVersion.ts"],"sourcesContent":["\nexport const resolveVersion = (ternUIVersion: string | undefined, packageVersion = TERN_UI_VERSION) => {\n if (ternUIVersion) {\n return ternUIVersion\n }\n\n const prereleaseTag = getPrereleaseTag(packageVersion);\n if (prereleaseTag) {\n if (prereleaseTag === 'snapshot') {\n return TERN_UI_VERSION;\n }\n\n return prereleaseTag;\n }\n\n return getMajorVersion(packageVersion);\n}\n\nconst getPrereleaseTag = (packageVersion: string) =>\n packageVersion\n .trim()\n .replace(/^v/, '')\n .match(/-(.+?)(\\.|$)/)?.[1];\n\nexport const getMajorVersion = (packageVersion: string) => packageVersion.trim().replace(/^v/, '').split('.')[0];"],"mappings":";AACO,IAAM,iBAAiB,CAAC,eAAmC,iBAAiB,mCAAoB;AACrG,MAAI,eAAe;AACjB,WAAO;AAAA,EACT;AAEA,QAAM,gBAAgB,iBAAiB,cAAc;AACrD,MAAI,eAAe;AACjB,QAAI,kBAAkB,YAAY;AAChC,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAEA,SAAO,gBAAgB,cAAc;AACvC;AAEA,IAAM,mBAAmB,CAAC,mBAAwB;AAlBlD;AAmBE,8BACG,KAAK,EACL,QAAQ,MAAM,EAAE,EAChB,MAAM,cAAc,MAHvB,mBAG2B;AAAA;AAEtB,IAAM,kBAAkB,CAAC,mBAA2B,eAAe,KAAK,EAAE,QAAQ,MAAM,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;","names":[]}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
retry
|
|
3
|
+
} from "./chunk-N2V3PKFE.mjs";
|
|
4
|
+
|
|
1
5
|
// src/loadScript.ts
|
|
2
6
|
async function loadScript(src = "", options) {
|
|
3
7
|
const { async, defer, crossOrigin, nonce, beforeLoad } = options;
|
|
@@ -25,7 +29,6 @@ async function loadScript(src = "", options) {
|
|
|
25
29
|
};
|
|
26
30
|
const handleLoad = () => {
|
|
27
31
|
if (resolved) return;
|
|
28
|
-
console.log(`[loadScript] Script loaded successfully: ${src}`);
|
|
29
32
|
resolved = true;
|
|
30
33
|
cleanup();
|
|
31
34
|
resolve(script);
|
|
@@ -35,22 +38,26 @@ async function loadScript(src = "", options) {
|
|
|
35
38
|
resolved = true;
|
|
36
39
|
cleanup();
|
|
37
40
|
script.remove();
|
|
38
|
-
console.error(`[loadScript] Failed to load script: ${src}`, error);
|
|
39
41
|
reject(new Error(`Failed to load script: ${src}, Error: ${error.message}`));
|
|
40
42
|
};
|
|
41
|
-
script.addEventListener("load",
|
|
42
|
-
|
|
43
|
+
script.addEventListener("load", () => {
|
|
44
|
+
script.remove();
|
|
45
|
+
resolve(script);
|
|
46
|
+
});
|
|
47
|
+
script.addEventListener("error", () => {
|
|
48
|
+
script.remove();
|
|
49
|
+
reject();
|
|
50
|
+
});
|
|
43
51
|
script.src = src;
|
|
44
52
|
script.nonce = nonce;
|
|
45
53
|
beforeLoad == null ? void 0 : beforeLoad(script);
|
|
46
|
-
console.log(`[loadScript] Appending script to document body: ${src}`);
|
|
47
54
|
document.body.appendChild(script);
|
|
48
55
|
});
|
|
49
56
|
};
|
|
50
|
-
return load();
|
|
57
|
+
return retry(load, { shouldRetry: (_, iterations) => iterations <= 5 });
|
|
51
58
|
}
|
|
52
59
|
|
|
53
60
|
export {
|
|
54
61
|
loadScript
|
|
55
62
|
};
|
|
56
|
-
//# sourceMappingURL=chunk-
|
|
63
|
+
//# sourceMappingURL=chunk-IGYBIQYE.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/loadScript.ts"],"sourcesContent":["import { retry } from './retry';\n\ntype LoadScriptOptions = {\n async?: boolean;\n defer?: boolean;\n crossOrigin?: 'anonymous' | 'use-credentials';\n nonce?: string;\n beforeLoad?: (script: HTMLScriptElement) => void;\n};\n\nexport async function loadScript(src = '', options: LoadScriptOptions): Promise<HTMLScriptElement> {\n const { async, defer, crossOrigin, nonce, beforeLoad } = options;\n\n const load = () => {\n return new Promise<HTMLScriptElement>((resolve, reject) => {\n if (!src) {\n reject(new Error('Script src is required'));\n }\n\n if (!document || !document.body) {\n reject(new Error('Document body is not available'));\n }\n\n const script = document.createElement('script');\n\n if (crossOrigin) script.setAttribute('crossorigin', crossOrigin);\n script.async = async || false;\n script.defer = defer || false;\n\n let resolved = false;\n let timeoutId: NodeJS.Timeout | null = null;\n\n /**\n * @deprecated\n */\n const cleanup = () => {\n script.removeEventListener('load', handleLoad);\n script.removeEventListener('error', handleError);\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n };\n\n /**\n * @deprecated\n */\n const handleLoad = () => {\n if (resolved) return;\n\n resolved = true;\n cleanup();\n resolve(script);\n };\n /**\n * @deprecated\n */\n const handleError = (error: ErrorEvent) => {\n if (resolved) return;\n resolved = true;\n cleanup();\n script.remove();\n reject(new Error(`Failed to load script: ${src}, Error: ${error.message}`));\n };\n\n script.addEventListener('load', () => {\n script.remove()\n resolve(script);\n });\n\n script.addEventListener('error', () => {\n script.remove()\n reject()\n });\n\n script.src = src;\n script.nonce = nonce;\n beforeLoad?.(script);\n document.body.appendChild(script)\n });\n };\n\n //return load()\n\n return retry(load, { shouldRetry: (_, iterations) => iterations <= 5 });\n}"],"mappings":";;;;;AAUA,eAAsB,WAAW,MAAM,IAAI,SAAwD;AACjG,QAAM,EAAE,OAAO,OAAO,aAAa,OAAO,WAAW,IAAI;AAEzD,QAAM,OAAO,MAAM;AACjB,WAAO,IAAI,QAA2B,CAAC,SAAS,WAAW;AACzD,UAAI,CAAC,KAAK;AACR,eAAO,IAAI,MAAM,wBAAwB,CAAC;AAAA,MAC5C;AAEA,UAAI,CAAC,YAAY,CAAC,SAAS,MAAM;AAC/B,eAAO,IAAI,MAAM,gCAAgC,CAAC;AAAA,MACpD;AAEA,YAAM,SAAS,SAAS,cAAc,QAAQ;AAE9C,UAAI,YAAa,QAAO,aAAa,eAAe,WAAW;AAC/D,aAAO,QAAQ,SAAS;AACxB,aAAO,QAAQ,SAAS;AAExB,UAAI,WAAW;AACf,UAAI,YAAmC;AAKvC,YAAM,UAAU,MAAM;AACpB,eAAO,oBAAoB,QAAQ,UAAU;AAC7C,eAAO,oBAAoB,SAAS,WAAW;AAC/C,YAAI,WAAW;AACb,uBAAa,SAAS;AACtB,sBAAY;AAAA,QACd;AAAA,MACF;AAKA,YAAM,aAAa,MAAM;AACvB,YAAI,SAAU;AAEd,mBAAW;AACX,gBAAQ;AACR,gBAAQ,MAAM;AAAA,MAChB;AAIA,YAAM,cAAc,CAAC,UAAsB;AACzC,YAAI,SAAU;AACd,mBAAW;AACX,gBAAQ;AACR,eAAO,OAAO;AACd,eAAO,IAAI,MAAM,0BAA0B,GAAG,YAAY,MAAM,OAAO,EAAE,CAAC;AAAA,MAC5E;AAEA,aAAO,iBAAiB,QAAQ,MAAM;AACpC,eAAO,OAAO;AACd,gBAAQ,MAAM;AAAA,MAChB,CAAC;AAED,aAAO,iBAAiB,SAAS,MAAM;AACrC,eAAO,OAAO;AACd,eAAO;AAAA,MACT,CAAC;AAED,aAAO,MAAM;AACb,aAAO,QAAQ;AACf,+CAAa;AACb,eAAS,KAAK,YAAY,MAAM;AAAA,IAClC,CAAC;AAAA,EACH;AAIA,SAAO,MAAM,MAAM,EAAE,aAAa,CAAC,GAAG,eAAe,cAAc,EAAE,CAAC;AACxE;","names":[]}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// src/retry.ts
|
|
2
|
+
var defaultOptions = {
|
|
3
|
+
initialDelay: 125,
|
|
4
|
+
maxDelayBetweenRetries: 0,
|
|
5
|
+
factor: 2,
|
|
6
|
+
shouldRetry: (_, iteration) => iteration < 5,
|
|
7
|
+
retryImmediately: false,
|
|
8
|
+
jitter: true
|
|
9
|
+
};
|
|
10
|
+
var RETRY_IMMEDIATELY_DELAY = 100;
|
|
11
|
+
var sleep = async (ms) => new Promise((s) => setTimeout(s, ms));
|
|
12
|
+
var applyJitter = (delay, jitter) => {
|
|
13
|
+
return jitter ? delay * (1 + Math.random()) : delay;
|
|
14
|
+
};
|
|
15
|
+
var createExponentialDelayAsyncFn = (opts) => {
|
|
16
|
+
let timesCalled = 0;
|
|
17
|
+
const calculateDelayInMs = () => {
|
|
18
|
+
const constant = opts.initialDelay;
|
|
19
|
+
const base = opts.factor;
|
|
20
|
+
let delay = constant * Math.pow(base, timesCalled);
|
|
21
|
+
delay = applyJitter(delay, opts.jitter);
|
|
22
|
+
return Math.min(opts.maxDelayBetweenRetries || delay, delay);
|
|
23
|
+
};
|
|
24
|
+
return async () => {
|
|
25
|
+
await sleep(calculateDelayInMs());
|
|
26
|
+
timesCalled++;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
var retry = async (callback, options = {}) => {
|
|
30
|
+
let iterations = 0;
|
|
31
|
+
const { shouldRetry, initialDelay, maxDelayBetweenRetries, factor, retryImmediately, jitter } = {
|
|
32
|
+
...defaultOptions,
|
|
33
|
+
...options
|
|
34
|
+
};
|
|
35
|
+
const delay = createExponentialDelayAsyncFn({
|
|
36
|
+
initialDelay,
|
|
37
|
+
maxDelayBetweenRetries,
|
|
38
|
+
factor,
|
|
39
|
+
jitter
|
|
40
|
+
});
|
|
41
|
+
while (true) {
|
|
42
|
+
try {
|
|
43
|
+
return await callback();
|
|
44
|
+
} catch (e) {
|
|
45
|
+
iterations++;
|
|
46
|
+
if (!shouldRetry(e, iterations)) {
|
|
47
|
+
throw e;
|
|
48
|
+
}
|
|
49
|
+
if (retryImmediately && iterations === 1) {
|
|
50
|
+
await sleep(applyJitter(RETRY_IMMEDIATELY_DELAY, jitter));
|
|
51
|
+
} else {
|
|
52
|
+
await delay();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export {
|
|
59
|
+
retry
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=chunk-N2V3PKFE.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/retry.ts"],"sourcesContent":["type Milliseconds = number;\n\ntype RetryOptions = Partial<{\n /**\n * The initial delay before the first retry.\n * @default 125\n */\n initialDelay: Milliseconds;\n /**\n * The maximum delay between retries.\n * The delay between retries will never exceed this value.\n * If set to 0, the delay will increase indefinitely.\n * @default 0\n */\n maxDelayBetweenRetries: Milliseconds;\n /**\n * The multiplier for the exponential backoff.\n * @default 2\n */\n factor: number;\n /**\n * A function to determine if the operation should be retried.\n * The callback accepts the error that was thrown and the number of iterations.\n * The iterations variable references the number of retries AFTER attempt\n * that caused the error and starts at 1 (as in, this is the 1st, 2nd, nth retry).\n * @default (error, iterations) => iterations < 5\n */\n shouldRetry: (error: unknown, iterations: number) => boolean;\n /**\n * Controls whether the helper should retry the operation immediately once before applying exponential backoff.\n * The delay for the immediate retry is 100ms.\n * @default false\n */\n retryImmediately: boolean;\n /**\n * If true, the intervals will be multiplied by a factor in the range of [1,2].\n * @default true\n */\n jitter: boolean;\n}>;\n\nconst defaultOptions: Required<RetryOptions> = {\n initialDelay: 125,\n maxDelayBetweenRetries: 0,\n factor: 2,\n shouldRetry: (_: unknown, iteration: number) => iteration < 5,\n retryImmediately: false,\n jitter: true,\n};\n\nconst RETRY_IMMEDIATELY_DELAY = 100;\n\nconst sleep = async (ms: Milliseconds) => new Promise(s => setTimeout(s, ms));\n\nconst applyJitter = (delay: Milliseconds, jitter: boolean) => {\n return jitter ? delay * (1 + Math.random()) : delay;\n};\n\nconst createExponentialDelayAsyncFn = (\n opts: Required<Pick<RetryOptions, 'initialDelay' | 'maxDelayBetweenRetries' | 'factor' | 'jitter'>>,\n) => {\n let timesCalled = 0;\n\n const calculateDelayInMs = () => {\n const constant = opts.initialDelay;\n const base = opts.factor;\n let delay = constant * Math.pow(base, timesCalled);\n delay = applyJitter(delay, opts.jitter);\n return Math.min(opts.maxDelayBetweenRetries || delay, delay);\n };\n\n return async (): Promise<void> => {\n await sleep(calculateDelayInMs());\n timesCalled++;\n };\n};\n\n/**\n * Retries a callback until it succeeds or the shouldRetry function returns false.\n * See {@link RetryOptions} for the available options.\n */\nexport const retry = async <T>(callback: () => T | Promise<T>, options: RetryOptions = {}): Promise<T> => {\n let iterations = 0;\n const { shouldRetry, initialDelay, maxDelayBetweenRetries, factor, retryImmediately, jitter } = {\n ...defaultOptions,\n ...options,\n };\n\n const delay = createExponentialDelayAsyncFn({\n initialDelay,\n maxDelayBetweenRetries,\n factor,\n jitter,\n });\n\n while (true) {\n try {\n return await callback();\n } catch (e) {\n iterations++;\n if (!shouldRetry(e, iterations)) {\n throw e;\n }\n if (retryImmediately && iterations === 1) {\n await sleep(applyJitter(RETRY_IMMEDIATELY_DELAY, jitter));\n } else {\n await delay();\n }\n }\n }\n};\n"],"mappings":";AAyCA,IAAM,iBAAyC;AAAA,EAC7C,cAAc;AAAA,EACd,wBAAwB;AAAA,EACxB,QAAQ;AAAA,EACR,aAAa,CAAC,GAAY,cAAsB,YAAY;AAAA,EAC5D,kBAAkB;AAAA,EAClB,QAAQ;AACV;AAEA,IAAM,0BAA0B;AAEhC,IAAM,QAAQ,OAAO,OAAqB,IAAI,QAAQ,OAAK,WAAW,GAAG,EAAE,CAAC;AAE5E,IAAM,cAAc,CAAC,OAAqB,WAAoB;AAC5D,SAAO,SAAS,SAAS,IAAI,KAAK,OAAO,KAAK;AAChD;AAEA,IAAM,gCAAgC,CACpC,SACG;AACH,MAAI,cAAc;AAElB,QAAM,qBAAqB,MAAM;AAC/B,UAAM,WAAW,KAAK;AACtB,UAAM,OAAO,KAAK;AAClB,QAAI,QAAQ,WAAW,KAAK,IAAI,MAAM,WAAW;AACjD,YAAQ,YAAY,OAAO,KAAK,MAAM;AACtC,WAAO,KAAK,IAAI,KAAK,0BAA0B,OAAO,KAAK;AAAA,EAC7D;AAEA,SAAO,YAA2B;AAChC,UAAM,MAAM,mBAAmB,CAAC;AAChC;AAAA,EACF;AACF;AAMO,IAAM,QAAQ,OAAU,UAAgC,UAAwB,CAAC,MAAkB;AACxG,MAAI,aAAa;AACjB,QAAM,EAAE,aAAa,cAAc,wBAAwB,QAAQ,kBAAkB,OAAO,IAAI;AAAA,IAC9F,GAAG;AAAA,IACH,GAAG;AAAA,EACL;AAEA,QAAM,QAAQ,8BAA8B;AAAA,IAC1C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAO,MAAM;AACX,QAAI;AACF,aAAO,MAAM,SAAS;AAAA,IACxB,SAAS,GAAG;AACV;AACA,UAAI,CAAC,YAAY,GAAG,UAAU,GAAG;AAC/B,cAAM;AAAA,MACR;AACA,UAAI,oBAAoB,eAAe,GAAG;AACxC,cAAM,MAAM,YAAY,yBAAyB,MAAM,CAAC;AAAA,MAC1D,OAAO;AACL,cAAM,MAAM;AAAA,MACd;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|
package/dist/errors.js
CHANGED
|
@@ -65,7 +65,7 @@ function handleFirebaseAuthError(error) {
|
|
|
65
65
|
"invalid-credential": { message: "Invalid email or password", code: "INVALID_CREDENTIALS" },
|
|
66
66
|
"invalid-login-credentials": { message: "Invalid email or password", code: "INVALID_CREDENTIALS" },
|
|
67
67
|
"wrong-password": { message: "Invalid email or password", code: "INVALID_CREDENTIALS" },
|
|
68
|
-
"user-not-found": { message: "
|
|
68
|
+
"user-not-found": { message: "User not found", code: "USER_NOT_FOUND" },
|
|
69
69
|
"user-disabled": { message: "This account has been disabled", code: "USER_DISABLED" },
|
|
70
70
|
"too-many-requests": { message: "Too many attempts. Please try again later", code: "TOO_MANY_ATTEMPTS" },
|
|
71
71
|
"network-request-failed": { message: "Network error. Please check your connection", code: "NETWORK_ERROR" },
|
package/dist/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts"],"sourcesContent":["import type { AuthErrorResponse, ErrorCode } from \"@tern-secure/types\";\n\n\nexport class TernSecureError extends Error {\n code: ErrorCode\n\n constructor(code: ErrorCode, message?: string) {\n super(message || code)\n this.name = \"TernSecureError\"\n this.code = code\n }\n}\n\n\n/**\n * Handles Firebase authentication errors with multiple fallback mechanisms\n */\nexport function handleFirebaseAuthError(error: unknown): AuthErrorResponse {\n function extractErrorInfo(input: unknown): { code: string; message: string } | null {\n // Case 1: String input (direct Firebase error message)\n if (typeof input === 'string') {\n const match = input.match(/Firebase:\\s*Error\\s*\\(auth\\/([^)]+)\\)/);\n if (match) {\n return { code: match[1], message: input };\n }\n }\n\n // Case 2: Error object\n if (input && typeof input === 'object') {\n const err = input as { code?: string; message?: string };\n \n // Check for bundled message format first\n if (err.message) {\n const match = err.message.match(/Firebase:\\s*Error\\s*\\(auth\\/([^)]+)\\)/);\n if (match) {\n return { code: match[1], message: err.message };\n }\n }\n\n // Check for direct code\n if (err.code) {\n return {\n code: err.code.replace('auth/', ''),\n message: err.message || ''\n };\n }\n }\n\n return null;\n }\n\n // Map error codes to user-friendly messages\n const ERROR_MESSAGES: Record<string, { message: string; code: ErrorCode }> = {\n 'argument-error': { message: 'Method called with incorrect arguments', code: 'INCORRECT_ARGUMENT' },\n 'invalid-email': { message: 'Invalid email format', code: 'INVALID_EMAIL' },\n 'invalid-tenant-id': { message: 'Invalid tenant ID', code: 'INVALID_ARGUMENT' },\n 'invalid-credential': { message: 'Invalid email or password', code: 'INVALID_CREDENTIALS' },\n 'invalid-login-credentials': { message: 'Invalid email or password', code: 'INVALID_CREDENTIALS' },\n 'wrong-password': { message: 'Invalid email or password', code: 'INVALID_CREDENTIALS' },\n 'user-not-found': { message: '
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts"],"sourcesContent":["import type { AuthErrorResponse, ErrorCode } from \"@tern-secure/types\";\n\n\nexport class TernSecureError extends Error {\n code: ErrorCode\n\n constructor(code: ErrorCode, message?: string) {\n super(message || code)\n this.name = \"TernSecureError\"\n this.code = code\n }\n}\n\n\n/**\n * Handles Firebase authentication errors with multiple fallback mechanisms\n */\nexport function handleFirebaseAuthError(error: unknown): AuthErrorResponse {\n function extractErrorInfo(input: unknown): { code: string; message: string } | null {\n // Case 1: String input (direct Firebase error message)\n if (typeof input === 'string') {\n const match = input.match(/Firebase:\\s*Error\\s*\\(auth\\/([^)]+)\\)/);\n if (match) {\n return { code: match[1], message: input };\n }\n }\n\n // Case 2: Error object\n if (input && typeof input === 'object') {\n const err = input as { code?: string; message?: string };\n \n // Check for bundled message format first\n if (err.message) {\n const match = err.message.match(/Firebase:\\s*Error\\s*\\(auth\\/([^)]+)\\)/);\n if (match) {\n return { code: match[1], message: err.message };\n }\n }\n\n // Check for direct code\n if (err.code) {\n return {\n code: err.code.replace('auth/', ''),\n message: err.message || ''\n };\n }\n }\n\n return null;\n }\n\n // Map error codes to user-friendly messages\n const ERROR_MESSAGES: Record<string, { message: string; code: ErrorCode }> = {\n 'argument-error': { message: 'Method called with incorrect arguments', code: 'INCORRECT_ARGUMENT' },\n 'invalid-email': { message: 'Invalid email format', code: 'INVALID_EMAIL' },\n 'invalid-tenant-id': { message: 'Invalid tenant ID', code: 'INVALID_ARGUMENT' },\n 'invalid-credential': { message: 'Invalid email or password', code: 'INVALID_CREDENTIALS' },\n 'invalid-login-credentials': { message: 'Invalid email or password', code: 'INVALID_CREDENTIALS' },\n 'wrong-password': { message: 'Invalid email or password', code: 'INVALID_CREDENTIALS' },\n 'user-not-found': { message: 'User not found', code: 'USER_NOT_FOUND' },\n 'user-disabled': { message: 'This account has been disabled', code: 'USER_DISABLED' },\n 'too-many-requests': { message: 'Too many attempts. Please try again later', code: 'TOO_MANY_ATTEMPTS' },\n 'network-request-failed': { message: 'Network error. Please check your connection', code: 'NETWORK_ERROR' },\n 'email-already-in-use': { message: 'This email is already in use', code: 'EMAIL_EXISTS' },\n 'weak-password': { message: 'Password is too weak', code: 'WEAK_PASSWORD' },\n 'operation-not-allowed': { message: 'This login method is not enabled', code: 'OPERATION_NOT_ALLOWED' },\n 'popup-blocked': { message: 'Login popup was blocked. Please enable popups', code: 'POPUP_BLOCKED' },\n 'expired-action-code': { message: 'Your session has expired. Please login again', code: 'EXPIRED_TOKEN' },\n 'user-token-expired': { message: 'Your session has expired. Please login again', code: 'EXPIRED_TOKEN' },\n 'tenant-not-found': { message: 'There is no tenant corresponding to the provided identifier.', code: 'INVALID_ARGUMENT' },\n };\n\n try {\n // Extract error information\n const errorInfo = extractErrorInfo(error);\n \n if (errorInfo) {\n const mappedError = ERROR_MESSAGES[errorInfo.code];\n if (mappedError) {\n return {\n success: false,\n message: mappedError.message,\n code: mappedError.code\n };\n }\n }\n\n // If we couldn't extract or map the error, try one last time with string conversion\n const errorString = String(error);\n const lastMatch = errorString.match(/Firebase:\\s*Error\\s*\\(auth\\/([^)]+)\\)/);\n if (lastMatch && ERROR_MESSAGES[lastMatch[1]]) {\n return {\n success: false,\n ...ERROR_MESSAGES[lastMatch[1]]\n };\n }\n\n } catch (e) {\n // Silent catch - we'll return the default error\n }\n\n // Default fallback\n return {\n success: false,\n message: 'An unexpected error occurred. Please try again later',\n code: 'INTERNAL_ERROR'\n };\n}\n\n/**\n * Type guard to check if a response is an AuthErrorResponse\n */\nexport function isAuthErrorResponse(response: unknown): response is AuthErrorResponse {\n return (\n typeof response === \"object\" &&\n response !== null &&\n \"success\" in response &&\n (response as { success: boolean }).success === false &&\n \"code\" in response &&\n \"message\" in response\n )\n}\n\nexport function getErrorAlertVariant(error: any | undefined) {\n if (!error) return \"destructive\"\n\n switch (error.error) {\n case \"AUTHENTICATED\":\n return \"default\"\n case \"EMAIL_EXISTS\":\n case \"UNAUTHENTICATED\":\n case \"UNVERIFIED\":\n case \"REQUIRES_VERIFICATION\":\n case \"INVALID_EMAIL\":\n case \"INVALID_TOKEN\":\n case \"INTERNAL_ERROR\":\n case \"USER_DISABLED\":\n case \"TOO_MANY_ATTEMPTS\":\n case \"NETWORK_ERROR\":\n case \"SESSION_EXPIRED\":\n case \"EXPIRED_TOKEN\":\n case \"INVALID_CREDENTIALS\":\n default:\n return \"destructive\"\n }\n}"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EAGzC,YAAY,MAAiB,SAAkB;AAC7C,UAAM,WAAW,IAAI;AACrB,SAAK,OAAO;AACZ,SAAK,OAAO;AAAA,EACd;AACF;AAMO,SAAS,wBAAwB,OAAmC;AACzE,WAAS,iBAAiB,OAA0D;AAElF,QAAI,OAAO,UAAU,UAAU;AAC7B,YAAM,QAAQ,MAAM,MAAM,uCAAuC;AACjE,UAAI,OAAO;AACT,eAAO,EAAE,MAAM,MAAM,CAAC,GAAG,SAAS,MAAM;AAAA,MAC1C;AAAA,IACF;AAGA,QAAI,SAAS,OAAO,UAAU,UAAU;AACtC,YAAM,MAAM;AAGZ,UAAI,IAAI,SAAS;AACf,cAAM,QAAQ,IAAI,QAAQ,MAAM,uCAAuC;AACvE,YAAI,OAAO;AACT,iBAAO,EAAE,MAAM,MAAM,CAAC,GAAG,SAAS,IAAI,QAAQ;AAAA,QAChD;AAAA,MACF;AAGA,UAAI,IAAI,MAAM;AACZ,eAAO;AAAA,UACL,MAAM,IAAI,KAAK,QAAQ,SAAS,EAAE;AAAA,UAClC,SAAS,IAAI,WAAW;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAGA,QAAM,iBAAuE;AAAA,IAC3E,kBAAkB,EAAE,SAAS,0CAA0C,MAAM,qBAAqB;AAAA,IAClG,iBAAiB,EAAE,SAAS,wBAAwB,MAAM,gBAAgB;AAAA,IAC1E,qBAAqB,EAAE,SAAS,qBAAqB,MAAM,mBAAmB;AAAA,IAC9E,sBAAsB,EAAE,SAAS,6BAA6B,MAAM,sBAAsB;AAAA,IAC1F,6BAA6B,EAAE,SAAS,6BAA6B,MAAM,sBAAsB;AAAA,IACjG,kBAAkB,EAAE,SAAS,6BAA6B,MAAM,sBAAsB;AAAA,IACtF,kBAAkB,EAAE,SAAS,kBAAkB,MAAM,iBAAiB;AAAA,IACtE,iBAAiB,EAAE,SAAS,kCAAkC,MAAM,gBAAgB;AAAA,IACpF,qBAAqB,EAAE,SAAS,6CAA6C,MAAM,oBAAoB;AAAA,IACvG,0BAA0B,EAAE,SAAS,+CAA+C,MAAM,gBAAgB;AAAA,IAC1G,wBAAwB,EAAE,SAAS,gCAAgC,MAAM,eAAe;AAAA,IACxF,iBAAiB,EAAE,SAAS,wBAAwB,MAAM,gBAAgB;AAAA,IAC1E,yBAAyB,EAAE,SAAS,oCAAoC,MAAM,wBAAwB;AAAA,IACtG,iBAAiB,EAAE,SAAS,iDAAiD,MAAM,gBAAgB;AAAA,IACnG,uBAAuB,EAAE,SAAS,gDAAgD,MAAM,gBAAgB;AAAA,IACxG,sBAAsB,EAAE,SAAS,gDAAgD,MAAM,gBAAgB;AAAA,IACvG,oBAAoB,EAAE,SAAS,gEAAgE,MAAM,mBAAmB;AAAA,EAC1H;AAEA,MAAI;AAEF,UAAM,YAAY,iBAAiB,KAAK;AAExC,QAAI,WAAW;AACb,YAAM,cAAc,eAAe,UAAU,IAAI;AACjD,UAAI,aAAa;AACf,eAAO;AAAA,UACL,SAAS;AAAA,UACT,SAAS,YAAY;AAAA,UACrB,MAAM,YAAY;AAAA,QACpB;AAAA,MACF;AAAA,IACF;AAGA,UAAM,cAAc,OAAO,KAAK;AAChC,UAAM,YAAY,YAAY,MAAM,uCAAuC;AAC3E,QAAI,aAAa,eAAe,UAAU,CAAC,CAAC,GAAG;AAC7C,aAAO;AAAA,QACL,SAAS;AAAA,QACT,GAAG,eAAe,UAAU,CAAC,CAAC;AAAA,MAChC;AAAA,IACF;AAAA,EAEF,SAAS,GAAG;AAAA,EAEZ;AAGA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,SAAS;AAAA,IACT,MAAM;AAAA,EACR;AACF;AAKO,SAAS,oBAAoB,UAAkD;AACpF,SACE,OAAO,aAAa,YACpB,aAAa,QACb,aAAa,YACZ,SAAkC,YAAY,SAC/C,UAAU,YACV,aAAa;AAEjB;AAEO,SAAS,qBAAqB,OAAwB;AAC5D,MAAI,CAAC,MAAO,QAAO;AAElB,UAAQ,MAAM,OAAO;AAAA,IACnB,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL;AACE,aAAO;AAAA,EACX;AACF;","names":[]}
|
package/dist/errors.mjs
CHANGED
|
@@ -38,7 +38,7 @@ function handleFirebaseAuthError(error) {
|
|
|
38
38
|
"invalid-credential": { message: "Invalid email or password", code: "INVALID_CREDENTIALS" },
|
|
39
39
|
"invalid-login-credentials": { message: "Invalid email or password", code: "INVALID_CREDENTIALS" },
|
|
40
40
|
"wrong-password": { message: "Invalid email or password", code: "INVALID_CREDENTIALS" },
|
|
41
|
-
"user-not-found": { message: "
|
|
41
|
+
"user-not-found": { message: "User not found", code: "USER_NOT_FOUND" },
|
|
42
42
|
"user-disabled": { message: "This account has been disabled", code: "USER_DISABLED" },
|
|
43
43
|
"too-many-requests": { message: "Too many attempts. Please try again later", code: "TOO_MANY_ATTEMPTS" },
|
|
44
44
|
"network-request-failed": { message: "Network error. Please check your connection", code: "NETWORK_ERROR" },
|
package/dist/errors.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts"],"sourcesContent":["import type { AuthErrorResponse, ErrorCode } from \"@tern-secure/types\";\n\n\nexport class TernSecureError extends Error {\n code: ErrorCode\n\n constructor(code: ErrorCode, message?: string) {\n super(message || code)\n this.name = \"TernSecureError\"\n this.code = code\n }\n}\n\n\n/**\n * Handles Firebase authentication errors with multiple fallback mechanisms\n */\nexport function handleFirebaseAuthError(error: unknown): AuthErrorResponse {\n function extractErrorInfo(input: unknown): { code: string; message: string } | null {\n // Case 1: String input (direct Firebase error message)\n if (typeof input === 'string') {\n const match = input.match(/Firebase:\\s*Error\\s*\\(auth\\/([^)]+)\\)/);\n if (match) {\n return { code: match[1], message: input };\n }\n }\n\n // Case 2: Error object\n if (input && typeof input === 'object') {\n const err = input as { code?: string; message?: string };\n \n // Check for bundled message format first\n if (err.message) {\n const match = err.message.match(/Firebase:\\s*Error\\s*\\(auth\\/([^)]+)\\)/);\n if (match) {\n return { code: match[1], message: err.message };\n }\n }\n\n // Check for direct code\n if (err.code) {\n return {\n code: err.code.replace('auth/', ''),\n message: err.message || ''\n };\n }\n }\n\n return null;\n }\n\n // Map error codes to user-friendly messages\n const ERROR_MESSAGES: Record<string, { message: string; code: ErrorCode }> = {\n 'argument-error': { message: 'Method called with incorrect arguments', code: 'INCORRECT_ARGUMENT' },\n 'invalid-email': { message: 'Invalid email format', code: 'INVALID_EMAIL' },\n 'invalid-tenant-id': { message: 'Invalid tenant ID', code: 'INVALID_ARGUMENT' },\n 'invalid-credential': { message: 'Invalid email or password', code: 'INVALID_CREDENTIALS' },\n 'invalid-login-credentials': { message: 'Invalid email or password', code: 'INVALID_CREDENTIALS' },\n 'wrong-password': { message: 'Invalid email or password', code: 'INVALID_CREDENTIALS' },\n 'user-not-found': { message: '
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts"],"sourcesContent":["import type { AuthErrorResponse, ErrorCode } from \"@tern-secure/types\";\n\n\nexport class TernSecureError extends Error {\n code: ErrorCode\n\n constructor(code: ErrorCode, message?: string) {\n super(message || code)\n this.name = \"TernSecureError\"\n this.code = code\n }\n}\n\n\n/**\n * Handles Firebase authentication errors with multiple fallback mechanisms\n */\nexport function handleFirebaseAuthError(error: unknown): AuthErrorResponse {\n function extractErrorInfo(input: unknown): { code: string; message: string } | null {\n // Case 1: String input (direct Firebase error message)\n if (typeof input === 'string') {\n const match = input.match(/Firebase:\\s*Error\\s*\\(auth\\/([^)]+)\\)/);\n if (match) {\n return { code: match[1], message: input };\n }\n }\n\n // Case 2: Error object\n if (input && typeof input === 'object') {\n const err = input as { code?: string; message?: string };\n \n // Check for bundled message format first\n if (err.message) {\n const match = err.message.match(/Firebase:\\s*Error\\s*\\(auth\\/([^)]+)\\)/);\n if (match) {\n return { code: match[1], message: err.message };\n }\n }\n\n // Check for direct code\n if (err.code) {\n return {\n code: err.code.replace('auth/', ''),\n message: err.message || ''\n };\n }\n }\n\n return null;\n }\n\n // Map error codes to user-friendly messages\n const ERROR_MESSAGES: Record<string, { message: string; code: ErrorCode }> = {\n 'argument-error': { message: 'Method called with incorrect arguments', code: 'INCORRECT_ARGUMENT' },\n 'invalid-email': { message: 'Invalid email format', code: 'INVALID_EMAIL' },\n 'invalid-tenant-id': { message: 'Invalid tenant ID', code: 'INVALID_ARGUMENT' },\n 'invalid-credential': { message: 'Invalid email or password', code: 'INVALID_CREDENTIALS' },\n 'invalid-login-credentials': { message: 'Invalid email or password', code: 'INVALID_CREDENTIALS' },\n 'wrong-password': { message: 'Invalid email or password', code: 'INVALID_CREDENTIALS' },\n 'user-not-found': { message: 'User not found', code: 'USER_NOT_FOUND' },\n 'user-disabled': { message: 'This account has been disabled', code: 'USER_DISABLED' },\n 'too-many-requests': { message: 'Too many attempts. Please try again later', code: 'TOO_MANY_ATTEMPTS' },\n 'network-request-failed': { message: 'Network error. Please check your connection', code: 'NETWORK_ERROR' },\n 'email-already-in-use': { message: 'This email is already in use', code: 'EMAIL_EXISTS' },\n 'weak-password': { message: 'Password is too weak', code: 'WEAK_PASSWORD' },\n 'operation-not-allowed': { message: 'This login method is not enabled', code: 'OPERATION_NOT_ALLOWED' },\n 'popup-blocked': { message: 'Login popup was blocked. Please enable popups', code: 'POPUP_BLOCKED' },\n 'expired-action-code': { message: 'Your session has expired. Please login again', code: 'EXPIRED_TOKEN' },\n 'user-token-expired': { message: 'Your session has expired. Please login again', code: 'EXPIRED_TOKEN' },\n 'tenant-not-found': { message: 'There is no tenant corresponding to the provided identifier.', code: 'INVALID_ARGUMENT' },\n };\n\n try {\n // Extract error information\n const errorInfo = extractErrorInfo(error);\n \n if (errorInfo) {\n const mappedError = ERROR_MESSAGES[errorInfo.code];\n if (mappedError) {\n return {\n success: false,\n message: mappedError.message,\n code: mappedError.code\n };\n }\n }\n\n // If we couldn't extract or map the error, try one last time with string conversion\n const errorString = String(error);\n const lastMatch = errorString.match(/Firebase:\\s*Error\\s*\\(auth\\/([^)]+)\\)/);\n if (lastMatch && ERROR_MESSAGES[lastMatch[1]]) {\n return {\n success: false,\n ...ERROR_MESSAGES[lastMatch[1]]\n };\n }\n\n } catch (e) {\n // Silent catch - we'll return the default error\n }\n\n // Default fallback\n return {\n success: false,\n message: 'An unexpected error occurred. Please try again later',\n code: 'INTERNAL_ERROR'\n };\n}\n\n/**\n * Type guard to check if a response is an AuthErrorResponse\n */\nexport function isAuthErrorResponse(response: unknown): response is AuthErrorResponse {\n return (\n typeof response === \"object\" &&\n response !== null &&\n \"success\" in response &&\n (response as { success: boolean }).success === false &&\n \"code\" in response &&\n \"message\" in response\n )\n}\n\nexport function getErrorAlertVariant(error: any | undefined) {\n if (!error) return \"destructive\"\n\n switch (error.error) {\n case \"AUTHENTICATED\":\n return \"default\"\n case \"EMAIL_EXISTS\":\n case \"UNAUTHENTICATED\":\n case \"UNVERIFIED\":\n case \"REQUIRES_VERIFICATION\":\n case \"INVALID_EMAIL\":\n case \"INVALID_TOKEN\":\n case \"INTERNAL_ERROR\":\n case \"USER_DISABLED\":\n case \"TOO_MANY_ATTEMPTS\":\n case \"NETWORK_ERROR\":\n case \"SESSION_EXPIRED\":\n case \"EXPIRED_TOKEN\":\n case \"INVALID_CREDENTIALS\":\n default:\n return \"destructive\"\n }\n}"],"mappings":"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","names":[]}
|
package/dist/loadScript.js
CHANGED
|
@@ -23,6 +23,65 @@ __export(loadScript_exports, {
|
|
|
23
23
|
loadScript: () => loadScript
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(loadScript_exports);
|
|
26
|
+
|
|
27
|
+
// src/retry.ts
|
|
28
|
+
var defaultOptions = {
|
|
29
|
+
initialDelay: 125,
|
|
30
|
+
maxDelayBetweenRetries: 0,
|
|
31
|
+
factor: 2,
|
|
32
|
+
shouldRetry: (_, iteration) => iteration < 5,
|
|
33
|
+
retryImmediately: false,
|
|
34
|
+
jitter: true
|
|
35
|
+
};
|
|
36
|
+
var RETRY_IMMEDIATELY_DELAY = 100;
|
|
37
|
+
var sleep = async (ms) => new Promise((s) => setTimeout(s, ms));
|
|
38
|
+
var applyJitter = (delay, jitter) => {
|
|
39
|
+
return jitter ? delay * (1 + Math.random()) : delay;
|
|
40
|
+
};
|
|
41
|
+
var createExponentialDelayAsyncFn = (opts) => {
|
|
42
|
+
let timesCalled = 0;
|
|
43
|
+
const calculateDelayInMs = () => {
|
|
44
|
+
const constant = opts.initialDelay;
|
|
45
|
+
const base = opts.factor;
|
|
46
|
+
let delay = constant * Math.pow(base, timesCalled);
|
|
47
|
+
delay = applyJitter(delay, opts.jitter);
|
|
48
|
+
return Math.min(opts.maxDelayBetweenRetries || delay, delay);
|
|
49
|
+
};
|
|
50
|
+
return async () => {
|
|
51
|
+
await sleep(calculateDelayInMs());
|
|
52
|
+
timesCalled++;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
var retry = async (callback, options = {}) => {
|
|
56
|
+
let iterations = 0;
|
|
57
|
+
const { shouldRetry, initialDelay, maxDelayBetweenRetries, factor, retryImmediately, jitter } = {
|
|
58
|
+
...defaultOptions,
|
|
59
|
+
...options
|
|
60
|
+
};
|
|
61
|
+
const delay = createExponentialDelayAsyncFn({
|
|
62
|
+
initialDelay,
|
|
63
|
+
maxDelayBetweenRetries,
|
|
64
|
+
factor,
|
|
65
|
+
jitter
|
|
66
|
+
});
|
|
67
|
+
while (true) {
|
|
68
|
+
try {
|
|
69
|
+
return await callback();
|
|
70
|
+
} catch (e) {
|
|
71
|
+
iterations++;
|
|
72
|
+
if (!shouldRetry(e, iterations)) {
|
|
73
|
+
throw e;
|
|
74
|
+
}
|
|
75
|
+
if (retryImmediately && iterations === 1) {
|
|
76
|
+
await sleep(applyJitter(RETRY_IMMEDIATELY_DELAY, jitter));
|
|
77
|
+
} else {
|
|
78
|
+
await delay();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// src/loadScript.ts
|
|
26
85
|
async function loadScript(src = "", options) {
|
|
27
86
|
const { async, defer, crossOrigin, nonce, beforeLoad } = options;
|
|
28
87
|
const load = () => {
|
|
@@ -49,7 +108,6 @@ async function loadScript(src = "", options) {
|
|
|
49
108
|
};
|
|
50
109
|
const handleLoad = () => {
|
|
51
110
|
if (resolved) return;
|
|
52
|
-
console.log(`[loadScript] Script loaded successfully: ${src}`);
|
|
53
111
|
resolved = true;
|
|
54
112
|
cleanup();
|
|
55
113
|
resolve(script);
|
|
@@ -59,19 +117,23 @@ async function loadScript(src = "", options) {
|
|
|
59
117
|
resolved = true;
|
|
60
118
|
cleanup();
|
|
61
119
|
script.remove();
|
|
62
|
-
console.error(`[loadScript] Failed to load script: ${src}`, error);
|
|
63
120
|
reject(new Error(`Failed to load script: ${src}, Error: ${error.message}`));
|
|
64
121
|
};
|
|
65
|
-
script.addEventListener("load",
|
|
66
|
-
|
|
122
|
+
script.addEventListener("load", () => {
|
|
123
|
+
script.remove();
|
|
124
|
+
resolve(script);
|
|
125
|
+
});
|
|
126
|
+
script.addEventListener("error", () => {
|
|
127
|
+
script.remove();
|
|
128
|
+
reject();
|
|
129
|
+
});
|
|
67
130
|
script.src = src;
|
|
68
131
|
script.nonce = nonce;
|
|
69
132
|
beforeLoad == null ? void 0 : beforeLoad(script);
|
|
70
|
-
console.log(`[loadScript] Appending script to document body: ${src}`);
|
|
71
133
|
document.body.appendChild(script);
|
|
72
134
|
});
|
|
73
135
|
};
|
|
74
|
-
return load();
|
|
136
|
+
return retry(load, { shouldRetry: (_, iterations) => iterations <= 5 });
|
|
75
137
|
}
|
|
76
138
|
// Annotate the CommonJS export names for ESM import in node:
|
|
77
139
|
0 && (module.exports = {
|
package/dist/loadScript.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/loadScript.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../src/loadScript.ts","../src/retry.ts"],"sourcesContent":["import { retry } from './retry';\n\ntype LoadScriptOptions = {\n async?: boolean;\n defer?: boolean;\n crossOrigin?: 'anonymous' | 'use-credentials';\n nonce?: string;\n beforeLoad?: (script: HTMLScriptElement) => void;\n};\n\nexport async function loadScript(src = '', options: LoadScriptOptions): Promise<HTMLScriptElement> {\n const { async, defer, crossOrigin, nonce, beforeLoad } = options;\n\n const load = () => {\n return new Promise<HTMLScriptElement>((resolve, reject) => {\n if (!src) {\n reject(new Error('Script src is required'));\n }\n\n if (!document || !document.body) {\n reject(new Error('Document body is not available'));\n }\n\n const script = document.createElement('script');\n\n if (crossOrigin) script.setAttribute('crossorigin', crossOrigin);\n script.async = async || false;\n script.defer = defer || false;\n\n let resolved = false;\n let timeoutId: NodeJS.Timeout | null = null;\n\n /**\n * @deprecated\n */\n const cleanup = () => {\n script.removeEventListener('load', handleLoad);\n script.removeEventListener('error', handleError);\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n };\n\n /**\n * @deprecated\n */\n const handleLoad = () => {\n if (resolved) return;\n\n resolved = true;\n cleanup();\n resolve(script);\n };\n /**\n * @deprecated\n */\n const handleError = (error: ErrorEvent) => {\n if (resolved) return;\n resolved = true;\n cleanup();\n script.remove();\n reject(new Error(`Failed to load script: ${src}, Error: ${error.message}`));\n };\n\n script.addEventListener('load', () => {\n script.remove()\n resolve(script);\n });\n\n script.addEventListener('error', () => {\n script.remove()\n reject()\n });\n\n script.src = src;\n script.nonce = nonce;\n beforeLoad?.(script);\n document.body.appendChild(script)\n });\n };\n\n //return load()\n\n return retry(load, { shouldRetry: (_, iterations) => iterations <= 5 });\n}","type Milliseconds = number;\n\ntype RetryOptions = Partial<{\n /**\n * The initial delay before the first retry.\n * @default 125\n */\n initialDelay: Milliseconds;\n /**\n * The maximum delay between retries.\n * The delay between retries will never exceed this value.\n * If set to 0, the delay will increase indefinitely.\n * @default 0\n */\n maxDelayBetweenRetries: Milliseconds;\n /**\n * The multiplier for the exponential backoff.\n * @default 2\n */\n factor: number;\n /**\n * A function to determine if the operation should be retried.\n * The callback accepts the error that was thrown and the number of iterations.\n * The iterations variable references the number of retries AFTER attempt\n * that caused the error and starts at 1 (as in, this is the 1st, 2nd, nth retry).\n * @default (error, iterations) => iterations < 5\n */\n shouldRetry: (error: unknown, iterations: number) => boolean;\n /**\n * Controls whether the helper should retry the operation immediately once before applying exponential backoff.\n * The delay for the immediate retry is 100ms.\n * @default false\n */\n retryImmediately: boolean;\n /**\n * If true, the intervals will be multiplied by a factor in the range of [1,2].\n * @default true\n */\n jitter: boolean;\n}>;\n\nconst defaultOptions: Required<RetryOptions> = {\n initialDelay: 125,\n maxDelayBetweenRetries: 0,\n factor: 2,\n shouldRetry: (_: unknown, iteration: number) => iteration < 5,\n retryImmediately: false,\n jitter: true,\n};\n\nconst RETRY_IMMEDIATELY_DELAY = 100;\n\nconst sleep = async (ms: Milliseconds) => new Promise(s => setTimeout(s, ms));\n\nconst applyJitter = (delay: Milliseconds, jitter: boolean) => {\n return jitter ? delay * (1 + Math.random()) : delay;\n};\n\nconst createExponentialDelayAsyncFn = (\n opts: Required<Pick<RetryOptions, 'initialDelay' | 'maxDelayBetweenRetries' | 'factor' | 'jitter'>>,\n) => {\n let timesCalled = 0;\n\n const calculateDelayInMs = () => {\n const constant = opts.initialDelay;\n const base = opts.factor;\n let delay = constant * Math.pow(base, timesCalled);\n delay = applyJitter(delay, opts.jitter);\n return Math.min(opts.maxDelayBetweenRetries || delay, delay);\n };\n\n return async (): Promise<void> => {\n await sleep(calculateDelayInMs());\n timesCalled++;\n };\n};\n\n/**\n * Retries a callback until it succeeds or the shouldRetry function returns false.\n * See {@link RetryOptions} for the available options.\n */\nexport const retry = async <T>(callback: () => T | Promise<T>, options: RetryOptions = {}): Promise<T> => {\n let iterations = 0;\n const { shouldRetry, initialDelay, maxDelayBetweenRetries, factor, retryImmediately, jitter } = {\n ...defaultOptions,\n ...options,\n };\n\n const delay = createExponentialDelayAsyncFn({\n initialDelay,\n maxDelayBetweenRetries,\n factor,\n jitter,\n });\n\n while (true) {\n try {\n return await callback();\n } catch (e) {\n iterations++;\n if (!shouldRetry(e, iterations)) {\n throw e;\n }\n if (retryImmediately && iterations === 1) {\n await sleep(applyJitter(RETRY_IMMEDIATELY_DELAY, jitter));\n } else {\n await delay();\n }\n }\n }\n};\n"],"mappings":"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","names":[]}
|
package/dist/loadScript.mjs
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TernSecureAuthOptions, TernSecureSDK } from '@tern-secure/types';
|
|
2
2
|
|
|
3
|
-
type LoadTernUISCriptOptions =
|
|
3
|
+
type LoadTernUISCriptOptions = TernSecureAuthOptions & {
|
|
4
4
|
apiKey?: string;
|
|
5
|
-
|
|
5
|
+
apiUrl?: string;
|
|
6
|
+
authDomain?: string;
|
|
6
7
|
proxyUrl?: string;
|
|
8
|
+
ternUIUrl?: string;
|
|
7
9
|
ternUIVersion?: string;
|
|
8
10
|
sdkMetadata?: TernSecureSDK;
|
|
9
11
|
scriptHost?: string;
|
|
@@ -12,11 +14,17 @@ type LoadTernUISCriptOptions = TernSecureInstanceTreeOptions & {
|
|
|
12
14
|
};
|
|
13
15
|
declare const loadTernUIScript: (options?: LoadTernUISCriptOptions) => Promise<unknown>;
|
|
14
16
|
declare const ternUIgetScriptUrl: (options: LoadTernUISCriptOptions) => string;
|
|
17
|
+
/**
|
|
18
|
+
* @deprecated Use constructTernUIScriptAttributes instead
|
|
19
|
+
*/
|
|
15
20
|
declare const constructScriptAttributes: (options?: LoadTernUISCriptOptions) => {
|
|
16
21
|
nonce?: string | undefined;
|
|
17
|
-
'data-domain': string;
|
|
22
|
+
'data-auth-domain': string;
|
|
18
23
|
'data-apikey': string;
|
|
19
|
-
'data-
|
|
24
|
+
'data-api-url': string;
|
|
25
|
+
'data-proxy-url': string;
|
|
20
26
|
};
|
|
27
|
+
declare const constructTernUIScriptAttributes: (options: LoadTernUISCriptOptions) => Record<string, string>;
|
|
28
|
+
declare const applyLoadWithOptions: (options: LoadTernUISCriptOptions) => (script: HTMLScriptElement) => void;
|
|
21
29
|
|
|
22
|
-
export { type LoadTernUISCriptOptions, constructScriptAttributes, loadTernUIScript, ternUIgetScriptUrl };
|
|
30
|
+
export { type LoadTernUISCriptOptions, applyLoadWithOptions, constructScriptAttributes, constructTernUIScriptAttributes, loadTernUIScript, ternUIgetScriptUrl };
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TernSecureAuthOptions, TernSecureSDK } from '@tern-secure/types';
|
|
2
2
|
|
|
3
|
-
type LoadTernUISCriptOptions =
|
|
3
|
+
type LoadTernUISCriptOptions = TernSecureAuthOptions & {
|
|
4
4
|
apiKey?: string;
|
|
5
|
-
|
|
5
|
+
apiUrl?: string;
|
|
6
|
+
authDomain?: string;
|
|
6
7
|
proxyUrl?: string;
|
|
8
|
+
ternUIUrl?: string;
|
|
7
9
|
ternUIVersion?: string;
|
|
8
10
|
sdkMetadata?: TernSecureSDK;
|
|
9
11
|
scriptHost?: string;
|
|
@@ -12,11 +14,17 @@ type LoadTernUISCriptOptions = TernSecureInstanceTreeOptions & {
|
|
|
12
14
|
};
|
|
13
15
|
declare const loadTernUIScript: (options?: LoadTernUISCriptOptions) => Promise<unknown>;
|
|
14
16
|
declare const ternUIgetScriptUrl: (options: LoadTernUISCriptOptions) => string;
|
|
17
|
+
/**
|
|
18
|
+
* @deprecated Use constructTernUIScriptAttributes instead
|
|
19
|
+
*/
|
|
15
20
|
declare const constructScriptAttributes: (options?: LoadTernUISCriptOptions) => {
|
|
16
21
|
nonce?: string | undefined;
|
|
17
|
-
'data-domain': string;
|
|
22
|
+
'data-auth-domain': string;
|
|
18
23
|
'data-apikey': string;
|
|
19
|
-
'data-
|
|
24
|
+
'data-api-url': string;
|
|
25
|
+
'data-proxy-url': string;
|
|
20
26
|
};
|
|
27
|
+
declare const constructTernUIScriptAttributes: (options: LoadTernUISCriptOptions) => Record<string, string>;
|
|
28
|
+
declare const applyLoadWithOptions: (options: LoadTernUISCriptOptions) => (script: HTMLScriptElement) => void;
|
|
21
29
|
|
|
22
|
-
export { type LoadTernUISCriptOptions, constructScriptAttributes, loadTernUIScript, ternUIgetScriptUrl };
|
|
30
|
+
export { type LoadTernUISCriptOptions, applyLoadWithOptions, constructScriptAttributes, constructTernUIScriptAttributes, loadTernUIScript, ternUIgetScriptUrl };
|