@tern-secure/auth 1.1.0-canary.v20250916132854 → 1.1.0-canary.v20250918173007

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.
@@ -32,15 +32,16 @@ var import_web_extension = require("firebase/auth/web-extension");
32
32
  var import_installations = require("firebase/installations");
33
33
  var import_internal = require("../resources/internal");
34
34
  var import_construct = require("../utils/construct");
35
+ var import_c_coreApiClient = require("./c_coreApiClient");
35
36
  var import_events = require("./events");
36
37
  function inBrowser() {
37
38
  return typeof window !== "undefined";
38
39
  }
39
40
  class TernSecureAuth {
40
- static version = "1.1.0-canary.v20250916132854";
41
+ static version = "1.1.0-canary.v20250918173007";
41
42
  static sdkMetadata = {
42
43
  name: "@tern-secure/auth",
43
- version: "1.1.0-canary.v20250916132854",
44
+ version: "1.1.0-canary.v20250918173007",
44
45
  environment: process.env.NODE_ENV || "production"
45
46
  };
46
47
  static instance = null;
@@ -55,6 +56,7 @@ class TernSecureAuth {
55
56
  user = null;
56
57
  __internal_country;
57
58
  #domain;
59
+ #apiClient;
58
60
  #apiUrl;
59
61
  #instanceType;
60
62
  #status = "loading";
@@ -85,7 +87,6 @@ class TernSecureAuth {
85
87
  get apiUrl() {
86
88
  return this.#apiUrl;
87
89
  }
88
- getApiUrl = () => this.#apiUrl;
89
90
  get domain() {
90
91
  if (inBrowser()) {
91
92
  const strippedDomainString = (0, import_url.stripScheme)(
@@ -106,9 +107,15 @@ class TernSecureAuth {
106
107
  this.#domain = (_a = options == null ? void 0 : options.ternSecureConfig) == null ? void 0 : _a.authDomain;
107
108
  this.#apiUrl = (options == null ? void 0 : options.apiUrl) || "";
108
109
  this.#instanceType = process.env.NODE_ENV || "production";
110
+ this.#apiClient = (0, import_c_coreApiClient.createCoreApiClient)({
111
+ domain: this.#domain,
112
+ apiUrl: options == null ? void 0 : options.apiUrl,
113
+ instanceType: this.instanceType
114
+ });
109
115
  this.#publicEventBus.emit(import_ternStatusEvent.ternEvents.Status, "loading");
110
116
  import_internal.TernSecureBase.ternsecure = this;
111
117
  }
118
+ getApiClient = () => this.#apiClient;
112
119
  setLoading(isLoading) {
113
120
  this.isLoading = isLoading;
114
121
  }
@@ -119,7 +126,6 @@ class TernSecureAuth {
119
126
  if (!this.instance) {
120
127
  this.instance = new TernSecureAuth(options);
121
128
  }
122
- console.log("[TernSecureAuth] TernSecureAuth instance:", this.instance);
123
129
  return this.instance;
124
130
  }
125
131
  static clearInstance() {
@@ -162,19 +168,18 @@ class TernSecureAuth {
162
168
  throw error;
163
169
  }
164
170
  };
165
- initializeFirebaseApp(config) {
171
+ async initializeFirebaseApp(config) {
166
172
  const appName = config.appName || "[DEFAULT]";
167
173
  this.firebaseClientApp = (0, import_app.getApps)().length === 0 ? (0, import_app.initializeApp)(config, appName) : (0, import_app.getApps)()[0];
168
174
  const persistence = this.#setPersistence();
169
- const auth = (0, import_auth.initializeAuth)(this.firebaseClientApp, {
170
- persistence
171
- });
175
+ const auth = (0, import_auth.getAuth)(this.firebaseClientApp);
172
176
  this.auth = auth;
173
177
  if (config.tenantId) {
174
178
  this.auth.tenantId = config.tenantId;
175
179
  }
176
180
  this.#configureEmulator();
177
181
  (0, import_installations.getInstallations)(this.firebaseClientApp);
182
+ await auth.setPersistence(import_web_extension.browserCookiePersistence);
178
183
  }
179
184
  signOut = async (options) => {
180
185
  const redirectUrl = (options == null ? void 0 : options.redirectUrl) || this.#constructAfterSignOutUrl();
@@ -294,10 +299,6 @@ class TernSecureAuth {
294
299
  if (!this.#options.ternSecureConfig) {
295
300
  throw new Error("TernSecureConfig is required to initialize TernSecureAuth");
296
301
  }
297
- if (!this.#options.apiUrl) {
298
- throw new Error("apiUrl is required to initialize TernSecureAuth");
299
- }
300
- this.#apiUrl = this.#options.apiUrl;
301
302
  this.initializeFirebaseApp(this.#options.ternSecureConfig);
302
303
  this.signIn = new import_internal.SignIn(this.auth, this.csrfToken);
303
304
  this.signUp = new import_internal.SignUp(this.auth);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/instance/TernAuth.ts"],"sourcesContent":["import { handleFirebaseAuthError } from '@tern-secure/shared/errors';\nimport { createTernAuthEventBus, ternEvents } from '@tern-secure/shared/ternStatusEvent';\nimport { stripScheme } from '@tern-secure/shared/url';\nimport { handleValueOrFn } from '@tern-secure/shared/utils';\nimport type {\n DomainOrProxyUrl,\n InstanceType,\n ListenerCallback,\n RedirectOptions,\n SignedInSession,\n SignInRedirectOptions,\n SignInResource,\n SignInResponseTree,\n SignOut,\n SignOutOptions,\n SignUpRedirectOptions,\n SignUpResource,\n TernSecureAuth as TernSecureAuthInterface,\n TernSecureAuthOptions,\n TernSecureAuthStatus,\n TernSecureConfig,\n TernSecureResources,\n TernSecureSDK,\n TernSecureUser,\n UnsubscribeCallback,\n} from '@tern-secure/types';\nimport type { FirebaseApp } from 'firebase/app';\nimport { getApps, initializeApp } from 'firebase/app';\nimport type { Auth, Auth as TernAuth } from 'firebase/auth';\nimport {\n browserLocalPersistence,\n browserSessionPersistence,\n connectAuthEmulator,\n getRedirectResult,\n initializeAuth,\n inMemoryPersistence,\n onAuthStateChanged,\n onIdTokenChanged,\n} from 'firebase/auth';\nimport { browserCookiePersistence } from 'firebase/auth/web-extension';\nimport { getInstallations } from 'firebase/installations';\n\nimport { AuthCookieManager, SignIn, SignUp, TernSecureBase } from '../resources/internal';\nimport { buildURL } from '../utils/construct';\nimport { eventBus, events } from './events';\n\nexport function inBrowser(): boolean {\n return typeof window !== 'undefined';\n}\n\nexport { TernAuth };\n\n/**\n * Firebase implementation of the TernSecureAuth interface\n */\nexport class TernSecureAuth implements TernSecureAuthInterface {\n public static version: string = PACKAGE_VERSION;\n public static sdkMetadata: TernSecureSDK = {\n name: PACKAGE_NAME,\n version: PACKAGE_VERSION,\n environment: process.env.NODE_ENV || 'production',\n };\n private static instance: TernSecureAuth | null = null;\n private _currentUser: TernSecureUser | null = null;\n private signedInSession: SignedInSession | null = null;\n private firebaseClientApp: FirebaseApp | undefined;\n private authStateUnsubscribe: (() => void) | null = null;\n private auth!: Auth;\n private csrfToken: string | undefined;\n public isLoading = false;\n public error: Error | null = null;\n public user: TernSecureUser | null | undefined = null;\n public __internal_country?: string | null;\n #domain: DomainOrProxyUrl['domain'];\n #apiUrl!: string;\n #instanceType?: InstanceType;\n #status: TernSecureAuthInterface['status'] = 'loading';\n #listeners: Array<(emission: TernSecureResources) => void> = [];\n #options: TernSecureAuthOptions = {} as TernSecureAuthOptions;\n #authCookieManager?: AuthCookieManager;\n #publicEventBus = createTernAuthEventBus();\n\n signIn!: SignInResource;\n signUp!: SignUpResource;\n\n get isReady(): boolean {\n return this.status === 'ready';\n }\n\n get status(): TernSecureAuthInterface['status'] {\n return this.#status;\n }\n\n get version(): string {\n return TernSecureAuth.version;\n }\n\n set sdkMetadata(metadata: TernSecureSDK) {\n TernSecureAuth.sdkMetadata = metadata;\n }\n\n get sdkMetadata(): TernSecureSDK {\n return TernSecureAuth.sdkMetadata;\n }\n\n get requiresVerification(): boolean {\n return this.#options.requiresVerification ?? true;\n }\n\n get apiUrl(): string {\n return this.#apiUrl;\n }\n\n public getApiUrl = (): string => this.#apiUrl;\n\n get domain(): string {\n if (inBrowser()) {\n const strippedDomainString = stripScheme(\n handleValueOrFn(this.#domain, new URL(window.location.href)),\n );\n if (this.#instanceType === 'production') {\n return strippedDomainString;\n }\n return strippedDomainString;\n }\n return '';\n }\n\n get instanceType() {\n return this.#instanceType;\n }\n\n public constructor(options?: TernSecureAuthOptions) {\n this.#domain = options?.ternSecureConfig?.authDomain;\n this.#apiUrl = options?.apiUrl || '';\n this.#instanceType = (process.env.NODE_ENV as InstanceType) || 'production';\n this.#publicEventBus.emit(ternEvents.Status, 'loading');\n TernSecureBase.ternsecure = this;\n }\n\n public setLoading(isLoading: boolean): void {\n this.isLoading = isLoading;\n }\n\n public authCookieManager(): AuthCookieManager | undefined {\n return this.#authCookieManager;\n }\n\n static getorCreateInstance(options?: TernSecureAuthOptions): TernSecureAuth {\n if (!this.instance) {\n this.instance = new TernSecureAuth(options);\n }\n console.log('[TernSecureAuth] TernSecureAuth instance:', this.instance);\n return this.instance;\n }\n\n static clearInstance() {\n if (TernSecureAuth.instance) {\n if (TernSecureAuth.instance.authStateUnsubscribe) {\n TernSecureAuth.instance.authStateUnsubscribe();\n TernSecureAuth.instance.authStateUnsubscribe = null;\n }\n TernSecureAuth.instance = null;\n }\n }\n\n public static initialize(options: TernSecureAuthOptions): TernSecureAuth {\n const instance = this.getorCreateInstance(options);\n instance.#initialize(options);\n return instance;\n }\n\n #initialize = (options: TernSecureAuthOptions): TernSecureAuth => {\n this.#options = this.#initOptions(options);\n\n try {\n if (!this.#options.ternSecureConfig) {\n throw new Error('TernSecureConfig is required to initialize TernSecureAuth');\n }\n\n if (!this.#options.apiUrl) {\n throw new Error('apiUrl is required to initialize TernSecureAuth');\n }\n\n this.initializeFirebaseApp(this.#options.ternSecureConfig);\n this.authStateUnsubscribe = this.initAuthStateListener();\n this._onIdTokenChanged();\n\n this.#authCookieManager = new AuthCookieManager();\n this.csrfToken = this.#authCookieManager.getCSRFToken();\n\n this.signIn = new SignIn(this.auth, this.csrfToken);\n this.signUp = new SignUp(this.auth);\n\n this.#setStatus('ready');\n this.#publicEventBus.emit(ternEvents.Status, 'ready');\n\n return this;\n } catch (error) {\n this.error = error as Error;\n this.#setStatus('error');\n this.#publicEventBus.emit(ternEvents.Status, 'error');\n throw error;\n }\n };\n\n private initializeFirebaseApp(config: TernSecureConfig) {\n const appName = config.appName || '[DEFAULT]';\n this.firebaseClientApp = getApps().length === 0 ? initializeApp(config, appName) : getApps()[0];\n\n const persistence = this.#setPersistence();\n const auth = initializeAuth(this.firebaseClientApp, {\n persistence,\n });\n\n this.auth = auth;\n\n if (config.tenantId) {\n this.auth.tenantId = config.tenantId;\n }\n\n this.#configureEmulator();\n\n getInstallations(this.firebaseClientApp);\n }\n\n public signOut: SignOut = async (options?: SignOutOptions) => {\n const redirectUrl = options?.redirectUrl || this.#constructAfterSignOutUrl();\n if (options?.onBeforeSignOut) {\n await options.onBeforeSignOut();\n }\n\n await this.auth.signOut();\n\n if (options?.onAfterSignOut) {\n await options.onAfterSignOut();\n }\n if (inBrowser()) {\n window.location.href = redirectUrl;\n }\n eventBus.emit(events.UserSignOut, null);\n eventBus.emit(events.TokenRefreshed, { token: null });\n this.#emit();\n };\n\n get currentSession(): SignedInSession | null {\n return this.signedInSession;\n };\n\n private initAuthStateListener(): () => void {\n return onAuthStateChanged(this.auth, async (user: TernSecureUser | null) => {\n await this.auth.authStateReady();\n this._currentUser = user;\n await this.updateCurrentSession();\n\n eventBus.emit(events.UserChanged, this._currentUser);\n this.#emit();\n });\n }\n\n private _onIdTokenChanged(): () => void {\n return onIdTokenChanged(this.auth, async (user: TernSecureUser | null) => {\n await this.auth.authStateReady();\n this._currentUser = user;\n await this.updateCurrentSession();\n\n eventBus.emit(events.TokenRefreshed, { token: user ? await user.getIdTokenResult() : null });\n this.#emit();\n });\n }\n\n public onAuthStateChanged(callback: (cb: any) => void): () => void {\n return onAuthStateChanged(this.auth, callback);\n }\n\n public onIdTokenChanged(callback: (cb: any) => void): () => void {\n return onIdTokenChanged(this.auth, callback);\n }\n\n private async updateCurrentSession(): Promise<void> {\n if (!this._currentUser) {\n this.signedInSession = null;\n return;\n }\n\n try {\n const res = await this._currentUser.getIdTokenResult();\n this.signedInSession = {\n status: 'active',\n token: res.token,\n claims: res.claims,\n issuedAtTime: res.issuedAtTime,\n expirationTime: res.expirationTime,\n authTime: res.authTime,\n signInProvider: res.signInProvider || 'unknown',\n };\n } catch (error) {\n console.error('[TernSecureAuth] Error updating session:', error);\n this.signedInSession = null;\n }\n }\n\n public async checkRedirectResult(): Promise<SignInResponseTree | null> {\n try {\n const result = await getRedirectResult(this.auth);\n if (result) {\n return {\n success: true,\n user: result.user as TernSecureUser,\n };\n }\n return null;\n } catch (error) {\n const authError = handleFirebaseAuthError(error);\n return {\n success: false,\n message: authError.message,\n error: authError.code,\n user: null,\n };\n }\n }\n\n public addListener = (listener: ListenerCallback): UnsubscribeCallback => {\n this.#listeners.push(listener);\n if (this._currentUser) {\n listener({\n user: this._currentUser,\n session: this.signedInSession,\n });\n }\n\n const unsubscribe = () => {\n this.#listeners = this.#listeners.filter(l => l !== listener);\n };\n return unsubscribe;\n };\n\n public on: TernSecureAuthInterface['on'] = (...args) => {\n this.#publicEventBus.on(...args);\n };\n\n public off: TernSecureAuthInterface['off'] = (...args) => {\n this.#publicEventBus.off(...args);\n };\n\n public initialize(options: TernSecureAuthOptions): Promise<void> {\n this._initialize(options);\n return Promise.resolve();\n }\n\n public static create(options: TernSecureAuthOptions): TernSecureAuth {\n const instance = this.getorCreateInstance();\n instance.initialize(options);\n return instance;\n }\n\n _initialize = (options: TernSecureAuthOptions): void => {\n this.#options = this.#initOptions(options);\n try {\n if (!this.#options.ternSecureConfig) {\n throw new Error('TernSecureConfig is required to initialize TernSecureAuth');\n }\n\n if (!this.#options.apiUrl) {\n throw new Error('apiUrl is required to initialize TernSecureAuth');\n }\n\n this.#apiUrl = this.#options.apiUrl;\n\n this.initializeFirebaseApp(this.#options.ternSecureConfig);\n\n this.signIn = new SignIn(this.auth, this.csrfToken);\n this.signUp = new SignUp(this.auth);\n\n this.#setStatus('ready');\n } catch (error) {\n this.error = error as Error;\n this.#setStatus('error');\n throw error;\n }\n };\n\n public constructUrlWithAuthRedirect = (to: string): string => {\n const baseUrl = window.location.origin;\n const url = new URL(to, baseUrl);\n\n if (url.origin === window.location.origin) {\n return url.href;\n }\n\n return url.toString();\n };\n\n #buildUrl = (key: 'signInUrl' | 'signUpUrl', options: RedirectOptions): string => {\n if (!key || !this.isReady) {\n return '';\n }\n\n const baseUrlConfig = key === 'signInUrl' ? this.#options.signInUrl : this.#options.signUpUrl;\n const defaultPagePath = key === 'signInUrl' ? '/sign-in' : '/sign-up';\n const base = baseUrlConfig || defaultPagePath;\n\n let effectiveRedirectUrl: string | null | undefined;\n\n // Priority 1: Get redirect URL from options (signInForceRedirectUrl or signUpForceRedirectUrl)\n if (key === 'signInUrl' && 'signInForceRedirectUrl' in options) {\n effectiveRedirectUrl = options.signInForceRedirectUrl;\n } else if (key === 'signUpUrl' && 'signUpForceRedirectUrl' in options) {\n effectiveRedirectUrl = options.signUpForceRedirectUrl;\n }\n\n // Priority 2: If no force redirect from options, check 'redirect' param in current URL (only in browser)\n if (!effectiveRedirectUrl && inBrowser()) {\n const currentUrlParams = new URLSearchParams(window.location.search);\n const existingRedirectParam = currentUrlParams.get('redirect_url');\n if (existingRedirectParam) {\n effectiveRedirectUrl = existingRedirectParam;\n }\n }\n\n // Priority 3: If still no redirect URL, fallback to current page's full path (only in browser)\n // This ensures that if the call originates from a page, it attempts to redirect back there by default.\n if (!effectiveRedirectUrl && inBrowser()) {\n effectiveRedirectUrl =\n window.location.pathname + window.location.search + window.location.hash;\n }\n\n if (effectiveRedirectUrl && inBrowser()) {\n let signInPagePath: string | undefined;\n try {\n signInPagePath = this.#options.signInUrl\n ? new URL(this.#options.signInUrl, window.location.origin).pathname\n : defaultPagePath;\n } catch {\n signInPagePath = defaultPagePath;\n }\n\n let signUpPagePath: string | undefined;\n try {\n signUpPagePath = this.#options.signUpUrl\n ? new URL(this.#options.signUpUrl, window.location.origin).pathname\n : key === 'signUpUrl'\n ? defaultPagePath\n : '/sign-in';\n } catch {\n signUpPagePath = key === 'signUpUrl' ? defaultPagePath : '/sign-in';\n }\n\n const redirectTargetObj = new URL(effectiveRedirectUrl, window.location.origin);\n\n if (\n redirectTargetObj.pathname === signInPagePath ||\n redirectTargetObj.pathname === signUpPagePath\n ) {\n // If the intended redirect path is the sign-in or sign-up page itself,\n // change the redirect target to the application root ('/').\n effectiveRedirectUrl = '/';\n }\n }\n\n const paramsForBuildUrl: Parameters<typeof buildURL>[0] = {\n base,\n searchParams: new URLSearchParams(),\n };\n\n if (effectiveRedirectUrl) {\n // Check if a redirect URL was determined\n if (inBrowser()) {\n const absoluteRedirectUrl = new URL(effectiveRedirectUrl, window.location.origin).href;\n paramsForBuildUrl.searchParams?.set('redirect', absoluteRedirectUrl);\n } else {\n // If not in browser, use the effectiveRedirectUrl as is.\n // This assumes it's either absolute or a path the server can interpret.\n paramsForBuildUrl.searchParams?.set('redirect', effectiveRedirectUrl);\n }\n }\n\n const constructedUrl = buildURL(paramsForBuildUrl, {\n stringify: true,\n skipOrigin: false,\n });\n\n if (typeof constructedUrl !== 'string') {\n console.error(\n '[TernSecure] Error: buildURL did not return a string as expected. Falling back to base URL.',\n );\n if (inBrowser()) {\n try {\n return new URL(base, window.location.origin).href;\n } catch {\n return base;\n }\n }\n return base;\n }\n\n return this.constructUrlWithAuthRedirect(constructedUrl);\n };\n\n #constructAfterSignOutUrl = (): string => {\n if (!this.#options.afterSignOutUrl) {\n return '/';\n }\n return this.constructUrlWithAuthRedirect(this.#options.afterSignOutUrl);\n };\n\n public constructSignInUrl = (options?: SignInRedirectOptions): string => {\n return this.#buildUrl('signInUrl', { ...options });\n };\n\n public constructSignUpUrl = (options?: SignUpRedirectOptions): string => {\n return this.#buildUrl('signUpUrl', { ...options });\n };\n\n __internal_setCountry = (country: string | null) => {\n if (!this.__internal_country) {\n this.__internal_country = country;\n }\n };\n\n #initOptions = (options: TernSecureAuthOptions): TernSecureAuthOptions => {\n return {\n ...options,\n };\n };\n\n #emit = (): void => {\n if (this._currentUser) {\n for (const listener of this.#listeners) {\n listener({\n user: this._currentUser,\n });\n }\n }\n };\n\n #setStatus(newStatus: TernSecureAuthStatus): void {\n if (this.#status !== newStatus) {\n this.#status = newStatus;\n this.#publicEventBus.emit(ternEvents.Status, this.#status);\n\n if (newStatus === 'ready') {\n this.#publicEventBus.emit(ternEvents.Status, 'ready');\n }\n }\n }\n\n #setPersistence = () => {\n const persistenceType = this.#options.persistence || 'none';\n\n switch (persistenceType) {\n case 'browserCookie':\n return browserCookiePersistence;\n case 'session':\n return browserSessionPersistence;\n case 'local':\n return browserLocalPersistence;\n case 'none':\n default:\n return inMemoryPersistence;\n }\n };\n\n #emulatorHost = (): string | undefined => {\n if (typeof process === 'undefined') return undefined;\n return process.env.FIREBASE_AUTH_EMULATOR_HOST;\n };\n\n #configureEmulator = (): void => {\n const host = this.#emulatorHost();\n const isDev = this.#instanceType === 'development';\n const shouldUseEmulator = isDev && !!host;\n if (!shouldUseEmulator || !host) {\n return;\n }\n\n const emulatorUrl = host.startsWith('http') ? host : `http://${host}`;\n\n try {\n //(this.auth as unknown as any)._canInitEmulator = true;\n connectAuthEmulator(this.auth, emulatorUrl, { disableWarnings: true });\n console.warn(`[TernSecure] Firebase Auth Emulator connected at ${emulatorUrl}`);\n } catch (error) {\n console.error('[TernSecure] Error connecting to Firebase Auth Emulator:', error);\n }\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/instance/TernAuth.ts"],"sourcesContent":["import { handleFirebaseAuthError } from '@tern-secure/shared/errors';\nimport { createTernAuthEventBus, ternEvents } from '@tern-secure/shared/ternStatusEvent';\nimport { stripScheme } from '@tern-secure/shared/url';\nimport { handleValueOrFn } from '@tern-secure/shared/utils';\nimport type {\n DomainOrProxyUrl,\n InstanceType,\n ListenerCallback,\n RedirectOptions,\n SignedInSession,\n SignInRedirectOptions,\n SignInResource,\n SignInResponseTree,\n SignOut,\n SignOutOptions,\n SignUpRedirectOptions,\n SignUpResource,\n TernSecureAuth as TernSecureAuthInterface,\n TernSecureAuthOptions,\n TernSecureAuthStatus,\n TernSecureConfig,\n TernSecureResources,\n TernSecureSDK,\n TernSecureUser,\n UnsubscribeCallback,\n} from '@tern-secure/types';\nimport type { FirebaseApp } from 'firebase/app';\nimport { getApps, initializeApp } from 'firebase/app';\nimport type { Auth, Auth as TernAuth } from 'firebase/auth';\nimport {\n browserLocalPersistence,\n browserSessionPersistence,\n connectAuthEmulator,\n getAuth,\n getRedirectResult,\n inMemoryPersistence,\n onAuthStateChanged,\n onIdTokenChanged,\n} from 'firebase/auth';\nimport { browserCookiePersistence } from 'firebase/auth/web-extension';\nimport { getInstallations } from 'firebase/installations';\n\nimport { AuthCookieManager, SignIn, SignUp, TernSecureBase } from '../resources/internal';\nimport { buildURL } from '../utils/construct';\nimport { type ApiClient, createCoreApiClient } from './c_coreApiClient';\nimport { eventBus, events } from './events';\n\nexport function inBrowser(): boolean {\n return typeof window !== 'undefined';\n}\n\nexport { TernAuth };\n\n/**\n * Firebase implementation of the TernSecureAuth interface\n */\nexport class TernSecureAuth implements TernSecureAuthInterface {\n public static version: string = PACKAGE_VERSION;\n public static sdkMetadata: TernSecureSDK = {\n name: PACKAGE_NAME,\n version: PACKAGE_VERSION,\n environment: process.env.NODE_ENV || 'production',\n };\n private static instance: TernSecureAuth | null = null;\n private _currentUser: TernSecureUser | null = null;\n private signedInSession: SignedInSession | null = null;\n private firebaseClientApp: FirebaseApp | undefined;\n private authStateUnsubscribe: (() => void) | null = null;\n private auth!: Auth;\n private csrfToken: string | undefined;\n public isLoading = false;\n public error: Error | null = null;\n public user: TernSecureUser | null | undefined = null;\n public __internal_country?: string | null;\n #domain: DomainOrProxyUrl['domain'];\n #apiClient: ApiClient;\n #apiUrl: string;\n #instanceType?: InstanceType;\n #status: TernSecureAuthInterface['status'] = 'loading';\n #listeners: Array<(emission: TernSecureResources) => void> = [];\n #options: TernSecureAuthOptions = {} as TernSecureAuthOptions;\n #authCookieManager?: AuthCookieManager;\n #publicEventBus = createTernAuthEventBus();\n\n signIn!: SignInResource;\n signUp!: SignUpResource;\n\n get isReady(): boolean {\n return this.status === 'ready';\n }\n\n get status(): TernSecureAuthInterface['status'] {\n return this.#status;\n }\n\n get version(): string {\n return TernSecureAuth.version;\n }\n\n set sdkMetadata(metadata: TernSecureSDK) {\n TernSecureAuth.sdkMetadata = metadata;\n }\n\n get sdkMetadata(): TernSecureSDK {\n return TernSecureAuth.sdkMetadata;\n }\n\n get requiresVerification(): boolean {\n return this.#options.requiresVerification ?? true;\n }\n\n get apiUrl(): string {\n return this.#apiUrl;\n }\n\n get domain(): string {\n if (inBrowser()) {\n const strippedDomainString = stripScheme(\n handleValueOrFn(this.#domain, new URL(window.location.href)),\n );\n if (this.#instanceType === 'production') {\n return strippedDomainString;\n }\n return strippedDomainString;\n }\n return '';\n }\n\n get instanceType() {\n return this.#instanceType;\n }\n\n public constructor(options?: TernSecureAuthOptions) {\n this.#domain = options?.ternSecureConfig?.authDomain;\n this.#apiUrl = options?.apiUrl || '';\n this.#instanceType = (process.env.NODE_ENV as InstanceType) || 'production';\n\n this.#apiClient = createCoreApiClient({\n domain: this.#domain,\n apiUrl: options?.apiUrl,\n instanceType: this.instanceType as InstanceType,\n });\n\n this.#publicEventBus.emit(ternEvents.Status, 'loading');\n TernSecureBase.ternsecure = this;\n }\n\n public getApiClient = (): ApiClient => this.#apiClient;\n\n public setLoading(isLoading: boolean): void {\n this.isLoading = isLoading;\n }\n\n public authCookieManager(): AuthCookieManager | undefined {\n return this.#authCookieManager;\n }\n\n static getorCreateInstance(options?: TernSecureAuthOptions): TernSecureAuth {\n if (!this.instance) {\n this.instance = new TernSecureAuth(options);\n }\n //console.log('TernSecureAuth instance:', this.instance);\n return this.instance;\n }\n\n static clearInstance() {\n if (TernSecureAuth.instance) {\n if (TernSecureAuth.instance.authStateUnsubscribe) {\n TernSecureAuth.instance.authStateUnsubscribe();\n TernSecureAuth.instance.authStateUnsubscribe = null;\n }\n TernSecureAuth.instance = null;\n }\n }\n\n public static initialize(options: TernSecureAuthOptions): TernSecureAuth {\n const instance = this.getorCreateInstance(options);\n instance.#initialize(options);\n return instance;\n }\n\n #initialize = (options: TernSecureAuthOptions): TernSecureAuth => {\n this.#options = this.#initOptions(options);\n\n try {\n if (!this.#options.ternSecureConfig) {\n throw new Error('TernSecureConfig is required to initialize TernSecureAuth');\n }\n\n if (!this.#options.apiUrl) {\n throw new Error('apiUrl is required to initialize TernSecureAuth');\n }\n\n this.initializeFirebaseApp(this.#options.ternSecureConfig);\n this.authStateUnsubscribe = this.initAuthStateListener();\n this._onIdTokenChanged();\n\n this.#authCookieManager = new AuthCookieManager();\n this.csrfToken = this.#authCookieManager.getCSRFToken();\n\n this.signIn = new SignIn(this.auth, this.csrfToken);\n this.signUp = new SignUp(this.auth);\n\n this.#setStatus('ready');\n this.#publicEventBus.emit(ternEvents.Status, 'ready');\n\n return this;\n } catch (error) {\n this.error = error as Error;\n this.#setStatus('error');\n this.#publicEventBus.emit(ternEvents.Status, 'error');\n throw error;\n }\n };\n\n private async initializeFirebaseApp(config: TernSecureConfig) {\n const appName = config.appName || '[DEFAULT]';\n this.firebaseClientApp = getApps().length === 0 ? initializeApp(config, appName) : getApps()[0];\n\n const persistence = this.#setPersistence();\n //const auth = initializeAuth(this.firebaseClientApp, {\n // persistence: browserCookiePersistence,\n //});\n const auth = getAuth(this.firebaseClientApp);\n\n this.auth = auth;\n\n if (config.tenantId) {\n this.auth.tenantId = config.tenantId;\n }\n\n this.#configureEmulator();\n\n getInstallations(this.firebaseClientApp);\n\n await auth.setPersistence(browserCookiePersistence)\n }\n\n public signOut: SignOut = async (options?: SignOutOptions) => {\n const redirectUrl = options?.redirectUrl || this.#constructAfterSignOutUrl();\n if (options?.onBeforeSignOut) {\n await options.onBeforeSignOut();\n }\n\n await this.auth.signOut();\n\n if (options?.onAfterSignOut) {\n await options.onAfterSignOut();\n }\n if (inBrowser()) {\n window.location.href = redirectUrl;\n }\n eventBus.emit(events.UserSignOut, null);\n eventBus.emit(events.TokenRefreshed, { token: null });\n this.#emit();\n };\n\n get currentSession(): SignedInSession | null {\n return this.signedInSession;\n }\n\n private initAuthStateListener(): () => void {\n return onAuthStateChanged(this.auth, async (user: TernSecureUser | null) => {\n await this.auth.authStateReady();\n this._currentUser = user;\n await this.updateCurrentSession();\n\n eventBus.emit(events.UserChanged, this._currentUser);\n this.#emit();\n });\n }\n\n private _onIdTokenChanged(): () => void {\n return onIdTokenChanged(this.auth, async (user: TernSecureUser | null) => {\n await this.auth.authStateReady();\n this._currentUser = user;\n await this.updateCurrentSession();\n\n eventBus.emit(events.TokenRefreshed, { token: user ? await user.getIdTokenResult() : null });\n this.#emit();\n });\n }\n\n public onAuthStateChanged(callback: (cb: any) => void): () => void {\n return onAuthStateChanged(this.auth, callback);\n }\n\n public onIdTokenChanged(callback: (cb: any) => void): () => void {\n return onIdTokenChanged(this.auth, callback);\n }\n\n private async updateCurrentSession(): Promise<void> {\n if (!this._currentUser) {\n this.signedInSession = null;\n return;\n }\n\n try {\n const res = await this._currentUser.getIdTokenResult();\n this.signedInSession = {\n status: 'active',\n token: res.token,\n claims: res.claims,\n issuedAtTime: res.issuedAtTime,\n expirationTime: res.expirationTime,\n authTime: res.authTime,\n signInProvider: res.signInProvider || 'unknown',\n };\n } catch (error) {\n console.error('[TernSecureAuth] Error updating session:', error);\n this.signedInSession = null;\n }\n }\n\n public async checkRedirectResult(): Promise<SignInResponseTree | null> {\n try {\n const result = await getRedirectResult(this.auth);\n if (result) {\n return {\n success: true,\n user: result.user as TernSecureUser,\n };\n }\n return null;\n } catch (error) {\n const authError = handleFirebaseAuthError(error);\n return {\n success: false,\n message: authError.message,\n error: authError.code,\n user: null,\n };\n }\n }\n\n public addListener = (listener: ListenerCallback): UnsubscribeCallback => {\n this.#listeners.push(listener);\n if (this._currentUser) {\n listener({\n user: this._currentUser,\n session: this.signedInSession,\n });\n }\n\n const unsubscribe = () => {\n this.#listeners = this.#listeners.filter(l => l !== listener);\n };\n return unsubscribe;\n };\n\n public on: TernSecureAuthInterface['on'] = (...args) => {\n this.#publicEventBus.on(...args);\n };\n\n public off: TernSecureAuthInterface['off'] = (...args) => {\n this.#publicEventBus.off(...args);\n };\n\n public initialize(options: TernSecureAuthOptions): Promise<void> {\n this._initialize(options);\n return Promise.resolve();\n }\n\n public static create(options: TernSecureAuthOptions): TernSecureAuth {\n const instance = this.getorCreateInstance();\n instance.initialize(options);\n return instance;\n }\n\n _initialize = (options: TernSecureAuthOptions): void => {\n this.#options = this.#initOptions(options);\n try {\n if (!this.#options.ternSecureConfig) {\n throw new Error('TernSecureConfig is required to initialize TernSecureAuth');\n }\n\n this.initializeFirebaseApp(this.#options.ternSecureConfig);\n\n this.signIn = new SignIn(this.auth, this.csrfToken);\n this.signUp = new SignUp(this.auth);\n\n this.#setStatus('ready');\n } catch (error) {\n this.error = error as Error;\n this.#setStatus('error');\n throw error;\n }\n };\n\n public constructUrlWithAuthRedirect = (to: string): string => {\n const baseUrl = window.location.origin;\n const url = new URL(to, baseUrl);\n\n if (url.origin === window.location.origin) {\n return url.href;\n }\n\n return url.toString();\n };\n\n #buildUrl = (key: 'signInUrl' | 'signUpUrl', options: RedirectOptions): string => {\n if (!key || !this.isReady) {\n return '';\n }\n\n const baseUrlConfig = key === 'signInUrl' ? this.#options.signInUrl : this.#options.signUpUrl;\n const defaultPagePath = key === 'signInUrl' ? '/sign-in' : '/sign-up';\n const base = baseUrlConfig || defaultPagePath;\n\n let effectiveRedirectUrl: string | null | undefined;\n\n // Priority 1: Get redirect URL from options (signInForceRedirectUrl or signUpForceRedirectUrl)\n if (key === 'signInUrl' && 'signInForceRedirectUrl' in options) {\n effectiveRedirectUrl = options.signInForceRedirectUrl;\n } else if (key === 'signUpUrl' && 'signUpForceRedirectUrl' in options) {\n effectiveRedirectUrl = options.signUpForceRedirectUrl;\n }\n\n // Priority 2: If no force redirect from options, check 'redirect' param in current URL (only in browser)\n if (!effectiveRedirectUrl && inBrowser()) {\n const currentUrlParams = new URLSearchParams(window.location.search);\n const existingRedirectParam = currentUrlParams.get('redirect_url');\n if (existingRedirectParam) {\n effectiveRedirectUrl = existingRedirectParam;\n }\n }\n\n // Priority 3: If still no redirect URL, fallback to current page's full path (only in browser)\n // This ensures that if the call originates from a page, it attempts to redirect back there by default.\n if (!effectiveRedirectUrl && inBrowser()) {\n effectiveRedirectUrl =\n window.location.pathname + window.location.search + window.location.hash;\n }\n\n if (effectiveRedirectUrl && inBrowser()) {\n let signInPagePath: string | undefined;\n try {\n signInPagePath = this.#options.signInUrl\n ? new URL(this.#options.signInUrl, window.location.origin).pathname\n : defaultPagePath;\n } catch {\n signInPagePath = defaultPagePath;\n }\n\n let signUpPagePath: string | undefined;\n try {\n signUpPagePath = this.#options.signUpUrl\n ? new URL(this.#options.signUpUrl, window.location.origin).pathname\n : key === 'signUpUrl'\n ? defaultPagePath\n : '/sign-in';\n } catch {\n signUpPagePath = key === 'signUpUrl' ? defaultPagePath : '/sign-in';\n }\n\n const redirectTargetObj = new URL(effectiveRedirectUrl, window.location.origin);\n\n if (\n redirectTargetObj.pathname === signInPagePath ||\n redirectTargetObj.pathname === signUpPagePath\n ) {\n // If the intended redirect path is the sign-in or sign-up page itself,\n // change the redirect target to the application root ('/').\n effectiveRedirectUrl = '/';\n }\n }\n\n const paramsForBuildUrl: Parameters<typeof buildURL>[0] = {\n base,\n searchParams: new URLSearchParams(),\n };\n\n if (effectiveRedirectUrl) {\n // Check if a redirect URL was determined\n if (inBrowser()) {\n const absoluteRedirectUrl = new URL(effectiveRedirectUrl, window.location.origin).href;\n paramsForBuildUrl.searchParams?.set('redirect', absoluteRedirectUrl);\n } else {\n // If not in browser, use the effectiveRedirectUrl as is.\n // This assumes it's either absolute or a path the server can interpret.\n paramsForBuildUrl.searchParams?.set('redirect', effectiveRedirectUrl);\n }\n }\n\n const constructedUrl = buildURL(paramsForBuildUrl, {\n stringify: true,\n skipOrigin: false,\n });\n\n if (typeof constructedUrl !== 'string') {\n console.error(\n '[TernSecure] Error: buildURL did not return a string as expected. Falling back to base URL.',\n );\n if (inBrowser()) {\n try {\n return new URL(base, window.location.origin).href;\n } catch {\n return base;\n }\n }\n return base;\n }\n\n return this.constructUrlWithAuthRedirect(constructedUrl);\n };\n\n #constructAfterSignOutUrl = (): string => {\n if (!this.#options.afterSignOutUrl) {\n return '/';\n }\n return this.constructUrlWithAuthRedirect(this.#options.afterSignOutUrl);\n };\n\n public constructSignInUrl = (options?: SignInRedirectOptions): string => {\n return this.#buildUrl('signInUrl', { ...options });\n };\n\n public constructSignUpUrl = (options?: SignUpRedirectOptions): string => {\n return this.#buildUrl('signUpUrl', { ...options });\n };\n\n __internal_setCountry = (country: string | null) => {\n if (!this.__internal_country) {\n this.__internal_country = country;\n }\n };\n\n #initOptions = (options: TernSecureAuthOptions): TernSecureAuthOptions => {\n return {\n ...options,\n };\n };\n\n #emit = (): void => {\n if (this._currentUser) {\n for (const listener of this.#listeners) {\n listener({\n user: this._currentUser,\n });\n }\n }\n };\n\n #setStatus(newStatus: TernSecureAuthStatus): void {\n if (this.#status !== newStatus) {\n this.#status = newStatus;\n this.#publicEventBus.emit(ternEvents.Status, this.#status);\n\n if (newStatus === 'ready') {\n this.#publicEventBus.emit(ternEvents.Status, 'ready');\n }\n }\n }\n\n #setPersistence = () => {\n const persistenceType = this.#options.persistence || 'none';\n\n switch (persistenceType) {\n case 'browserCookie':\n return browserCookiePersistence;\n case 'session':\n return browserSessionPersistence;\n case 'local':\n return browserLocalPersistence;\n case 'none':\n default:\n return inMemoryPersistence;\n }\n };\n\n #emulatorHost = (): string | undefined => {\n if (typeof process === 'undefined') return undefined;\n return process.env.FIREBASE_AUTH_EMULATOR_HOST;\n };\n\n #configureEmulator = (): void => {\n const host = this.#emulatorHost();\n const isDev = this.#instanceType === 'development';\n const shouldUseEmulator = isDev && !!host;\n if (!shouldUseEmulator || !host) {\n return;\n }\n\n const emulatorUrl = host.startsWith('http') ? host : `http://${host}`;\n\n try {\n //(this.auth as unknown as any)._canInitEmulator = true;\n connectAuthEmulator(this.auth, emulatorUrl, { disableWarnings: true });\n console.warn(`[TernSecure] Firebase Auth Emulator connected at ${emulatorUrl}`);\n } catch (error) {\n console.error('[TernSecure] Error connecting to Firebase Auth Emulator:', error);\n }\n };\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,261 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var c_coreApiClient_exports = {};
20
+ __export(c_coreApiClient_exports, {
21
+ CircuitOpenError: () => CircuitOpenError,
22
+ HTTPError: () => HTTPError,
23
+ NetworkError: () => NetworkError,
24
+ TimeoutError: () => TimeoutError,
25
+ createCoreApiClient: () => createCoreApiClient
26
+ });
27
+ module.exports = __toCommonJS(c_coreApiClient_exports);
28
+ var import_utils = require("../utils");
29
+ class NetworkError extends Error {
30
+ constructor(url, original) {
31
+ super(`Network error for ${url}: ${original.message}`);
32
+ this.url = url;
33
+ this.original = original;
34
+ this.name = "NetworkError";
35
+ }
36
+ }
37
+ class TimeoutError extends Error {
38
+ constructor() {
39
+ super("Request timed out");
40
+ this.name = "TimeoutError";
41
+ }
42
+ }
43
+ class CircuitOpenError extends Error {
44
+ constructor() {
45
+ super("Circuit breaker is open");
46
+ this.name = "CircuitOpenError";
47
+ }
48
+ }
49
+ class HTTPError extends Error {
50
+ constructor(status, url, body) {
51
+ super(`HTTP ${status} error for ${url}`);
52
+ this.status = status;
53
+ this.url = url;
54
+ this.body = body;
55
+ this.name = "HTTPError";
56
+ }
57
+ }
58
+ function camelToSnake(str) {
59
+ return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
60
+ }
61
+ function jitteredDelay(delay) {
62
+ return delay * Math.random();
63
+ }
64
+ function createInitialState(clientOptions = {}) {
65
+ return {
66
+ circuitBreaker: {
67
+ failures: 0,
68
+ lastFailureTime: 0,
69
+ state: "closed"
70
+ },
71
+ beforeRequestHooks: [],
72
+ afterResponseHooks: [],
73
+ clientOptions
74
+ };
75
+ }
76
+ function addBeforeRequestHook(state, hook) {
77
+ state.beforeRequestHooks.push(hook);
78
+ }
79
+ function addAfterResponseHook(state, hook) {
80
+ state.afterResponseHooks.push(hook);
81
+ }
82
+ async function runBeforeRequestHooks(state) {
83
+ for (const hook of state.beforeRequestHooks) {
84
+ const result = await hook();
85
+ if (result === false) return false;
86
+ }
87
+ return true;
88
+ }
89
+ async function runAfterResponseHooks(state, response) {
90
+ for (const hook of state.afterResponseHooks) {
91
+ await hook(response);
92
+ }
93
+ }
94
+ function checkCircuitBreaker(state, requestOptions) {
95
+ const { recoveryTimeoutMs = 6e4 } = requestOptions;
96
+ const now = Date.now();
97
+ if (state.circuitBreaker.state === "open") {
98
+ if (now - state.circuitBreaker.lastFailureTime >= recoveryTimeoutMs) {
99
+ state.circuitBreaker.state = "half-open";
100
+ } else {
101
+ throw new CircuitOpenError();
102
+ }
103
+ }
104
+ }
105
+ function recordSuccess(state) {
106
+ state.circuitBreaker.failures = 0;
107
+ state.circuitBreaker.state = "closed";
108
+ }
109
+ function recordFailure(state, requestOptions) {
110
+ const { failureThreshold = 5 } = requestOptions;
111
+ state.circuitBreaker.failures++;
112
+ state.circuitBreaker.lastFailureTime = Date.now();
113
+ if (state.circuitBreaker.failures >= failureThreshold) {
114
+ state.circuitBreaker.state = "open";
115
+ }
116
+ }
117
+ function shouldRetry(state, requestOptions, error, method, attempt, maxTries) {
118
+ const isRetryable = error instanceof NetworkError && method.toUpperCase() === "GET" && attempt < maxTries;
119
+ if (!isRetryable) {
120
+ recordFailure(state, requestOptions);
121
+ }
122
+ return isRetryable;
123
+ }
124
+ async function retryWithBackoff(state, requestOptions, attemptFn, shouldRetryFn) {
125
+ const {
126
+ initialDelay = 700,
127
+ factor = 2,
128
+ maxDelay = 5e3,
129
+ maxTries = typeof navigator !== "undefined" && navigator.onLine ? 4 : 11
130
+ } = requestOptions;
131
+ let lastError;
132
+ for (let attempt = 1; attempt <= maxTries; attempt++) {
133
+ try {
134
+ const result = await attemptFn();
135
+ recordSuccess(state);
136
+ return result;
137
+ } catch (error) {
138
+ lastError = error;
139
+ if (!shouldRetryFn(error, attempt)) {
140
+ throw error;
141
+ }
142
+ recordFailure(state, requestOptions);
143
+ if (attempt < maxTries) {
144
+ const delay = Math.min(initialDelay * Math.pow(factor, attempt - 1), maxDelay);
145
+ await new Promise((resolve) => setTimeout(resolve, jitteredDelay(delay)));
146
+ }
147
+ }
148
+ }
149
+ throw lastError;
150
+ }
151
+ function createCoreApiClient(clientOptions) {
152
+ function buildUrl(requestInit) {
153
+ const { path } = requestInit;
154
+ const domainInProd = clientOptions.instanceType === "production" ? clientOptions.domain : "";
155
+ const baseUrl = `https://${domainInProd || clientOptions.apiUrl}`;
156
+ return (0, import_utils.buildURL)(
157
+ {
158
+ base: baseUrl,
159
+ pathname: path,
160
+ searchParams: requestInit.search ? new URLSearchParams(requestInit.search) : void 0
161
+ },
162
+ { stringify: false }
163
+ );
164
+ }
165
+ async function makeRequest(state2, init, opts = {}) {
166
+ const requestInit = { ...init };
167
+ const { method = "GET", body } = requestInit;
168
+ const requestOptions = { ...opts };
169
+ requestInit.url = buildUrl({ ...init });
170
+ checkCircuitBreaker(state2, requestOptions);
171
+ const shouldContinue = await runBeforeRequestHooks(state2);
172
+ if (!shouldContinue) {
173
+ const mockResponse = new Response("{}", {
174
+ status: 200
175
+ });
176
+ mockResponse.payload = { response: {} };
177
+ await runAfterResponseHooks(state2, mockResponse);
178
+ return mockResponse;
179
+ }
180
+ const { timeoutMs } = requestOptions;
181
+ const overwrittenRequestMethod = method === "GET" ? "GET" : "POST";
182
+ const url = requestInit.url.toString();
183
+ console.log("Request URL:", url);
184
+ requestInit.headers = new Headers(requestInit.headers);
185
+ if (method !== "GET" && !(body instanceof FormData) && !requestInit.headers.has("content-type")) {
186
+ requestInit.headers.set("content-type", "application/json");
187
+ }
188
+ if (requestInit.headers.get("content-type") === "application/x-www-form-urlencoded") {
189
+ requestInit.body = body ? (0, import_utils.stringifyQueryParams)(body, {
190
+ keyEncoder: camelToSnake
191
+ }) : body;
192
+ } else if (requestInit.headers.get("content-type") === "application/json" && body) {
193
+ requestInit.body = typeof body === "string" ? body : JSON.stringify(body);
194
+ }
195
+ const attemptRequest = async () => {
196
+ const controller = new AbortController();
197
+ const timeoutId = timeoutMs ? setTimeout(() => {
198
+ controller.abort();
199
+ }, timeoutMs) : null;
200
+ let response;
201
+ const fetchOpts = {
202
+ ...requestInit,
203
+ credentials: "include",
204
+ method: overwrittenRequestMethod
205
+ };
206
+ try {
207
+ response = await fetch(url, fetchOpts);
208
+ if (timeoutId) clearTimeout(timeoutId);
209
+ let payload = null;
210
+ if (response.status === 204) {
211
+ payload = null;
212
+ } else {
213
+ try {
214
+ const json = await response.json();
215
+ payload = json;
216
+ } catch {
217
+ payload = { response: {} };
218
+ }
219
+ }
220
+ const apiResponse = response;
221
+ apiResponse.payload = payload;
222
+ await runAfterResponseHooks(state2, apiResponse);
223
+ return apiResponse;
224
+ } catch (error) {
225
+ if (timeoutId) clearTimeout(timeoutId);
226
+ if (error.name === "AbortError") {
227
+ throw new TimeoutError();
228
+ }
229
+ throw new NetworkError(url, error);
230
+ }
231
+ };
232
+ return retryWithBackoff(
233
+ state2,
234
+ requestOptions,
235
+ attemptRequest,
236
+ (error, attempt) => shouldRetry(
237
+ state2,
238
+ requestOptions,
239
+ error,
240
+ overwrittenRequestMethod,
241
+ attempt,
242
+ requestOptions.maxTries || (typeof navigator !== "undefined" && navigator.onLine ? 4 : 11)
243
+ )
244
+ );
245
+ }
246
+ const state = createInitialState(clientOptions);
247
+ return {
248
+ onBeforeRequest: (hook) => addBeforeRequestHook(state, hook),
249
+ onAfterResponse: (hook) => addAfterResponseHook(state, hook),
250
+ request: (init, opts = {}) => makeRequest(state, init, opts)
251
+ };
252
+ }
253
+ // Annotate the CommonJS export names for ESM import in node:
254
+ 0 && (module.exports = {
255
+ CircuitOpenError,
256
+ HTTPError,
257
+ NetworkError,
258
+ TimeoutError,
259
+ createCoreApiClient
260
+ });
261
+ //# sourceMappingURL=c_coreApiClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/instance/c_coreApiClient.ts"],"sourcesContent":["import type { InstanceType, TernSecureApiErrorJSON } from '@tern-secure/types';\n\nimport { buildURL as buildUrlUtil, stringifyQueryParams } from '../utils';\n\nexport type HTTPMethod =\n | 'CONNECT'\n | 'DELETE'\n | 'GET'\n | 'HEAD'\n | 'OPTIONS'\n | 'PATCH'\n | 'POST'\n | 'PUT'\n | 'TRACE';\n\nexport type ApiRequestInit = RequestInit & {\n path?: string;\n search?: ConstructorParameters<typeof URLSearchParams>[0];\n sessionId?: string;\n url?: URL;\n};\n\nexport interface ApiResponseJSON<T> {\n response: T;\n errors?: TernSecureApiErrorJSON[];\n}\n\nexport type ApiResponse<T> = Response & { payload: ApiResponseJSON<T> | null };\n\nexport type ApiRequestCallback<T> = (request: ApiRequestInit, response?: ApiResponse<T>) => unknown;\n\nexport interface ApiRequestOptions {\n timeoutMs?: number;\n maxTries?: number;\n initialDelay?: number;\n factor?: number;\n maxDelay?: number;\n failureThreshold?: number;\n recoveryTimeoutMs?: number;\n}\n\nexport interface ApiClientOptions {\n domain?: string;\n apiUrl?: string;\n frontendApi?: string;\n instanceType?: InstanceType;\n}\n\nexport interface ApiClient {\n onBeforeRequest: (hook: BeforeRequestHook) => void;\n onAfterResponse: (hook: AfterResponseHook) => void;\n request: <T>(init: ApiRequestInit, opts?: ApiRequestOptions) => Promise<ApiResponse<T>>;\n}\n\nexport type BeforeRequestHook = () => boolean | Promise<boolean>;\nexport type AfterResponseHook = (response: ApiResponse<any>) => boolean | Promise<boolean>;\n\n// Error classes\nexport class NetworkError extends Error {\n constructor(\n public url: string,\n public original: Error,\n ) {\n super(`Network error for ${url}: ${original.message}`);\n this.name = 'NetworkError';\n }\n}\n\nexport class TimeoutError extends Error {\n constructor() {\n super('Request timed out');\n this.name = 'TimeoutError';\n }\n}\n\nexport class CircuitOpenError extends Error {\n constructor() {\n super('Circuit breaker is open');\n this.name = 'CircuitOpenError';\n }\n}\n\nexport class HTTPError extends Error {\n constructor(\n public status: number,\n public url: string,\n public body?: any,\n ) {\n super(`HTTP ${status} error for ${url}`);\n this.name = 'HTTPError';\n }\n}\n\n// Circuit breaker state interface\ninterface CircuitBreakerState {\n failures: number;\n lastFailureTime: number;\n state: 'closed' | 'open' | 'half-open';\n}\n\n// Client state interface\ninterface ClientState {\n circuitBreaker: CircuitBreakerState;\n beforeRequestHooks: BeforeRequestHook[];\n afterResponseHooks: AfterResponseHook[];\n clientOptions: ApiClientOptions;\n}\n\n// Utility functions\nfunction camelToSnake(str: string): string {\n return str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);\n}\n\nfunction jitteredDelay(delay: number): number {\n return delay * Math.random();\n}\n\nfunction createInitialState(clientOptions: ApiClientOptions = {}): ClientState {\n return {\n circuitBreaker: {\n failures: 0,\n lastFailureTime: 0,\n state: 'closed',\n },\n beforeRequestHooks: [],\n afterResponseHooks: [],\n clientOptions,\n };\n}\n\nfunction addBeforeRequestHook(state: ClientState, hook: BeforeRequestHook): void {\n state.beforeRequestHooks.push(hook);\n}\n\nfunction addAfterResponseHook(state: ClientState, hook: AfterResponseHook): void {\n state.afterResponseHooks.push(hook);\n}\n\nasync function runBeforeRequestHooks(state: ClientState): Promise<boolean> {\n for (const hook of state.beforeRequestHooks) {\n const result = await hook();\n if (result === false) return false;\n }\n return true;\n}\n\nasync function runAfterResponseHooks(\n state: ClientState,\n response: ApiResponse<any>,\n): Promise<void> {\n for (const hook of state.afterResponseHooks) {\n await hook(response);\n }\n}\n\nfunction checkCircuitBreaker(state: ClientState, requestOptions: ApiRequestOptions): void {\n const { recoveryTimeoutMs = 60000 } = requestOptions;\n const now = Date.now();\n\n if (state.circuitBreaker.state === 'open') {\n if (now - state.circuitBreaker.lastFailureTime >= recoveryTimeoutMs) {\n state.circuitBreaker.state = 'half-open';\n } else {\n throw new CircuitOpenError();\n }\n }\n}\n\nfunction recordSuccess(state: ClientState): void {\n state.circuitBreaker.failures = 0;\n state.circuitBreaker.state = 'closed';\n}\n\nfunction recordFailure(state: ClientState, requestOptions: ApiRequestOptions): void {\n const { failureThreshold = 5 } = requestOptions;\n state.circuitBreaker.failures++;\n state.circuitBreaker.lastFailureTime = Date.now();\n\n if (state.circuitBreaker.failures >= failureThreshold) {\n state.circuitBreaker.state = 'open';\n }\n}\n\nfunction shouldRetry(\n state: ClientState,\n requestOptions: ApiRequestOptions,\n error: any,\n method: string,\n attempt: number,\n maxTries: number,\n): boolean {\n const isRetryable =\n error instanceof NetworkError && method.toUpperCase() === 'GET' && attempt < maxTries;\n\n if (!isRetryable) {\n recordFailure(state, requestOptions);\n }\n\n return isRetryable;\n}\n\nasync function retryWithBackoff<T>(\n state: ClientState,\n requestOptions: ApiRequestOptions,\n attemptFn: () => Promise<T>,\n shouldRetryFn: (error: any, attempt: number) => boolean,\n): Promise<T> {\n const {\n initialDelay = 700,\n factor = 2,\n maxDelay = 5000,\n maxTries = typeof navigator !== 'undefined' && navigator.onLine ? 4 : 11,\n } = requestOptions;\n\n let lastError: any;\n\n for (let attempt = 1; attempt <= maxTries; attempt++) {\n try {\n const result = await attemptFn();\n recordSuccess(state);\n return result;\n } catch (error) {\n lastError = error;\n\n if (!shouldRetryFn(error, attempt)) {\n throw error;\n }\n\n recordFailure(state, requestOptions);\n\n if (attempt < maxTries) {\n const delay = Math.min(initialDelay * Math.pow(factor, attempt - 1), maxDelay);\n await new Promise(resolve => setTimeout(resolve, jitteredDelay(delay)));\n }\n }\n }\n\n throw lastError;\n}\n\nexport function createCoreApiClient(clientOptions: ApiClientOptions): ApiClient {\n function buildUrl(requestInit: ApiRequestInit): URL {\n const { path } = requestInit;\n const domainInProd = clientOptions.instanceType === 'production' ? clientOptions.domain : '';\n\n const baseUrl = `https://${domainInProd || clientOptions.apiUrl}`;\n\n return buildUrlUtil(\n {\n base: baseUrl,\n pathname: path,\n searchParams: requestInit.search ? new URLSearchParams(requestInit.search) : undefined,\n },\n { stringify: false },\n );\n }\n\n async function makeRequest<T>(\n state: ClientState,\n init: ApiRequestInit,\n opts: ApiRequestOptions = {},\n ): Promise<ApiResponse<T>> {\n const requestInit = { ...init };\n const { method = 'GET', body } = requestInit;\n const requestOptions = { ...opts };\n\n requestInit.url = buildUrl({ ...init });\n checkCircuitBreaker(state, requestOptions);\n\n const shouldContinue = await runBeforeRequestHooks(state);\n if (!shouldContinue) {\n const mockResponse = new Response('{}', {\n status: 200,\n }) as ApiResponse<T>;\n mockResponse.payload = { response: {} as T };\n await runAfterResponseHooks(state, mockResponse);\n return mockResponse;\n }\n\n const { timeoutMs } = requestOptions;\n\n const overwrittenRequestMethod = method === 'GET' ? 'GET' : 'POST';\n const url = requestInit.url.toString();\n\n console.log('Request URL:', url);\n\n requestInit.headers = new Headers(requestInit.headers);\n\n if (\n method !== 'GET' &&\n !(body instanceof FormData) &&\n !requestInit.headers.has('content-type')\n ) {\n requestInit.headers.set('content-type', 'application/json');\n }\n\n if (requestInit.headers.get('content-type') === 'application/x-www-form-urlencoded') {\n requestInit.body = body\n ? stringifyQueryParams(body as any as Record<string, string>, {\n keyEncoder: camelToSnake,\n })\n : body;\n } else if (requestInit.headers.get('content-type') === 'application/json' && body) {\n requestInit.body = typeof body === 'string' ? body : JSON.stringify(body);\n }\n\n const attemptRequest = async (): Promise<ApiResponse<T>> => {\n const controller = new AbortController();\n const timeoutId = timeoutMs\n ? setTimeout(() => {\n controller.abort();\n }, timeoutMs)\n : null;\n\n let response: Response;\n const fetchOpts: ApiRequestInit = {\n ...requestInit,\n credentials: 'include',\n method: overwrittenRequestMethod,\n };\n\n try {\n response = await fetch(url, fetchOpts);\n\n if (timeoutId) clearTimeout(timeoutId);\n\n let payload: ApiResponseJSON<T> | null = null;\n\n if (response.status === 204) {\n payload = null;\n } else {\n try {\n const json = await response.json();\n payload = json;\n } catch {\n payload = { response: {} as T };\n }\n }\n\n const apiResponse = response as ApiResponse<T>;\n apiResponse.payload = payload;\n\n await runAfterResponseHooks(state, apiResponse);\n\n return apiResponse;\n } catch (error: any) {\n if (timeoutId) clearTimeout(timeoutId);\n\n if (error.name === 'AbortError') {\n throw new TimeoutError();\n }\n\n throw new NetworkError(url, error);\n }\n };\n\n return retryWithBackoff(state, requestOptions, attemptRequest, (error, attempt) =>\n shouldRetry(\n state,\n requestOptions,\n error,\n overwrittenRequestMethod,\n attempt,\n requestOptions.maxTries || (typeof navigator !== 'undefined' && navigator.onLine ? 4 : 11),\n ),\n );\n }\n const state = createInitialState(clientOptions);\n\n return {\n onBeforeRequest: (hook: BeforeRequestHook) => addBeforeRequestHook(state, hook),\n onAfterResponse: (hook: AfterResponseHook) => addAfterResponseHook(state, hook),\n request: <T>(init: ApiRequestInit, opts: ApiRequestOptions = {}) =>\n makeRequest<T>(state, init, opts),\n };\n}\n"],"mappings":"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","names":["buildUrlUtil","state"]}
@@ -22,12 +22,11 @@ __export(Base_exports, {
22
22
  });
23
23
  module.exports = __toCommonJS(Base_exports);
24
24
  var import_browser = require("@tern-secure/shared/browser");
25
- var import_coreApiClient = require("../instance/coreApiClient");
26
25
  var import_Error = require("./Error");
27
26
  class TernSecureBase {
28
27
  static ternsecure;
29
- static get apiUrl() {
30
- return TernSecureBase.ternsecure.getApiUrl();
28
+ static get apiClient() {
29
+ return TernSecureBase.ternsecure.getApiClient();
31
30
  }
32
31
  static get authCookieManager() {
33
32
  return this.ternsecure.authCookieManager();
@@ -41,13 +40,9 @@ class TernSecureBase {
41
40
  */
42
41
  static async fetchFromCoreApi(requestInit) {
43
42
  var _a;
44
- if (!TernSecureBase.apiUrl) {
45
- throw new Error("API URL is not defined. Make sure TernSecureAuth is properly initialized.");
46
- }
47
- const apiUrl = this.ternsecure.apiUrl;
48
43
  let apiResponse;
49
44
  try {
50
- apiResponse = await import_coreApiClient.coreApiClient.request(requestInit, { apiUrl });
45
+ apiResponse = await TernSecureBase.apiClient.request(requestInit, { timeoutMs: 1e4 });
51
46
  } catch (error) {
52
47
  if (!(0, import_browser.isValidBrowserOnline)()) {
53
48
  console.warn(error);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/resources/Base.ts"],"sourcesContent":["import { isValidBrowserOnline } from '@tern-secure/shared/browser';\nimport type { TernSecureApiErrorJSON } from '@tern-secure/types';\n\nimport type { ApiRequestInit, ApiResponse, ApiResponseJSON } from '../instance/coreApiClient';\nimport { coreApiClient } from '../instance/coreApiClient';\nimport { TernSecureAPIResponseError } from './Error';\nimport type { AuthCookieManager,TernSecureAuth } from './internal';\n\nexport type HTTPMethod =\n | 'CONNECT'\n | 'DELETE'\n | 'GET'\n | 'HEAD'\n | 'OPTIONS'\n | 'PATCH'\n | 'POST'\n | 'PUT'\n | 'TRACE';\n\nexport type PostMutateParams = {\n action?: string | undefined;\n body?: any;\n method?: HTTPMethod | undefined;\n path?: string;\n};\n\nexport abstract class TernSecureBase {\n static ternsecure: TernSecureAuth;\n\n static get apiUrl() {\n return TernSecureBase.ternsecure.getApiUrl();\n }\n\n static get authCookieManager(): AuthCookieManager | undefined {\n return this.ternsecure.authCookieManager();\n }\n protected get authCookieManager(): AuthCookieManager | undefined {\n return TernSecureBase.authCookieManager;\n }\n\n /**\n * Core method to fetch data from API endpoints using coreApiClient\n * This method handles the complete request lifecycle including error handling\n */\n static async fetchFromCoreApi(requestInit: ApiRequestInit): Promise<ApiResponseJSON<any> | null> {\n if (!TernSecureBase.apiUrl) {\n throw new Error('API URL is not defined. Make sure TernSecureAuth is properly initialized.');\n }\n\n const apiUrl = this.ternsecure.apiUrl;\n\n let apiResponse: ApiResponse<any>;\n try {\n apiResponse = await coreApiClient.request(requestInit, { apiUrl });\n } catch (error) {\n if (!isValidBrowserOnline()) {\n console.warn(error);\n return null;\n }\n throw error;\n }\n\n const { payload, status, statusText, headers } = apiResponse;\n\n if (headers) {\n const country = headers.get('x-country');\n this.ternsecure.__internal_setCountry(country ? country.toLowerCase() : null);\n }\n\n if (status >= 200 && status <= 299) {\n return payload;\n }\n\n if (status >= 400) {\n const errors = payload?.errors as TernSecureApiErrorJSON[];\n const message = errors?.[0]?.message;\n\n const apiResponseOptions: ConstructorParameters<typeof TernSecureAPIResponseError>[1] = {\n data: errors,\n status,\n };\n if (status === 429 && headers) {\n const retryAfter = headers.get('retry-After');\n if (retryAfter) {\n const value = parseInt(retryAfter, 10);\n if (!isNaN(value)) {\n apiResponseOptions.retryAfter = value;\n }\n }\n }\n\n throw new TernSecureAPIResponseError(message || statusText, apiResponseOptions);\n }\n\n return null;\n }\n\n /**\n * Convenience method for making POST requests\n */\n static async basePost(params: PostMutateParams): Promise<ApiResponseJSON<any> | null> {\n return this.fetchFromCoreApi({ ...params, method: 'POST' });\n }\n\n /**\n * Instance method to fetch data from API endpoints\n */\n protected async fetchFromCoreApi(\n requestInit: ApiRequestInit,\n ): Promise<ApiResponseJSON<any> | null> {\n return TernSecureBase.fetchFromCoreApi(requestInit);\n }\n\n /**\n * Instance method for making POST requests\n */\n protected async basePost(params: PostMutateParams): Promise<ApiResponseJSON<any> | null> {\n return TernSecureBase.basePost(params);\n }\n\n /**\n * Protected instance method for making POST requests with specific path and body\n * This is designed to be used by child classes like SignIn\n */\n protected async _post(params: PostMutateParams): Promise<ApiResponseJSON<any> | null> {\n return this.basePost({\n path: params.path,\n body: params.body\n });\n }\n\n static async makeApiRequest(requestInit: ApiRequestInit): Promise<ApiResponseJSON<any> | null> {\n return this.fetchFromCoreApi(requestInit);\n }\n\n protected async makeApiRequest(\n requestInit: ApiRequestInit,\n ): Promise<ApiResponseJSON<any> | null> {\n return this.fetchFromCoreApi(requestInit);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAAqC;AAIrC,2BAA8B;AAC9B,mBAA2C;AAqBpC,MAAe,eAAe;AAAA,EACnC,OAAO;AAAA,EAEP,WAAW,SAAS;AAClB,WAAO,eAAe,WAAW,UAAU;AAAA,EAC7C;AAAA,EAEA,WAAW,oBAAmD;AAC5D,WAAO,KAAK,WAAW,kBAAkB;AAAA,EAC3C;AAAA,EACA,IAAc,oBAAmD;AAC/D,WAAO,eAAe;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa,iBAAiB,aAAmE;AA5CnG;AA6CI,QAAI,CAAC,eAAe,QAAQ;AAC1B,YAAM,IAAI,MAAM,2EAA2E;AAAA,IAC7F;AAEA,UAAM,SAAS,KAAK,WAAW;AAE/B,QAAI;AACJ,QAAI;AACF,oBAAc,MAAM,mCAAc,QAAQ,aAAa,EAAE,OAAO,CAAC;AAAA,IACnE,SAAS,OAAO;AACd,UAAI,KAAC,qCAAqB,GAAG;AAC3B,gBAAQ,KAAK,KAAK;AAClB,eAAO;AAAA,MACT;AACA,YAAM;AAAA,IACR;AAEA,UAAM,EAAE,SAAS,QAAQ,YAAY,QAAQ,IAAI;AAEjD,QAAI,SAAS;AACX,YAAM,UAAU,QAAQ,IAAI,WAAW;AACvC,WAAK,WAAW,sBAAsB,UAAU,QAAQ,YAAY,IAAI,IAAI;AAAA,IAC9E;AAEA,QAAI,UAAU,OAAO,UAAU,KAAK;AAClC,aAAO;AAAA,IACT;AAEA,QAAI,UAAU,KAAK;AACjB,YAAM,SAAS,mCAAS;AACxB,YAAM,WAAU,sCAAS,OAAT,mBAAa;AAE7B,YAAM,qBAAkF;AAAA,QACtF,MAAM;AAAA,QACN;AAAA,MACF;AACA,UAAI,WAAW,OAAO,SAAS;AAC7B,cAAM,aAAa,QAAQ,IAAI,aAAa;AAC5C,YAAI,YAAY;AACd,gBAAM,QAAQ,SAAS,YAAY,EAAE;AACrC,cAAI,CAAC,MAAM,KAAK,GAAG;AACjB,+BAAmB,aAAa;AAAA,UAClC;AAAA,QACF;AAAA,MACF;AAEA,YAAM,IAAI,wCAA2B,WAAW,YAAY,kBAAkB;AAAA,IAChF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,SAAS,QAAgE;AACpF,WAAO,KAAK,iBAAiB,EAAE,GAAG,QAAQ,QAAQ,OAAO,CAAC;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAgB,iBACd,aACsC;AACtC,WAAO,eAAe,iBAAiB,WAAW;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAgB,SAAS,QAAgE;AACvF,WAAO,eAAe,SAAS,MAAM;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAgB,MAAM,QAAgE;AACpF,WAAO,KAAK,SAAS;AAAA,MACnB,MAAM,OAAO;AAAA,MACb,MAAM,OAAO;AAAA,IACf,CAAC;AAAA,EACH;AAAA,EAEA,aAAa,eAAe,aAAmE;AAC7F,WAAO,KAAK,iBAAiB,WAAW;AAAA,EAC1C;AAAA,EAEA,MAAgB,eACd,aACsC;AACtC,WAAO,KAAK,iBAAiB,WAAW;AAAA,EAC1C;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/resources/Base.ts"],"sourcesContent":["import { isValidBrowserOnline } from '@tern-secure/shared/browser';\nimport type { TernSecureApiErrorJSON } from '@tern-secure/types';\n\nimport type { ApiRequestInit, ApiResponse, ApiResponseJSON } from '../instance/coreApiClient';\n//import { coreApiClient} from '../instance/coreApiClient';\nimport { TernSecureAPIResponseError } from './Error';\nimport type { AuthCookieManager,TernSecureAuth } from './internal';\n\nexport type HTTPMethod =\n | 'CONNECT'\n | 'DELETE'\n | 'GET'\n | 'HEAD'\n | 'OPTIONS'\n | 'PATCH'\n | 'POST'\n | 'PUT'\n | 'TRACE';\n\nexport type PostMutateParams = {\n action?: string | undefined;\n body?: any;\n method?: HTTPMethod | undefined;\n path?: string;\n};\n\nexport abstract class TernSecureBase {\n static ternsecure: TernSecureAuth;\n\n static get apiClient() {\n return TernSecureBase.ternsecure.getApiClient();\n }\n\n static get authCookieManager(): AuthCookieManager | undefined {\n return this.ternsecure.authCookieManager();\n }\n protected get authCookieManager(): AuthCookieManager | undefined {\n return TernSecureBase.authCookieManager;\n }\n\n /**\n * Core method to fetch data from API endpoints using coreApiClient\n * This method handles the complete request lifecycle including error handling\n */\n static async fetchFromCoreApi(requestInit: ApiRequestInit): Promise<ApiResponseJSON<any> | null> {\n\n let apiResponse: ApiResponse<any>;\n try {\n apiResponse = await TernSecureBase.apiClient.request(requestInit, { timeoutMs: 10000 });\n } catch (error) {\n if (!isValidBrowserOnline()) {\n console.warn(error);\n return null;\n }\n throw error;\n }\n\n const { payload, status, statusText, headers } = apiResponse;\n\n if (headers) {\n const country = headers.get('x-country');\n this.ternsecure.__internal_setCountry(country ? country.toLowerCase() : null);\n }\n\n if (status >= 200 && status <= 299) {\n return payload;\n }\n\n if (status >= 400) {\n const errors = payload?.errors as TernSecureApiErrorJSON[];\n const message = errors?.[0]?.message;\n\n const apiResponseOptions: ConstructorParameters<typeof TernSecureAPIResponseError>[1] = {\n data: errors,\n status,\n };\n if (status === 429 && headers) {\n const retryAfter = headers.get('retry-After');\n if (retryAfter) {\n const value = parseInt(retryAfter, 10);\n if (!isNaN(value)) {\n apiResponseOptions.retryAfter = value;\n }\n }\n }\n\n throw new TernSecureAPIResponseError(message || statusText, apiResponseOptions);\n }\n\n return null;\n }\n\n /**\n * Convenience method for making POST requests\n */\n static async basePost(params: PostMutateParams): Promise<ApiResponseJSON<any> | null> {\n return this.fetchFromCoreApi({ ...params, method: 'POST' });\n }\n\n /**\n * Instance method to fetch data from API endpoints\n */\n protected async fetchFromCoreApi(\n requestInit: ApiRequestInit,\n ): Promise<ApiResponseJSON<any> | null> {\n return TernSecureBase.fetchFromCoreApi(requestInit);\n }\n\n /**\n * Instance method for making POST requests\n */\n protected async basePost(params: PostMutateParams): Promise<ApiResponseJSON<any> | null> {\n return TernSecureBase.basePost(params);\n }\n\n /**\n * Protected instance method for making POST requests with specific path and body\n * This is designed to be used by child classes like SignIn\n */\n protected async _post(params: PostMutateParams): Promise<ApiResponseJSON<any> | null> {\n return this.basePost({\n path: params.path,\n body: params.body\n });\n }\n\n static async makeApiRequest(requestInit: ApiRequestInit): Promise<ApiResponseJSON<any> | null> {\n return this.fetchFromCoreApi(requestInit);\n }\n\n protected async makeApiRequest(\n requestInit: ApiRequestInit,\n ): Promise<ApiResponseJSON<any> | null> {\n return this.fetchFromCoreApi(requestInit);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAAqC;AAKrC,mBAA2C;AAqBpC,MAAe,eAAe;AAAA,EACnC,OAAO;AAAA,EAEP,WAAW,YAAY;AACrB,WAAO,eAAe,WAAW,aAAa;AAAA,EAChD;AAAA,EAEA,WAAW,oBAAmD;AAC5D,WAAO,KAAK,WAAW,kBAAkB;AAAA,EAC3C;AAAA,EACA,IAAc,oBAAmD;AAC/D,WAAO,eAAe;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa,iBAAiB,aAAmE;AA5CnG;AA8CI,QAAI;AACJ,QAAI;AACF,oBAAc,MAAM,eAAe,UAAU,QAAQ,aAAa,EAAE,WAAW,IAAM,CAAC;AAAA,IACxF,SAAS,OAAO;AACd,UAAI,KAAC,qCAAqB,GAAG;AAC3B,gBAAQ,KAAK,KAAK;AAClB,eAAO;AAAA,MACT;AACA,YAAM;AAAA,IACR;AAEA,UAAM,EAAE,SAAS,QAAQ,YAAY,QAAQ,IAAI;AAEjD,QAAI,SAAS;AACX,YAAM,UAAU,QAAQ,IAAI,WAAW;AACvC,WAAK,WAAW,sBAAsB,UAAU,QAAQ,YAAY,IAAI,IAAI;AAAA,IAC9E;AAEA,QAAI,UAAU,OAAO,UAAU,KAAK;AAClC,aAAO;AAAA,IACT;AAEA,QAAI,UAAU,KAAK;AACjB,YAAM,SAAS,mCAAS;AACxB,YAAM,WAAU,sCAAS,OAAT,mBAAa;AAE7B,YAAM,qBAAkF;AAAA,QACtF,MAAM;AAAA,QACN;AAAA,MACF;AACA,UAAI,WAAW,OAAO,SAAS;AAC7B,cAAM,aAAa,QAAQ,IAAI,aAAa;AAC5C,YAAI,YAAY;AACd,gBAAM,QAAQ,SAAS,YAAY,EAAE;AACrC,cAAI,CAAC,MAAM,KAAK,GAAG;AACjB,+BAAmB,aAAa;AAAA,UAClC;AAAA,QACF;AAAA,MACF;AAEA,YAAM,IAAI,wCAA2B,WAAW,YAAY,kBAAkB;AAAA,IAChF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,SAAS,QAAgE;AACpF,WAAO,KAAK,iBAAiB,EAAE,GAAG,QAAQ,QAAQ,OAAO,CAAC;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAgB,iBACd,aACsC;AACtC,WAAO,eAAe,iBAAiB,WAAW;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAgB,SAAS,QAAgE;AACvF,WAAO,eAAe,SAAS,MAAM;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAgB,MAAM,QAAgE;AACpF,WAAO,KAAK,SAAS;AAAA,MACnB,MAAM,OAAO;AAAA,MACb,MAAM,OAAO;AAAA,IACf,CAAC;AAAA,EACH;AAAA,EAEA,aAAa,eAAe,aAAmE;AAC7F,WAAO,KAAK,iBAAiB,WAAW;AAAA,EAC1C;AAAA,EAEA,MAAgB,eACd,aACsC;AACtC,WAAO,KAAK,iBAAiB,WAAW;AAAA,EAC1C;AACF;","names":[]}