edmaxlabs-core 2.4.9 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -129,116 +129,91 @@ var HttpsRequest = class {
129
129
 
130
130
  // src/authentication/Authentication.ts
131
131
  var _Authentication = class _Authentication {
132
+ // Re-entrancy guard
132
133
  constructor() {
134
+ this.eUser = null;
135
+ this.client = null;
136
+ this.app = null;
137
+ // Dedicated lightweight instance for auth
133
138
  this.eventListeners = /* @__PURE__ */ new Map();
134
- this.eventWaiters = /* @__PURE__ */ new Map();
135
- this.unsubscribers = /* @__PURE__ */ new Set();
136
- this.isSameCredentials = (a, b) => {
137
- if (!a && !b)
138
- return true;
139
- if (!a || !b)
140
- return false;
141
- return JSON.stringify(a.toMap()) === JSON.stringify(b.toMap());
142
- };
139
+ this.isHandlingChange = false;
140
+ // ====================== AUTH METHODS ======================
143
141
  this.createUserWithEmailAndPassword = async ({
144
142
  email,
145
143
  password
146
144
  }) => {
147
- this.eUser = void 0;
148
145
  this.saveCredentials(null);
149
- const app = this.app?.getDatabase;
150
- const data = await app?.collection("users").query.where({
151
- key: "email",
152
- op: "===",
153
- value: email
154
- }).get();
155
- if (data.length > 0) {
146
+ const app = this.app.getDatabase;
147
+ const existing = await app.collection("users").query.where({ key: "email", op: "===", value: email }).get();
148
+ if (existing.length > 0) {
156
149
  throw new Error("Email Already In Use.");
157
150
  }
158
- const userRef = await app?.collection("users").add({
151
+ const userRef = await app.collection("users").add({
159
152
  email,
160
153
  password,
161
- token: this.client?.getConfig().token,
154
+ token: this.client.getConfig().token,
162
155
  logged: true,
163
156
  lastLogged: Date.now()
164
157
  });
165
- if (!userRef?.id || userRef?.id === "") {
166
- throw new Error("Something went wrong try Again.");
158
+ if (!userRef?.id) {
159
+ throw new Error("Something went wrong. Please try again.");
167
160
  }
168
- this.eUser = Credentials.fromMap(userRef);
169
- this.saveCredentials(this.eUser);
170
- return Credentials.fromMap(userRef.toMap());
161
+ const newCreds = Credentials.fromMap(userRef.toMap());
162
+ this.saveCredentials(newCreds);
163
+ return newCreds;
171
164
  };
172
165
  this.signInWithEmailAndPassword = async ({
173
166
  email,
174
167
  password
175
168
  }) => {
176
- const app = this.app?.getDatabase;
177
- const data = await app?.collection("users").query.where({
178
- key: "email",
179
- op: "===",
180
- value: email
181
- }).where({
182
- key: "password",
183
- op: "===",
184
- value: password
185
- }).get();
186
- if (data === void 0) {
187
- throw new Error("Auth Failed.");
188
- }
189
- if (data?.length === 0) {
169
+ const app = this.app.getDatabase;
170
+ const data = await app.collection("users").query.where({ key: "email", op: "===", value: email }).where({ key: "password", op: "===", value: password }).get();
171
+ if (!data || data.length === 0) {
190
172
  throw new Error("User Not Found.");
191
173
  }
192
- const _data = data[0];
193
- await app?.collection("users").doc(data[0].id).update({
174
+ const userDoc = data[0];
175
+ await app.collection("users").doc(userDoc.id).update({
194
176
  logged: true,
195
177
  lastLogged: Date.now()
196
178
  });
197
- this.eUser = Credentials.fromMap(_data);
198
- this.saveCredentials(this.eUser);
199
- return Credentials.fromMap(data[0].toMap());
179
+ const signedInUser = Credentials.fromMap(userDoc.toMap());
180
+ this.saveCredentials(signedInUser);
181
+ return signedInUser;
200
182
  };
201
- this.deleteUser = async () => {
202
- if (!this.eUser) {
203
- throw new Error("No User Signed in");
204
- }
205
- const app = this.app?.getDatabase;
206
- const userRef = await app?.collection("users").doc(this.eUser.uid).delete();
207
- if (userRef) {
208
- throw new Error("Something went wrong try Again.");
209
- }
210
- this.eUser = void 0;
183
+ this.signOut = async () => {
184
+ const current = this.currentUser();
185
+ if (!current)
186
+ return;
187
+ const app = this.app.getDatabase;
188
+ await app.collection("users").doc(current.uid).update({
189
+ logged: false,
190
+ lastLogged: Date.now()
191
+ });
211
192
  this.saveCredentials(null);
212
193
  };
213
- this.signOut = async () => {
214
- const app = this.app?.getDatabase;
215
- const luid = this.currentUser();
216
- this.eUser = void 0;
194
+ this.deleteUser = async () => {
195
+ if (!this.eUser)
196
+ throw new Error("No User Signed in");
197
+ const app = this.app.getDatabase;
198
+ await app.collection("users").doc(this.eUser.uid).delete();
217
199
  this.saveCredentials(null);
218
- if (luid)
219
- await app?.collection("users").doc(luid?.uid).update({
220
- logged: false,
221
- lastLogged: Date.now()
222
- });
223
- return;
224
200
  };
201
+ // Optional: Rules verification
225
202
  this.rules = async (path, context) => {
226
203
  const res = await new HttpsRequest({
227
204
  method: "POST" /* POST */,
228
- endpoint: this.client.getBaseUrl() + "/auth/rules/verify",
205
+ endpoint: `${this.client.getBaseUrl()}/auth/rules/verify`,
229
206
  headers: {
230
207
  authorization: this.client.getConfig().token,
231
208
  project: this.client.getConfig().project
232
209
  },
233
- body: {
234
- path,
235
- context
236
- }
210
+ body: { path, context }
237
211
  }).sendRequest();
238
212
  return res;
239
213
  };
240
- if (_Authentication.instance)
214
+ if (_Authentication.instance) {
241
215
  return _Authentication.instance;
216
+ }
242
217
  this.client = EdmaxLabs.instance;
243
218
  this.app = new EdmaxLabs({
244
219
  token: "auth",
@@ -247,26 +222,16 @@ var _Authentication = class _Authentication {
247
222
  _Authentication.instance = this;
248
223
  this.restoreSession();
249
224
  }
250
- restoreSession() {
251
- const saved = this.currentUser();
252
- if (saved) {
253
- this.eUser = saved;
254
- this.emitValue("creds", saved);
255
- }
256
- }
257
- // Better singleton
258
225
  static getInstance() {
259
226
  if (!_Authentication.instance) {
260
227
  _Authentication.instance = new _Authentication();
261
228
  }
262
229
  return _Authentication.instance;
263
230
  }
231
+ // ====================== EVENT SYSTEM ======================
264
232
  emitValue(key, value) {
265
233
  const listeners = this.eventListeners.get(key) || [];
266
- listeners.forEach((l) => l(value));
267
- const waiters = this.eventWaiters.get(key) || [];
268
- waiters.forEach((resolve) => resolve(value));
269
- this.eventWaiters.delete(key);
234
+ [...listeners].forEach((listener) => listener(value));
270
235
  }
271
236
  onValue(key, callback) {
272
237
  const listeners = this.eventListeners.get(key) || [];
@@ -277,6 +242,7 @@ var _Authentication = class _Authentication {
277
242
  this.eventListeners.set(key, filtered);
278
243
  };
279
244
  }
245
+ // ====================== CREDENTIALS ======================
280
246
  currentUser() {
281
247
  const data = localStorage.getItem("eauth");
282
248
  if (!data)
@@ -299,49 +265,71 @@ var _Authentication = class _Authentication {
299
265
  this.eUser = credentials;
300
266
  this.emitValue("creds", credentials);
301
267
  }
302
- // Main auth state listener - should be called ONCE at app root
268
+ isSameCredentials(a, b) {
269
+ if (!a && !b)
270
+ return true;
271
+ if (!a || !b)
272
+ return false;
273
+ return a.uid === b.uid && a.displayInfo.email === b.displayInfo.email && a.lastLogged === b.lastLogged;
274
+ }
275
+ restoreSession() {
276
+ const saved = this.currentUser();
277
+ if (saved) {
278
+ this.eUser = saved;
279
+ }
280
+ }
281
+ // ====================== MAIN AUTH STATE LISTENER ======================
282
+ /**
283
+ * Main method to listen to authentication state changes.
284
+ * This listener stays alive for the entire app lifetime.
285
+ */
303
286
  authState({
304
287
  onChange,
305
288
  onSignOut,
306
289
  onDeleted
307
290
  }) {
308
291
  let userDocUnsubscribe;
292
+ let credsUnsub;
309
293
  const handleCredsChange = (creds) => {
310
- if (userDocUnsubscribe) {
311
- userDocUnsubscribe();
312
- userDocUnsubscribe = void 0;
313
- }
294
+ if (this.isHandlingChange)
295
+ return;
296
+ this.isHandlingChange = true;
297
+ userDocUnsubscribe?.();
298
+ userDocUnsubscribe = void 0;
314
299
  if (!creds) {
315
300
  this.eUser = null;
316
301
  onSignOut?.();
302
+ this.isHandlingChange = false;
317
303
  return;
318
304
  }
319
- const userRef = this.app?.getDatabase.collection("users").doc(creds.uid);
320
- if (!userRef)
321
- return;
305
+ const userRef = this.app.getDatabase.collection("users").doc(creds.uid);
322
306
  userDocUnsubscribe = userRef.onSnapshot(
323
307
  (snapshot, change) => {
324
308
  if (change === "delete") {
325
309
  this.saveCredentials(null);
326
310
  onSignOut?.();
327
311
  onDeleted?.();
312
+ this.isHandlingChange = false;
328
313
  return;
329
314
  }
330
315
  if (change === "insert" || change === "update") {
331
- if (!snapshot)
316
+ if (!snapshot?.data) {
317
+ this.isHandlingChange = false;
332
318
  return;
319
+ }
333
320
  if (snapshot.data.logged === false || snapshot.data.logged === "false") {
334
321
  this.saveCredentials(null);
335
322
  onSignOut?.();
323
+ this.isHandlingChange = false;
336
324
  return;
337
325
  }
338
326
  const newCreds = Credentials.fromMap(snapshot.toMap());
339
327
  if (!this.isSameCredentials(this.eUser, newCreds)) {
340
- this.eUser = newCreds;
341
328
  this.saveCredentials(newCreds);
342
329
  onChange(newCreds);
343
330
  }
344
331
  }
332
+ this.isHandlingChange = false;
345
333
  }
346
334
  );
347
335
  };
@@ -350,10 +338,10 @@ var _Authentication = class _Authentication {
350
338
  this.eUser = initialUser;
351
339
  onChange(initialUser);
352
340
  }
341
+ credsUnsub = this.onValue("creds", handleCredsChange);
353
342
  handleCredsChange(initialUser);
354
- const credsUnsub = this.onValue("creds", handleCredsChange);
355
343
  return () => {
356
- credsUnsub();
344
+ credsUnsub?.();
357
345
  userDocUnsubscribe?.();
358
346
  };
359
347
  }