@tern-secure/auth 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/dist/cjs/global.d.js +2 -0
  2. package/dist/cjs/global.d.js.map +1 -0
  3. package/dist/cjs/index.js +42 -0
  4. package/dist/cjs/index.js.map +1 -0
  5. package/dist/cjs/instance/TernAuth.js +471 -0
  6. package/dist/cjs/instance/TernAuth.js.map +1 -0
  7. package/dist/cjs/instance/TernAuthServer.js +95 -0
  8. package/dist/cjs/instance/TernAuthServer.js.map +1 -0
  9. package/dist/cjs/instance/coreApiClient.example.js +96 -0
  10. package/dist/cjs/instance/coreApiClient.example.js.map +1 -0
  11. package/dist/cjs/instance/coreApiClient.js +255 -0
  12. package/dist/cjs/instance/coreApiClient.js.map +1 -0
  13. package/dist/cjs/instance/events.js +38 -0
  14. package/dist/cjs/instance/events.js.map +1 -0
  15. package/dist/cjs/resources/AuthCookieManager.js +89 -0
  16. package/dist/cjs/resources/AuthCookieManager.js.map +1 -0
  17. package/dist/cjs/resources/Base.js +125 -0
  18. package/dist/cjs/resources/Base.js.map +1 -0
  19. package/dist/cjs/resources/Error.js +31 -0
  20. package/dist/cjs/resources/Error.js.map +1 -0
  21. package/dist/cjs/resources/SignIn.js +224 -0
  22. package/dist/cjs/resources/SignIn.js.map +1 -0
  23. package/dist/cjs/resources/SignUp.js +43 -0
  24. package/dist/cjs/resources/SignUp.js.map +1 -0
  25. package/dist/cjs/resources/index.js +23 -0
  26. package/dist/cjs/resources/index.js.map +1 -0
  27. package/dist/cjs/resources/internal.js +33 -0
  28. package/dist/cjs/resources/internal.js.map +1 -0
  29. package/dist/cjs/utils/construct.js +174 -0
  30. package/dist/cjs/utils/construct.js.map +1 -0
  31. package/dist/cjs/utils/index.js +25 -0
  32. package/dist/cjs/utils/index.js.map +1 -0
  33. package/dist/cjs/utils/querystring.js +70 -0
  34. package/dist/cjs/utils/querystring.js.map +1 -0
  35. package/dist/esm/global.d.js +1 -0
  36. package/dist/esm/global.d.js.map +1 -0
  37. package/dist/esm/index.js +13 -0
  38. package/dist/esm/index.js.map +1 -0
  39. package/dist/esm/instance/TernAuth.js +455 -0
  40. package/dist/esm/instance/TernAuth.js.map +1 -0
  41. package/dist/esm/instance/TernAuthServer.js +73 -0
  42. package/dist/esm/instance/TernAuthServer.js.map +1 -0
  43. package/dist/esm/instance/coreApiClient.example.js +70 -0
  44. package/dist/esm/instance/coreApiClient.example.js.map +1 -0
  45. package/dist/esm/instance/coreApiClient.js +226 -0
  46. package/dist/esm/instance/coreApiClient.js.map +1 -0
  47. package/dist/esm/instance/events.js +13 -0
  48. package/dist/esm/instance/events.js.map +1 -0
  49. package/dist/esm/resources/AuthCookieManager.js +67 -0
  50. package/dist/esm/resources/AuthCookieManager.js.map +1 -0
  51. package/dist/esm/resources/Base.js +101 -0
  52. package/dist/esm/resources/Base.js.map +1 -0
  53. package/dist/esm/resources/Error.js +9 -0
  54. package/dist/esm/resources/Error.js.map +1 -0
  55. package/dist/esm/resources/SignIn.js +208 -0
  56. package/dist/esm/resources/SignIn.js.map +1 -0
  57. package/dist/esm/resources/SignUp.js +19 -0
  58. package/dist/esm/resources/SignUp.js.map +1 -0
  59. package/dist/esm/resources/index.js +2 -0
  60. package/dist/esm/resources/index.js.map +1 -0
  61. package/dist/esm/resources/internal.js +7 -0
  62. package/dist/esm/resources/internal.js.map +1 -0
  63. package/dist/esm/utils/construct.js +143 -0
  64. package/dist/esm/utils/construct.js.map +1 -0
  65. package/dist/esm/utils/index.js +3 -0
  66. package/dist/esm/utils/index.js.map +1 -0
  67. package/dist/esm/utils/querystring.js +45 -0
  68. package/dist/esm/utils/querystring.js.map +1 -0
  69. package/dist/types/index.d.ts +9 -0
  70. package/dist/types/index.d.ts.map +1 -0
  71. package/dist/types/instance/TernAuth.d.ts +62 -0
  72. package/dist/types/instance/TernAuth.d.ts.map +1 -0
  73. package/dist/types/instance/TernAuthServer.d.ts +32 -0
  74. package/dist/types/instance/TernAuthServer.d.ts.map +1 -0
  75. package/dist/types/instance/coreApiClient.d.ts +65 -0
  76. package/dist/types/instance/coreApiClient.d.ts.map +1 -0
  77. package/dist/types/instance/coreApiClient.example.d.ts +8 -0
  78. package/dist/types/instance/coreApiClient.example.d.ts.map +1 -0
  79. package/dist/types/instance/events.d.ts +27 -0
  80. package/dist/types/instance/events.d.ts.map +1 -0
  81. package/dist/types/resources/AuthCookieManager.d.ts +26 -0
  82. package/dist/types/resources/AuthCookieManager.d.ts.map +1 -0
  83. package/dist/types/resources/Base.d.ts +40 -0
  84. package/dist/types/resources/Base.d.ts.map +1 -0
  85. package/dist/types/resources/Error.d.ts +2 -0
  86. package/dist/types/resources/Error.d.ts.map +1 -0
  87. package/dist/types/resources/SignIn.d.ts +32 -0
  88. package/dist/types/resources/SignIn.d.ts.map +1 -0
  89. package/dist/types/resources/SignUp.d.ts +14 -0
  90. package/dist/types/resources/SignUp.d.ts.map +1 -0
  91. package/dist/types/resources/index.d.ts +2 -0
  92. package/dist/types/resources/index.d.ts.map +1 -0
  93. package/dist/types/resources/internal.d.ts +8 -0
  94. package/dist/types/resources/internal.d.ts.map +1 -0
  95. package/dist/types/utils/construct.d.ts +67 -0
  96. package/dist/types/utils/construct.d.ts.map +1 -0
  97. package/dist/types/utils/index.d.ts +3 -0
  98. package/dist/types/utils/index.d.ts.map +1 -0
  99. package/dist/types/utils/querystring.d.ts +7 -0
  100. package/dist/types/utils/querystring.d.ts.map +1 -0
  101. package/package.json +50 -0
@@ -0,0 +1,70 @@
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 querystring_exports = {};
20
+ __export(querystring_exports, {
21
+ getQueryParams: () => getQueryParams,
22
+ stringifyQueryParams: () => stringifyQueryParams
23
+ });
24
+ module.exports = __toCommonJS(querystring_exports);
25
+ const getQueryParams = (queryString) => {
26
+ const queryParamsObject = {};
27
+ const queryParams = new URLSearchParams(queryString);
28
+ queryParams.forEach((value, key) => {
29
+ if (key in queryParamsObject) {
30
+ const existingValue = queryParamsObject[key];
31
+ if (Array.isArray(existingValue)) {
32
+ existingValue.push(value);
33
+ } else {
34
+ queryParamsObject[key] = [existingValue, value];
35
+ }
36
+ } else {
37
+ queryParamsObject[key] = value;
38
+ }
39
+ });
40
+ return queryParamsObject;
41
+ };
42
+ const stringifyQueryParams = (params, opts = {}) => {
43
+ if (params === null || params === void 0) {
44
+ return "";
45
+ }
46
+ if (!params || typeof params !== "object") {
47
+ return "";
48
+ }
49
+ const queryParams = new URLSearchParams();
50
+ Object.keys(params).forEach((key) => {
51
+ const encodedKey = opts.keyEncoder ? opts.keyEncoder(key) : key;
52
+ const value = params[key];
53
+ if (Array.isArray(value)) {
54
+ value.forEach((v) => v !== void 0 && queryParams.append(encodedKey, v || ""));
55
+ } else if (value === void 0) {
56
+ return;
57
+ } else if (typeof value === "object" && value !== null) {
58
+ queryParams.append(encodedKey, JSON.stringify(value));
59
+ } else {
60
+ queryParams.append(encodedKey, String(value ?? ""));
61
+ }
62
+ });
63
+ return queryParams.toString();
64
+ };
65
+ // Annotate the CommonJS export names for ESM import in node:
66
+ 0 && (module.exports = {
67
+ getQueryParams,
68
+ stringifyQueryParams
69
+ });
70
+ //# sourceMappingURL=querystring.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/querystring.ts"],"sourcesContent":["export const getQueryParams = (queryString: string) => {\n const queryParamsObject: { [key: string]: string | string[] } = {};\n const queryParams = new URLSearchParams(queryString);\n queryParams.forEach((value, key) => {\n if (key in queryParamsObject) {\n // If the key already exists, we need to handle it as an array\n const existingValue = queryParamsObject[key];\n if (Array.isArray(existingValue)) {\n existingValue.push(value);\n } else {\n queryParamsObject[key] = [existingValue, value];\n }\n } else {\n queryParamsObject[key] = value;\n }\n });\n return queryParamsObject as Record<string, string>;\n};\n\ntype StringifyQueryParamsOptions = {\n keyEncoder?: (key: string) => string;\n};\n\nexport const stringifyQueryParams = (\n params:\n | Record<string, string | undefined | null | object | boolean | Array<string | undefined | null>>\n | null\n | undefined\n | string,\n opts: StringifyQueryParamsOptions = {},\n) => {\n if (params === null || params === undefined) {\n return '';\n }\n if (!params || typeof params !== 'object') {\n return '';\n }\n\n const queryParams = new URLSearchParams();\n\n Object.keys(params).forEach(key => {\n const encodedKey = opts.keyEncoder ? opts.keyEncoder(key) : key;\n const value = params[key];\n if (Array.isArray(value)) {\n value.forEach(v => v !== undefined && queryParams.append(encodedKey, v || ''));\n } else if (value === undefined) {\n return;\n } else if (typeof value === 'object' && value !== null) {\n queryParams.append(encodedKey, JSON.stringify(value));\n } else {\n queryParams.append(encodedKey, String(value ?? ''));\n }\n });\n\n return queryParams.toString();\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,MAAM,iBAAiB,CAAC,gBAAwB;AACrD,QAAM,oBAA0D,CAAC;AACjE,QAAM,cAAc,IAAI,gBAAgB,WAAW;AACnD,cAAY,QAAQ,CAAC,OAAO,QAAQ;AAClC,QAAI,OAAO,mBAAmB;AAE5B,YAAM,gBAAgB,kBAAkB,GAAG;AAC3C,UAAI,MAAM,QAAQ,aAAa,GAAG;AAChC,sBAAc,KAAK,KAAK;AAAA,MAC1B,OAAO;AACL,0BAAkB,GAAG,IAAI,CAAC,eAAe,KAAK;AAAA,MAChD;AAAA,IACF,OAAO;AACL,wBAAkB,GAAG,IAAI;AAAA,IAC3B;AAAA,EACF,CAAC;AACD,SAAO;AACT;AAMO,MAAM,uBAAuB,CAClC,QAKA,OAAoC,CAAC,MAClC;AACH,MAAI,WAAW,QAAQ,WAAW,QAAW;AAC3C,WAAO;AAAA,EACT;AACA,MAAI,CAAC,UAAU,OAAO,WAAW,UAAU;AACzC,WAAO;AAAA,EACT;AAEA,QAAM,cAAc,IAAI,gBAAgB;AAExC,SAAO,KAAK,MAAM,EAAE,QAAQ,SAAO;AACjC,UAAM,aAAa,KAAK,aAAa,KAAK,WAAW,GAAG,IAAI;AAC5D,UAAM,QAAQ,OAAO,GAAG;AACxB,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,YAAM,QAAQ,OAAK,MAAM,UAAa,YAAY,OAAO,YAAY,KAAK,EAAE,CAAC;AAAA,IAC/E,WAAW,UAAU,QAAW;AAC9B;AAAA,IACF,WAAW,OAAO,UAAU,YAAY,UAAU,MAAM;AACtD,kBAAY,OAAO,YAAY,KAAK,UAAU,KAAK,CAAC;AAAA,IACtD,OAAO;AACL,kBAAY,OAAO,YAAY,OAAO,SAAS,EAAE,CAAC;AAAA,IACpD;AAAA,EACF,CAAC;AAED,SAAO,YAAY,SAAS;AAC9B;","names":[]}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=global.d.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,13 @@
1
+ import { TernSecureAuth } from "./instance/TernAuth";
2
+ import { TernServerAuth } from "./instance/TernAuthServer";
3
+ import { CoreApiClient, coreApiClient } from "./instance/coreApiClient";
4
+ import { SignIn, TernSecureBase } from "./resources/internal";
5
+ export {
6
+ CoreApiClient,
7
+ SignIn,
8
+ TernSecureAuth,
9
+ TernSecureBase,
10
+ TernServerAuth,
11
+ coreApiClient
12
+ };
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["export { TernSecureAuth } from './instance/TernAuth';\nexport type { TernAuth } from './instance/TernAuth';\nexport { TernServerAuth } from './instance/TernAuthServer';\nexport type { TernServerAuthOptions, AuthenticatedApp } from './instance/TernAuthServer';\n\nexport { CoreApiClient, coreApiClient } from './instance/coreApiClient';\nexport type { \n ApiResponse, \n ApiResponseJSON, \n RequestOptions,\n BeforeRequestHook,\n AfterResponseHook\n} from './instance/coreApiClient';\n\nexport { SignIn, TernSecureBase } from './resources/internal';\n\nexport type {\n TernSecureConfig,\n SignInFormValuesTree,\n SignInResponseTree,\n ResendEmailVerification,\n TernSecureUser,\n TernSecureState\n} from '@tern-secure/types';"],"mappings":"AAAA,SAAS,sBAAsB;AAE/B,SAAS,sBAAsB;AAG/B,SAAS,eAAe,qBAAqB;AAS7C,SAAS,QAAQ,sBAAsB;","names":[]}
@@ -0,0 +1,455 @@
1
+ import { handleFirebaseAuthError } from "@tern-secure/shared/errors";
2
+ import { createTernAuthEventBus, ternEvents } from "@tern-secure/shared/ternStatusEvent";
3
+ import { stripScheme } from "@tern-secure/shared/url";
4
+ import { handleValueOrFn } from "@tern-secure/shared/utils";
5
+ import { getApps, initializeApp } from "firebase/app";
6
+ import {
7
+ browserLocalPersistence,
8
+ browserSessionPersistence,
9
+ connectAuthEmulator,
10
+ getRedirectResult,
11
+ initializeAuth,
12
+ inMemoryPersistence,
13
+ onAuthStateChanged,
14
+ onIdTokenChanged
15
+ } from "firebase/auth";
16
+ import { browserCookiePersistence } from "firebase/auth/web-extension";
17
+ import { getInstallations } from "firebase/installations";
18
+ import { AuthCookieManager, SignIn, SignUp, TernSecureBase } from "../resources/internal";
19
+ import { buildURL } from "../utils/construct";
20
+ import { eventBus, events } from "./events";
21
+ function inBrowser() {
22
+ return typeof window !== "undefined";
23
+ }
24
+ class TernSecureAuth {
25
+ static version = "1.0.0";
26
+ static sdkMetadata = {
27
+ name: "@tern-secure/auth",
28
+ version: "1.0.0",
29
+ environment: process.env.NODE_ENV || "production"
30
+ };
31
+ static instance = null;
32
+ _currentUser = null;
33
+ signedInSession = null;
34
+ firebaseClientApp;
35
+ authStateUnsubscribe = null;
36
+ auth;
37
+ csrfToken;
38
+ isLoading = false;
39
+ error = null;
40
+ user = null;
41
+ __internal_country;
42
+ #domain;
43
+ #apiUrl;
44
+ #instanceType;
45
+ #status = "loading";
46
+ #listeners = [];
47
+ #options = {};
48
+ #authCookieManager;
49
+ #publicEventBus = createTernAuthEventBus();
50
+ signIn;
51
+ signUp;
52
+ get isReady() {
53
+ return this.status === "ready";
54
+ }
55
+ get status() {
56
+ return this.#status;
57
+ }
58
+ get version() {
59
+ return TernSecureAuth.version;
60
+ }
61
+ set sdkMetadata(metadata) {
62
+ TernSecureAuth.sdkMetadata = metadata;
63
+ }
64
+ get sdkMetadata() {
65
+ return TernSecureAuth.sdkMetadata;
66
+ }
67
+ get requiresVerification() {
68
+ return this.#options.requiresVerification ?? true;
69
+ }
70
+ get apiUrl() {
71
+ return this.#apiUrl;
72
+ }
73
+ getApiUrl = () => this.#apiUrl;
74
+ get domain() {
75
+ if (inBrowser()) {
76
+ const strippedDomainString = stripScheme(
77
+ handleValueOrFn(this.#domain, new URL(window.location.href))
78
+ );
79
+ if (this.#instanceType === "production") {
80
+ return strippedDomainString;
81
+ }
82
+ return strippedDomainString;
83
+ }
84
+ return "";
85
+ }
86
+ get instanceType() {
87
+ return this.#instanceType;
88
+ }
89
+ constructor(options) {
90
+ var _a;
91
+ this.#domain = (_a = options == null ? void 0 : options.ternSecureConfig) == null ? void 0 : _a.authDomain;
92
+ this.#apiUrl = (options == null ? void 0 : options.apiUrl) || "";
93
+ this.#instanceType = process.env.NODE_ENV || "production";
94
+ this.#publicEventBus.emit(ternEvents.Status, "loading");
95
+ TernSecureBase.ternsecure = this;
96
+ }
97
+ setLoading(isLoading) {
98
+ this.isLoading = isLoading;
99
+ }
100
+ authCookieManager() {
101
+ return this.#authCookieManager;
102
+ }
103
+ static getorCreateInstance(options) {
104
+ if (!this.instance) {
105
+ this.instance = new TernSecureAuth(options);
106
+ }
107
+ console.log("[TernSecureAuth] TernSecureAuth instance:", this.instance);
108
+ return this.instance;
109
+ }
110
+ static clearInstance() {
111
+ if (TernSecureAuth.instance) {
112
+ if (TernSecureAuth.instance.authStateUnsubscribe) {
113
+ TernSecureAuth.instance.authStateUnsubscribe();
114
+ TernSecureAuth.instance.authStateUnsubscribe = null;
115
+ }
116
+ TernSecureAuth.instance = null;
117
+ }
118
+ }
119
+ static initialize(options) {
120
+ const instance = this.getorCreateInstance(options);
121
+ instance.#initialize(options);
122
+ return instance;
123
+ }
124
+ #initialize = (options) => {
125
+ this.#options = this.#initOptions(options);
126
+ try {
127
+ if (!this.#options.ternSecureConfig) {
128
+ throw new Error("TernSecureConfig is required to initialize TernSecureAuth");
129
+ }
130
+ if (!this.#options.apiUrl) {
131
+ throw new Error("apiUrl is required to initialize TernSecureAuth");
132
+ }
133
+ this.initializeFirebaseApp(this.#options.ternSecureConfig);
134
+ this.authStateUnsubscribe = this.initAuthStateListener();
135
+ this._onIdTokenChanged();
136
+ this.#authCookieManager = new AuthCookieManager();
137
+ this.csrfToken = this.#authCookieManager.getCSRFToken();
138
+ this.signIn = new SignIn(this.auth, this.csrfToken);
139
+ this.signUp = new SignUp(this.auth);
140
+ this.#setStatus("ready");
141
+ this.#publicEventBus.emit(ternEvents.Status, "ready");
142
+ return this;
143
+ } catch (error) {
144
+ this.error = error;
145
+ this.#setStatus("error");
146
+ this.#publicEventBus.emit(ternEvents.Status, "error");
147
+ throw error;
148
+ }
149
+ };
150
+ initializeFirebaseApp(config) {
151
+ const appName = config.appName || "[DEFAULT]";
152
+ this.firebaseClientApp = getApps().length === 0 ? initializeApp(config, appName) : getApps()[0];
153
+ const persistence = this.#setPersistence();
154
+ const auth = initializeAuth(this.firebaseClientApp, {
155
+ persistence
156
+ });
157
+ this.auth = auth;
158
+ if (config.tenantId) {
159
+ this.auth.tenantId = config.tenantId;
160
+ }
161
+ this.#configureEmulator();
162
+ getInstallations(this.firebaseClientApp);
163
+ }
164
+ signOut = async (options) => {
165
+ const redirectUrl = (options == null ? void 0 : options.redirectUrl) || this.#constructAfterSignOutUrl();
166
+ if (options == null ? void 0 : options.onBeforeSignOut) {
167
+ await options.onBeforeSignOut();
168
+ }
169
+ await this.auth.signOut();
170
+ if (options == null ? void 0 : options.onAfterSignOut) {
171
+ await options.onAfterSignOut();
172
+ }
173
+ if (inBrowser()) {
174
+ window.location.href = redirectUrl;
175
+ }
176
+ eventBus.emit(events.UserSignOut, null);
177
+ eventBus.emit(events.TokenRefreshed, { token: null });
178
+ this.#emit();
179
+ };
180
+ get currentSession() {
181
+ return this.signedInSession;
182
+ }
183
+ initAuthStateListener() {
184
+ return onAuthStateChanged(this.auth, async (user) => {
185
+ await this.auth.authStateReady();
186
+ this._currentUser = user;
187
+ await this.updateCurrentSession();
188
+ eventBus.emit(events.UserChanged, this._currentUser);
189
+ this.#emit();
190
+ });
191
+ }
192
+ _onIdTokenChanged() {
193
+ return onIdTokenChanged(this.auth, async (user) => {
194
+ await this.auth.authStateReady();
195
+ this._currentUser = user;
196
+ await this.updateCurrentSession();
197
+ eventBus.emit(events.TokenRefreshed, { token: user ? await user.getIdTokenResult() : null });
198
+ this.#emit();
199
+ });
200
+ }
201
+ onAuthStateChanged(callback) {
202
+ return onAuthStateChanged(this.auth, callback);
203
+ }
204
+ onIdTokenChanged(callback) {
205
+ return onIdTokenChanged(this.auth, callback);
206
+ }
207
+ async updateCurrentSession() {
208
+ if (!this._currentUser) {
209
+ this.signedInSession = null;
210
+ return;
211
+ }
212
+ try {
213
+ const res = await this._currentUser.getIdTokenResult();
214
+ this.signedInSession = {
215
+ status: "active",
216
+ token: res.token,
217
+ claims: res.claims,
218
+ issuedAtTime: res.issuedAtTime,
219
+ expirationTime: res.expirationTime,
220
+ authTime: res.authTime,
221
+ signInProvider: res.signInProvider || "unknown"
222
+ };
223
+ } catch (error) {
224
+ console.error("[TernSecureAuth] Error updating session:", error);
225
+ this.signedInSession = null;
226
+ }
227
+ }
228
+ async checkRedirectResult() {
229
+ try {
230
+ const result = await getRedirectResult(this.auth);
231
+ if (result) {
232
+ return {
233
+ success: true,
234
+ user: result.user
235
+ };
236
+ }
237
+ return null;
238
+ } catch (error) {
239
+ const authError = handleFirebaseAuthError(error);
240
+ return {
241
+ success: false,
242
+ message: authError.message,
243
+ error: authError.code,
244
+ user: null
245
+ };
246
+ }
247
+ }
248
+ addListener = (listener) => {
249
+ this.#listeners.push(listener);
250
+ if (this._currentUser) {
251
+ listener({
252
+ user: this._currentUser,
253
+ session: this.signedInSession
254
+ });
255
+ }
256
+ const unsubscribe = () => {
257
+ this.#listeners = this.#listeners.filter((l) => l !== listener);
258
+ };
259
+ return unsubscribe;
260
+ };
261
+ on = (...args) => {
262
+ this.#publicEventBus.on(...args);
263
+ };
264
+ off = (...args) => {
265
+ this.#publicEventBus.off(...args);
266
+ };
267
+ initialize(options) {
268
+ this._initialize(options);
269
+ return Promise.resolve();
270
+ }
271
+ static create(options) {
272
+ const instance = this.getorCreateInstance();
273
+ instance.initialize(options);
274
+ return instance;
275
+ }
276
+ _initialize = (options) => {
277
+ this.#options = this.#initOptions(options);
278
+ try {
279
+ if (!this.#options.ternSecureConfig) {
280
+ throw new Error("TernSecureConfig is required to initialize TernSecureAuth");
281
+ }
282
+ if (!this.#options.apiUrl) {
283
+ throw new Error("apiUrl is required to initialize TernSecureAuth");
284
+ }
285
+ this.#apiUrl = this.#options.apiUrl;
286
+ this.initializeFirebaseApp(this.#options.ternSecureConfig);
287
+ this.signIn = new SignIn(this.auth, this.csrfToken);
288
+ this.signUp = new SignUp(this.auth);
289
+ this.#setStatus("ready");
290
+ } catch (error) {
291
+ this.error = error;
292
+ this.#setStatus("error");
293
+ throw error;
294
+ }
295
+ };
296
+ constructUrlWithAuthRedirect = (to) => {
297
+ const baseUrl = window.location.origin;
298
+ const url = new URL(to, baseUrl);
299
+ if (url.origin === window.location.origin) {
300
+ return url.href;
301
+ }
302
+ return url.toString();
303
+ };
304
+ #buildUrl = (key, options) => {
305
+ var _a, _b;
306
+ if (!key || !this.isReady) {
307
+ return "";
308
+ }
309
+ const baseUrlConfig = key === "signInUrl" ? this.#options.signInUrl : this.#options.signUpUrl;
310
+ const defaultPagePath = key === "signInUrl" ? "/sign-in" : "/sign-up";
311
+ const base = baseUrlConfig || defaultPagePath;
312
+ let effectiveRedirectUrl;
313
+ if (key === "signInUrl" && "signInForceRedirectUrl" in options) {
314
+ effectiveRedirectUrl = options.signInForceRedirectUrl;
315
+ } else if (key === "signUpUrl" && "signUpForceRedirectUrl" in options) {
316
+ effectiveRedirectUrl = options.signUpForceRedirectUrl;
317
+ }
318
+ if (!effectiveRedirectUrl && inBrowser()) {
319
+ const currentUrlParams = new URLSearchParams(window.location.search);
320
+ const existingRedirectParam = currentUrlParams.get("redirect_url");
321
+ if (existingRedirectParam) {
322
+ effectiveRedirectUrl = existingRedirectParam;
323
+ }
324
+ }
325
+ if (!effectiveRedirectUrl && inBrowser()) {
326
+ effectiveRedirectUrl = window.location.pathname + window.location.search + window.location.hash;
327
+ }
328
+ if (effectiveRedirectUrl && inBrowser()) {
329
+ let signInPagePath;
330
+ try {
331
+ signInPagePath = this.#options.signInUrl ? new URL(this.#options.signInUrl, window.location.origin).pathname : defaultPagePath;
332
+ } catch {
333
+ signInPagePath = defaultPagePath;
334
+ }
335
+ let signUpPagePath;
336
+ try {
337
+ signUpPagePath = this.#options.signUpUrl ? new URL(this.#options.signUpUrl, window.location.origin).pathname : key === "signUpUrl" ? defaultPagePath : "/sign-in";
338
+ } catch {
339
+ signUpPagePath = key === "signUpUrl" ? defaultPagePath : "/sign-in";
340
+ }
341
+ const redirectTargetObj = new URL(effectiveRedirectUrl, window.location.origin);
342
+ if (redirectTargetObj.pathname === signInPagePath || redirectTargetObj.pathname === signUpPagePath) {
343
+ effectiveRedirectUrl = "/";
344
+ }
345
+ }
346
+ const paramsForBuildUrl = {
347
+ base,
348
+ searchParams: new URLSearchParams()
349
+ };
350
+ if (effectiveRedirectUrl) {
351
+ if (inBrowser()) {
352
+ const absoluteRedirectUrl = new URL(effectiveRedirectUrl, window.location.origin).href;
353
+ (_a = paramsForBuildUrl.searchParams) == null ? void 0 : _a.set("redirect", absoluteRedirectUrl);
354
+ } else {
355
+ (_b = paramsForBuildUrl.searchParams) == null ? void 0 : _b.set("redirect", effectiveRedirectUrl);
356
+ }
357
+ }
358
+ const constructedUrl = buildURL(paramsForBuildUrl, {
359
+ stringify: true,
360
+ skipOrigin: false
361
+ });
362
+ if (typeof constructedUrl !== "string") {
363
+ console.error(
364
+ "[TernSecure] Error: buildURL did not return a string as expected. Falling back to base URL."
365
+ );
366
+ if (inBrowser()) {
367
+ try {
368
+ return new URL(base, window.location.origin).href;
369
+ } catch {
370
+ return base;
371
+ }
372
+ }
373
+ return base;
374
+ }
375
+ return this.constructUrlWithAuthRedirect(constructedUrl);
376
+ };
377
+ #constructAfterSignOutUrl = () => {
378
+ if (!this.#options.afterSignOutUrl) {
379
+ return "/";
380
+ }
381
+ return this.constructUrlWithAuthRedirect(this.#options.afterSignOutUrl);
382
+ };
383
+ constructSignInUrl = (options) => {
384
+ return this.#buildUrl("signInUrl", { ...options });
385
+ };
386
+ constructSignUpUrl = (options) => {
387
+ return this.#buildUrl("signUpUrl", { ...options });
388
+ };
389
+ __internal_setCountry = (country) => {
390
+ if (!this.__internal_country) {
391
+ this.__internal_country = country;
392
+ }
393
+ };
394
+ #initOptions = (options) => {
395
+ return {
396
+ ...options
397
+ };
398
+ };
399
+ #emit = () => {
400
+ if (this._currentUser) {
401
+ for (const listener of this.#listeners) {
402
+ listener({
403
+ user: this._currentUser
404
+ });
405
+ }
406
+ }
407
+ };
408
+ #setStatus(newStatus) {
409
+ if (this.#status !== newStatus) {
410
+ this.#status = newStatus;
411
+ this.#publicEventBus.emit(ternEvents.Status, this.#status);
412
+ if (newStatus === "ready") {
413
+ this.#publicEventBus.emit(ternEvents.Status, "ready");
414
+ }
415
+ }
416
+ }
417
+ #setPersistence = () => {
418
+ const persistenceType = this.#options.persistence || "none";
419
+ switch (persistenceType) {
420
+ case "browserCookie":
421
+ return browserCookiePersistence;
422
+ case "session":
423
+ return browserSessionPersistence;
424
+ case "local":
425
+ return browserLocalPersistence;
426
+ case "none":
427
+ default:
428
+ return inMemoryPersistence;
429
+ }
430
+ };
431
+ #emulatorHost = () => {
432
+ if (typeof process === "undefined") return void 0;
433
+ return process.env.FIREBASE_AUTH_EMULATOR_HOST;
434
+ };
435
+ #configureEmulator = () => {
436
+ const host = this.#emulatorHost();
437
+ const isDev = this.#instanceType === "development";
438
+ const shouldUseEmulator = isDev && !!host;
439
+ if (!shouldUseEmulator || !host) {
440
+ return;
441
+ }
442
+ const emulatorUrl = host.startsWith("http") ? host : `http://${host}`;
443
+ try {
444
+ connectAuthEmulator(this.auth, emulatorUrl, { disableWarnings: true });
445
+ console.warn(`[TernSecure] Firebase Auth Emulator connected at ${emulatorUrl}`);
446
+ } catch (error) {
447
+ console.error("[TernSecure] Error connecting to Firebase Auth Emulator:", error);
448
+ }
449
+ };
450
+ }
451
+ export {
452
+ TernSecureAuth,
453
+ inBrowser
454
+ };
455
+ //# sourceMappingURL=TernAuth.js.map
@@ -0,0 +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":[]}