@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.
Files changed (42) hide show
  1. package/dist/chunk-2QSK7ZVG.mjs +25 -0
  2. package/dist/chunk-2QSK7ZVG.mjs.map +1 -0
  3. package/dist/{chunk-33U3M4YY.mjs → chunk-IGYBIQYE.mjs} +14 -7
  4. package/dist/chunk-IGYBIQYE.mjs.map +1 -0
  5. package/dist/chunk-N2V3PKFE.mjs +61 -0
  6. package/dist/chunk-N2V3PKFE.mjs.map +1 -0
  7. package/dist/errors.js +1 -1
  8. package/dist/errors.js.map +1 -1
  9. package/dist/errors.mjs +1 -1
  10. package/dist/errors.mjs.map +1 -1
  11. package/dist/loadScript.js +68 -6
  12. package/dist/loadScript.js.map +1 -1
  13. package/dist/loadScript.mjs +2 -1
  14. package/dist/loadTernUIScript.d.mts +14 -6
  15. package/dist/loadTernUIScript.d.ts +14 -6
  16. package/dist/loadTernUIScript.js +122 -29
  17. package/dist/loadTernUIScript.js.map +1 -1
  18. package/dist/loadTernUIScript.mjs +43 -23
  19. package/dist/loadTernUIScript.mjs.map +1 -1
  20. package/dist/react/index.d.mts +19 -1
  21. package/dist/react/index.d.ts +19 -1
  22. package/dist/react/index.js +26 -1
  23. package/dist/react/index.js.map +1 -1
  24. package/dist/react/index.mjs +23 -1
  25. package/dist/react/index.mjs.map +1 -1
  26. package/dist/resolveVersion.d.mts +2 -1
  27. package/dist/resolveVersion.d.ts +2 -1
  28. package/dist/resolveVersion.js +16 -2
  29. package/dist/resolveVersion.js.map +1 -1
  30. package/dist/resolveVersion.mjs +3 -1
  31. package/dist/retry.mjs +3 -56
  32. package/dist/retry.mjs.map +1 -1
  33. package/dist/url.d.mts +2 -1
  34. package/dist/url.d.ts +2 -1
  35. package/dist/url.js +4 -0
  36. package/dist/url.js.map +1 -1
  37. package/dist/url.mjs +3 -0
  38. package/dist/url.mjs.map +1 -1
  39. package/package.json +3 -2
  40. package/dist/chunk-33U3M4YY.mjs.map +0 -1
  41. package/dist/chunk-PHCVLVZY.mjs +0 -12
  42. 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", handleLoad);
42
- script.addEventListener("error", handleError);
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-33U3M4YY.mjs.map
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: "Invalid email or password", code: "INVALID_CREDENTIALS" },
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" },
@@ -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: 'Invalid email or password', code: 'INVALID_CREDENTIALS' },\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":[]}
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/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: "Invalid email or password", code: "INVALID_CREDENTIALS" },
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" },
@@ -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: 'Invalid email or password', code: 'INVALID_CREDENTIALS' },\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":[]}
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":[]}
@@ -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", handleLoad);
66
- script.addEventListener("error", handleError);
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 = {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/loadScript.ts"],"sourcesContent":["type LoadScriptOptions = {\n async?: boolean;\n defer?: boolean;\n crossOrigin?: 'anonymous' | 'use-credentials';\n nonce?: string;\n beforeLoad?: (script: HTMLScriptElement) => void;\n };\n\n export 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 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 const handleLoad = () => {\n if (resolved) return;\n console.log(`[loadScript] Script loaded successfully: ${src}`);\n\n resolved = true;\n cleanup();\n resolve(script);\n };\n \n const handleError = (error: ErrorEvent) => {\n if (resolved) return;\n resolved = true;\n cleanup();\n script.remove();\n console.error(`[loadScript] Failed to load script: ${src}`, error);\n reject(new Error(`Failed to load script: ${src}, Error: ${error.message}`));\n };\n \n script.addEventListener('load', handleLoad);\n script.addEventListener('error', handleError);\n\n script.src = src;\n script.nonce = nonce;\n beforeLoad?.(script);\n\n console.log(`[loadScript] Appending script to document body: ${src}`);\n document.body.appendChild(script)\n });\n };\n\n return load()\n\n //return retry(load, { shouldRetry: (_, iterations) => iterations <=5 });\n }"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQE,eAAsB,WAAW,MAAK,IAAI,SAAwD;AAChG,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;AAEvC,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;AAEA,YAAM,aAAa,MAAM;AACvB,YAAI,SAAU;AACd,gBAAQ,IAAI,4CAA4C,GAAG,EAAE;AAE7D,mBAAW;AACX,gBAAQ;AACR,gBAAQ,MAAM;AAAA,MAChB;AAEA,YAAM,cAAc,CAAC,UAAsB;AACzC,YAAI,SAAU;AACd,mBAAW;AACX,gBAAQ;AACR,eAAO,OAAO;AACd,gBAAQ,MAAM,uCAAuC,GAAG,IAAI,KAAK;AACjE,eAAO,IAAI,MAAM,0BAA0B,GAAG,YAAY,MAAM,OAAO,EAAE,CAAC;AAAA,MAC5E;AAEA,aAAO,iBAAiB,QAAQ,UAAU;AAC1C,aAAO,iBAAiB,SAAS,WAAW;AAE5C,aAAO,MAAM;AACb,aAAO,QAAQ;AACf,+CAAa;AAEb,cAAQ,IAAI,mDAAmD,GAAG,EAAE;AACpE,eAAS,KAAK,YAAY,MAAM;AAAA,IAClC,CAAC;AAAA,EACH;AAEA,SAAO,KAAK;AAGd;","names":[]}
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":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACyCA,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;;;ADpGA,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":[]}
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  loadScript
3
- } from "./chunk-33U3M4YY.mjs";
3
+ } from "./chunk-IGYBIQYE.mjs";
4
+ import "./chunk-N2V3PKFE.mjs";
4
5
  export {
5
6
  loadScript
6
7
  };
@@ -1,9 +1,11 @@
1
- import { TernSecureInstanceTreeOptions, TernSecureSDK } from '@tern-secure/types';
1
+ import { TernSecureAuthOptions, TernSecureSDK } from '@tern-secure/types';
2
2
 
3
- type LoadTernUISCriptOptions = TernSecureInstanceTreeOptions & {
3
+ type LoadTernUISCriptOptions = TernSecureAuthOptions & {
4
4
  apiKey?: string;
5
- customDomain?: string;
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-proxyUrl': string;
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 { TernSecureInstanceTreeOptions, TernSecureSDK } from '@tern-secure/types';
1
+ import { TernSecureAuthOptions, TernSecureSDK } from '@tern-secure/types';
2
2
 
3
- type LoadTernUISCriptOptions = TernSecureInstanceTreeOptions & {
3
+ type LoadTernUISCriptOptions = TernSecureAuthOptions & {
4
4
  apiKey?: string;
5
- customDomain?: string;
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-proxyUrl': string;
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 };