@ttt-productions/auth-core 0.2.6 → 0.3.2

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/env.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ export type AppEnvironment = "development" | "production";
2
+ export declare function getAppEnvironment(): AppEnvironment;
3
+ export declare function isDevelopment(): boolean;
4
+ export declare function isProduction(): boolean;
5
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG,YAAY,CAAC;AAE1D,wBAAgB,iBAAiB,IAAI,cAAc,CAKlD;AAED,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED,wBAAgB,YAAY,IAAI,OAAO,CAEtC"}
package/dist/env.js ADDED
@@ -0,0 +1,13 @@
1
+ export function getAppEnvironment() {
2
+ if (typeof process !== "undefined" && process.env?.NEXT_PUBLIC_APP_ENV === "production") {
3
+ return "production";
4
+ }
5
+ return "development";
6
+ }
7
+ export function isDevelopment() {
8
+ return getAppEnvironment() === "development";
9
+ }
10
+ export function isProduction() {
11
+ return getAppEnvironment() === "production";
12
+ }
13
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,iBAAiB;IAC/B,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,GAAG,EAAE,mBAAmB,KAAK,YAAY,EAAE,CAAC;QACxF,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,iBAAiB,EAAE,KAAK,aAAa,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,iBAAiB,EAAE,KAAK,YAAY,CAAC;AAC9C,CAAC"}
package/dist/errors.d.ts CHANGED
@@ -6,4 +6,6 @@ export type NormalizedAuthError = {
6
6
  details?: Record<string, unknown>;
7
7
  };
8
8
  export declare function normalizeAuthError(err: unknown, details?: Record<string, unknown>): NormalizedAuthError;
9
+ /** Convenience: returns just the user-facing message string */
10
+ export declare function getErrorMessage(error: unknown): string;
9
11
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GACrB,cAAc,GACd,oBAAoB,GACpB,wBAAwB,GACxB,mBAAmB,GACnB,oBAAoB,GACpB,gBAAgB,GAChB,oBAAoB,GACpB,qBAAqB,GACrB,qBAAqB,GACrB,oBAAoB,GACpB,2BAA2B,GAC3B,oBAAoB,GACpB,4BAA4B,GAC5B,yBAAyB,GACzB,+CAA+C,GAC/C,8BAA8B,GAC9B,gCAAgC,CAAC;AAErC,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC,CAAC;AA4EF,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,mBAAmB,CAyBvG"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GACrB,cAAc,GACd,oBAAoB,GACpB,wBAAwB,GACxB,mBAAmB,GACnB,oBAAoB,GACpB,gBAAgB,GAChB,oBAAoB,GACpB,qBAAqB,GACrB,qBAAqB,GACrB,oBAAoB,GACpB,2BAA2B,GAC3B,oBAAoB,GACpB,4BAA4B,GAC5B,yBAAyB,GACzB,+CAA+C,GAC/C,8BAA8B,GAC9B,gCAAgC,CAAC;AAErC,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC,CAAC;AA4EF,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,mBAAmB,CAyBvG;AAED,+DAA+D;AAC/D,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEtD"}
package/dist/errors.js CHANGED
@@ -93,4 +93,8 @@ export function normalizeAuthError(err, details) {
93
93
  details
94
94
  };
95
95
  }
96
+ /** Convenience: returns just the user-facing message string */
97
+ export function getErrorMessage(error) {
98
+ return normalizeAuthError(error).message;
99
+ }
96
100
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AA0BA,SAAS,gBAAgB,CAAC,GAAY;IACpC,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IACtD,MAAM,MAAM,GAAG,GAAU,CAAC;IAC1B,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC;IACtB,OAAO,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/C,CAAC;AAED,MAAM,GAAG,GAA6D;IACpE,6BAA6B,EAAE;QAC7B,IAAI,EAAE,oBAAoB;QAC1B,OAAO,EAAE,4DAA4D;KACtE;IACD,wBAAwB,EAAE;QACxB,IAAI,EAAE,wBAAwB;QAC9B,OAAO,EAAE,wDAAwD;KAClE;IACD,2BAA2B,EAAE;QAC3B,IAAI,EAAE,mBAAmB;QACzB,OAAO,EAAE,2BAA2B;KACrC;IACD,oBAAoB,EAAE;QACpB,IAAI,EAAE,oBAAoB;QAC1B,OAAO,EAAE,2CAA2C;KACrD;IACD,8BAA8B,EAAE;QAC9B,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,wBAAwB;KAClC;IACD,oBAAoB,EAAE;QACpB,IAAI,EAAE,oBAAoB;QAC1B,OAAO,EAAE,iCAAiC;KAC3C;IACD,qBAAqB,EAAE;QACrB,IAAI,EAAE,qBAAqB;QAC3B,OAAO,EAAE,mCAAmC;KAC7C;IACD,qBAAqB,EAAE;QACrB,IAAI,EAAE,qBAAqB;QAC3B,OAAO,EAAE,qBAAqB;KAC/B;IACD,oBAAoB,EAAE;QACpB,IAAI,EAAE,oBAAoB;QAC1B,OAAO,EAAE,wBAAwB;KAClC;IACD,2BAA2B,EAAE;QAC3B,IAAI,EAAE,2BAA2B;QACjC,OAAO,EAAE,+BAA+B;KACzC;IACD,oBAAoB,EAAE;QACpB,IAAI,EAAE,oBAAoB;QAC1B,OAAO,EAAE,uBAAuB;KACjC;IACD,4BAA4B,EAAE;QAC5B,IAAI,EAAE,4BAA4B;QAClC,OAAO,EAAE,uCAAuC;KACjD;IACD,yBAAyB,EAAE;QACzB,IAAI,EAAE,yBAAyB;QAC/B,OAAO,EAAE,wCAAwC;KAClD;IACD,+CAA+C,EAAE;QAC/C,IAAI,EAAE,+CAA+C;QACrD,OAAO,EAAE,4DAA4D;KACtE;IACD,8BAA8B,EAAE;QAC9B,IAAI,EAAE,8BAA8B;QACpC,OAAO,EAAE,kDAAkD;KAC5D;IACD,gCAAgC,EAAE;QAChC,IAAI,EAAE,gCAAgC;QACtC,OAAO,EAAE,gEAAgE;KAC1E;CACF,CAAC;AAEF,MAAM,UAAU,kBAAkB,CAAC,GAAY,EAAE,OAAiC;IAChF,MAAM,YAAY,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAE3C,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5D,IAAI,MAAM,EAAE,CAAC;QACX,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,YAAY;YACZ,OAAO;SACR,CAAC;IACJ,CAAC;IAED,iDAAiD;IACjD,MAAM,GAAG,GACP,OAAQ,GAAW,EAAE,OAAO,KAAK,QAAQ;QACvC,CAAC,CAAE,GAAW,CAAC,OAAO;QACtB,CAAC,CAAC,yCAAyC,CAAC;IAEhD,OAAO;QACL,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE,GAAG;QACZ,YAAY;QACZ,OAAO;KACR,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- export * from "./auth";
2
- export * from "./claims";
3
- export * from "./errors";
1
+ export * from "./auth.js";
2
+ export * from "./claims.js";
3
+ export * from "./errors.js";
4
+ export * from "./env.js";
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
- export * from "./auth";
2
- export * from "./claims";
3
- export * from "./errors";
1
+ export * from "./auth.js";
2
+ export * from "./claims.js";
3
+ export * from "./errors.js";
4
+ export * from "./env.js";
4
5
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { type ReactNode } from "react";
2
+ import type { AuthProviderConfig, AuthContextValue, BaseProfile } from "./types.js";
3
+ export declare const AuthContext: import("react").Context<AuthContextValue<any, any> | null>;
4
+ interface AuthProviderProps<TProfile extends BaseProfile, TClaims> {
5
+ config: AuthProviderConfig<TProfile, TClaims>;
6
+ children: ReactNode;
7
+ }
8
+ export declare function AuthProvider<TProfile extends BaseProfile = BaseProfile, TClaims = Record<string, unknown>>({ config, children }: AuthProviderProps<TProfile, TClaims>): import("react/jsx-runtime").JSX.Element;
9
+ export {};
10
+ //# sourceMappingURL=AuthProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthProvider.d.ts","sourceRoot":"","sources":["../../src/react/AuthProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAIf,OAAO,KAAK,EACV,kBAAkB,EAClB,gBAAgB,EAChB,WAAW,EAEZ,MAAM,YAAY,CAAC;AAGpB,eAAO,MAAM,WAAW,4DAAyD,CAAC;AAElF,UAAU,iBAAiB,CACzB,QAAQ,SAAS,WAAW,EAC5B,OAAO;IAEP,MAAM,EAAE,kBAAkB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC9C,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,YAAY,CAC1B,QAAQ,SAAS,WAAW,GAAG,WAAW,EAC1C,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,iBAAiB,CAAC,QAAQ,EAAE,OAAO,CAAC,2CA8M3D"}
@@ -0,0 +1,186 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { createContext, useEffect, useRef, useState, useCallback, useMemo, } from "react";
4
+ import { doc, onSnapshot } from "firebase/firestore";
5
+ import { useAuthState } from "./useAuthState.js";
6
+ import { getIdTokenClaims } from "../claims.js";
7
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
+ export const AuthContext = createContext(null);
9
+ export function AuthProvider({ config, children }) {
10
+ const { user, loading: authLoading } = useAuthState(config.auth);
11
+ const [claims, setClaims] = useState(config.defaultClaims);
12
+ const [claimsLoading, setClaimsLoading] = useState(true);
13
+ const [userProfile, setUserProfile] = useState(null);
14
+ const [profileLoading, setProfileLoading] = useState(true);
15
+ const [profileError, setProfileError] = useState(null);
16
+ // Refs for cleanup
17
+ const profileUnsubRef = useRef(null);
18
+ const timeoutRef = useRef(null);
19
+ const prevUidRef = useRef(null);
20
+ // Stable config ref so effects don't re-fire on config object identity changes
21
+ const configRef = useRef(config);
22
+ configRef.current = config;
23
+ // --- Claims fetching ---
24
+ useEffect(() => {
25
+ if (authLoading)
26
+ return;
27
+ if (!user) {
28
+ setClaims(configRef.current.defaultClaims);
29
+ setClaimsLoading(false);
30
+ return;
31
+ }
32
+ let cancelled = false;
33
+ setClaimsLoading(true);
34
+ getIdTokenClaims(user)
35
+ .then((raw) => {
36
+ if (cancelled)
37
+ return;
38
+ setClaims(configRef.current.parseClaims((raw ?? {})));
39
+ })
40
+ .catch((err) => {
41
+ if (cancelled)
42
+ return;
43
+ configRef.current.onError?.(err, "getIdTokenClaims");
44
+ setClaims(configRef.current.defaultClaims);
45
+ })
46
+ .finally(() => {
47
+ if (!cancelled)
48
+ setClaimsLoading(false);
49
+ });
50
+ return () => { cancelled = true; };
51
+ }, [user, authLoading]);
52
+ // --- Profile listener ---
53
+ useEffect(() => {
54
+ if (authLoading)
55
+ return;
56
+ const uid = user?.uid ?? null;
57
+ const prevUid = prevUidRef.current;
58
+ prevUidRef.current = uid;
59
+ // Clean up previous listener + timeout if user changed
60
+ if (uid !== prevUid) {
61
+ if (profileUnsubRef.current) {
62
+ profileUnsubRef.current();
63
+ profileUnsubRef.current = null;
64
+ }
65
+ if (timeoutRef.current) {
66
+ clearTimeout(timeoutRef.current);
67
+ timeoutRef.current = null;
68
+ }
69
+ }
70
+ // User signed out
71
+ if (!uid) {
72
+ setUserProfile(null);
73
+ setProfileError(null);
74
+ setProfileLoading(false);
75
+ configRef.current.onAuthStateChange?.(null);
76
+ configRef.current.onProfileChange?.(null, null);
77
+ return;
78
+ }
79
+ // User signed in (or changed)
80
+ setProfileLoading(true);
81
+ setProfileError(null);
82
+ configRef.current.onAuthStateChange?.(user);
83
+ const timeout = (configRef.current.profileTimeout ?? 15) * 1000;
84
+ const [colPath, docId] = configRef.current.profilePath(uid);
85
+ const docRef = doc(configRef.current.db, colPath, docId);
86
+ // Start timeout timer
87
+ timeoutRef.current = setTimeout(() => {
88
+ // Only fire if we're still waiting (profileLoading is still true)
89
+ setProfileError({
90
+ code: "PROFILE_TIMEOUT",
91
+ message: `Profile document not found after ${configRef.current.profileTimeout ?? 15}s.`,
92
+ uid,
93
+ });
94
+ setProfileLoading(false);
95
+ }, timeout);
96
+ const unsub = onSnapshot(docRef, (snap) => {
97
+ // Clear timeout on any successful snapshot
98
+ if (timeoutRef.current) {
99
+ clearTimeout(timeoutRef.current);
100
+ timeoutRef.current = null;
101
+ }
102
+ if (snap.exists()) {
103
+ const data = snap.data();
104
+ const parsed = configRef.current.parseProfile
105
+ ? configRef.current.parseProfile(data, uid)
106
+ : { uid, ...data };
107
+ setUserProfile(parsed);
108
+ setProfileError(null);
109
+ setProfileLoading(false);
110
+ configRef.current.onProfileChange?.(parsed, user);
111
+ }
112
+ else {
113
+ // Doc doesn't exist yet — restart timeout if not already timed out
114
+ if (!timeoutRef.current) {
115
+ timeoutRef.current = setTimeout(() => {
116
+ setProfileError({
117
+ code: "PROFILE_NOT_FOUND",
118
+ message: "Profile document does not exist.",
119
+ uid,
120
+ });
121
+ setProfileLoading(false);
122
+ }, timeout);
123
+ }
124
+ }
125
+ }, (err) => {
126
+ if (timeoutRef.current) {
127
+ clearTimeout(timeoutRef.current);
128
+ timeoutRef.current = null;
129
+ }
130
+ configRef.current.onError?.(err, "profile onSnapshot");
131
+ setProfileError({
132
+ code: "PROFILE_LISTENER_ERROR",
133
+ message: err instanceof Error ? err.message : "Profile listener failed.",
134
+ uid,
135
+ });
136
+ setProfileLoading(false);
137
+ });
138
+ profileUnsubRef.current = unsub;
139
+ return () => {
140
+ unsub();
141
+ profileUnsubRef.current = null;
142
+ if (timeoutRef.current) {
143
+ clearTimeout(timeoutRef.current);
144
+ timeoutRef.current = null;
145
+ }
146
+ };
147
+ }, [user, authLoading]);
148
+ // --- refreshClaims ---
149
+ const refreshClaims = useCallback(async () => {
150
+ if (!user)
151
+ return;
152
+ try {
153
+ const result = await user.getIdTokenResult(true);
154
+ setClaims(configRef.current.parseClaims((result.claims ?? {})));
155
+ }
156
+ catch (err) {
157
+ configRef.current.onError?.(err, "refreshClaims");
158
+ }
159
+ }, [user]);
160
+ // --- Context value ---
161
+ const loading = authLoading || claimsLoading || profileLoading;
162
+ const value = useMemo(() => ({
163
+ user,
164
+ userProfile,
165
+ claims,
166
+ loading,
167
+ authLoading,
168
+ claimsLoading,
169
+ profileLoading,
170
+ profileError,
171
+ isAuthenticated: !!user,
172
+ refreshClaims,
173
+ }), [
174
+ user,
175
+ userProfile,
176
+ claims,
177
+ loading,
178
+ authLoading,
179
+ claimsLoading,
180
+ profileLoading,
181
+ profileError,
182
+ refreshClaims,
183
+ ]);
184
+ return (_jsx(AuthContext.Provider, { value: value, children: children }));
185
+ }
186
+ //# sourceMappingURL=AuthProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthProvider.js","sourceRoot":"","sources":["../../src/react/AuthProvider.tsx"],"names":[],"mappings":"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"}
@@ -1,2 +1,8 @@
1
- export * from "./useAuthState";
1
+ export * from "./useAuthState.js";
2
+ export * from "./types.js";
3
+ export { AuthProvider } from "./AuthProvider.js";
4
+ export { AuthContext } from "./AuthProvider.js";
5
+ export { useAuth } from "./useAuth.js";
6
+ export { useAuthGuard } from "./useAuthGuard.js";
7
+ export type { AuthGuardConfig } from "./useAuthGuard.js";
2
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
@@ -1,2 +1,7 @@
1
- export * from "./useAuthState";
1
+ export * from "./useAuthState.js";
2
+ export * from "./types.js";
3
+ export { AuthProvider } from "./AuthProvider.js";
4
+ export { AuthContext } from "./AuthProvider.js";
5
+ export { useAuth } from "./useAuth.js";
6
+ export { useAuthGuard } from "./useAuthGuard.js";
2
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,62 @@
1
+ import type { Auth, User } from "firebase/auth";
2
+ import type { Firestore } from "firebase/firestore";
3
+ /**
4
+ * Base profile contract. Apps extend with their own fields.
5
+ * auth-core uses these for monitoring integration and generic display.
6
+ */
7
+ export interface BaseProfile {
8
+ uid: string;
9
+ displayName: string;
10
+ photoURL?: string | null;
11
+ status?: string;
12
+ }
13
+ export interface AuthProviderConfig<TProfile extends BaseProfile = BaseProfile, TClaims = Record<string, unknown>> {
14
+ auth: Auth;
15
+ db: Firestore;
16
+ /** Firestore path segments for profile doc: (uid) => ['users', uid] */
17
+ profilePath: (uid: string) => [string, string];
18
+ /** Transform raw Firestore data into app profile type */
19
+ parseProfile?: (data: Record<string, unknown>, uid: string) => TProfile;
20
+ /** Transform raw ID token claims into app claims shape */
21
+ parseClaims: (raw: Record<string, unknown>) => TClaims;
22
+ /** Default claims when no user or claims unavailable */
23
+ defaultClaims: TClaims;
24
+ /** Called on Firebase auth state change (for monitoring, analytics) */
25
+ onAuthStateChange?: (user: User | null) => void;
26
+ /** Called when profile snapshot updates (for monitoring, RQ cache bridge) */
27
+ onProfileChange?: (profile: TProfile | null, user: User | null) => void;
28
+ /** Called on errors (for Sentry) */
29
+ onError?: (error: unknown, context: string) => void;
30
+ /**
31
+ * Max seconds to wait for profile doc after auth.
32
+ * If exceeded, profileError is set and loading becomes false.
33
+ * Default: 15
34
+ */
35
+ profileTimeout?: number;
36
+ }
37
+ export interface AuthContextValue<TProfile extends BaseProfile = BaseProfile, TClaims = Record<string, unknown>> {
38
+ /** Firebase User */
39
+ user: User | null;
40
+ /** Firestore profile doc, parsed */
41
+ userProfile: TProfile | null;
42
+ /** Parsed custom claims */
43
+ claims: TClaims;
44
+ /** True until auth + claims + profile all resolved */
45
+ loading: boolean;
46
+ /** Individual loading states */
47
+ authLoading: boolean;
48
+ claimsLoading: boolean;
49
+ profileLoading: boolean;
50
+ /** Set when user is authenticated but profile doc not found within timeout */
51
+ profileError: ProfileError | null;
52
+ /** Convenience: !!user */
53
+ isAuthenticated: boolean;
54
+ /** Force refresh claims from Firebase */
55
+ refreshClaims: () => Promise<void>;
56
+ }
57
+ export type ProfileError = {
58
+ code: "PROFILE_NOT_FOUND" | "PROFILE_TIMEOUT" | "PROFILE_LISTENER_ERROR";
59
+ message: string;
60
+ uid: string;
61
+ };
62
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/react/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEpD;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB,CACjC,QAAQ,SAAS,WAAW,GAAG,WAAW,EAC1C,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAEjC,IAAI,EAAE,IAAI,CAAC;IACX,EAAE,EAAE,SAAS,CAAC;IAEd,uEAAuE;IACvE,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE/C,yDAAyD;IACzD,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,KAAK,QAAQ,CAAC;IAExE,0DAA0D;IAC1D,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC;IAEvD,wDAAwD;IACxD,aAAa,EAAE,OAAO,CAAC;IAEvB,uEAAuE;IACvE,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,KAAK,IAAI,CAAC;IAEhD,6EAA6E;IAC7E,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,GAAG,IAAI,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI,KAAK,IAAI,CAAC;IAExE,oCAAoC;IACpC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAEpD;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB,CAC/B,QAAQ,SAAS,WAAW,GAAG,WAAW,EAC1C,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAEjC,oBAAoB;IACpB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAElB,oCAAoC;IACpC,WAAW,EAAE,QAAQ,GAAG,IAAI,CAAC;IAE7B,2BAA2B;IAC3B,MAAM,EAAE,OAAO,CAAC;IAEhB,sDAAsD;IACtD,OAAO,EAAE,OAAO,CAAC;IAEjB,gCAAgC;IAChC,WAAW,EAAE,OAAO,CAAC;IACrB,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;IAExB,8EAA8E;IAC9E,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;IAElC,0BAA0B;IAC1B,eAAe,EAAE,OAAO,CAAC;IAEzB,yCAAyC;IACzC,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACpC;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,mBAAmB,GAAG,iBAAiB,GAAG,wBAAwB,CAAC;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/react/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ import type { BaseProfile, AuthContextValue } from "./types.js";
2
+ /**
3
+ * Access the auth context. Must be used within an AuthProvider.
4
+ * Generic params let each app specify its own profile + claims types.
5
+ */
6
+ export declare function useAuth<TProfile extends BaseProfile = BaseProfile, TClaims = Record<string, unknown>>(): AuthContextValue<TProfile, TClaims>;
7
+ //# sourceMappingURL=useAuth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAuth.d.ts","sourceRoot":"","sources":["../../src/react/useAuth.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEhE;;;GAGG;AACH,wBAAgB,OAAO,CACrB,QAAQ,SAAS,WAAW,GAAG,WAAW,EAC1C,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC9B,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAMvC"}
@@ -0,0 +1,15 @@
1
+ "use client";
2
+ import { useContext } from "react";
3
+ import { AuthContext } from "./AuthProvider.js";
4
+ /**
5
+ * Access the auth context. Must be used within an AuthProvider.
6
+ * Generic params let each app specify its own profile + claims types.
7
+ */
8
+ export function useAuth() {
9
+ const ctx = useContext(AuthContext);
10
+ if (!ctx) {
11
+ throw new Error("useAuth must be used within an AuthProvider");
12
+ }
13
+ return ctx;
14
+ }
15
+ //# sourceMappingURL=useAuth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAuth.js","sourceRoot":"","sources":["../../src/react/useAuth.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD;;;GAGG;AACH,MAAM,UAAU,OAAO;IAIrB,MAAM,GAAG,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IACpC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,GAA0C,CAAC;AACpD,CAAC"}
@@ -0,0 +1,37 @@
1
+ export interface AuthGuardConfig {
2
+ /** Routes accessible without authentication */
3
+ publicRoutes: string[];
4
+ /** Routes that redirect authenticated users away (login, register) */
5
+ authRedirectRoutes: string[];
6
+ /** Where unauthenticated users go */
7
+ loginRoute: string;
8
+ /** Where authenticated users go from authRedirectRoutes */
9
+ defaultRoute: string;
10
+ /** Special root path handling */
11
+ rootRedirect?: {
12
+ authenticated: string;
13
+ unauthenticated: string;
14
+ };
15
+ /** localStorage key for post-login redirect */
16
+ redirectKey?: string;
17
+ /** Navigation function (e.g. router.replace) */
18
+ replace: (path: string) => void;
19
+ /** Current path */
20
+ pathname: string;
21
+ /** From useAuth() */
22
+ loading: boolean;
23
+ /** From useAuth() */
24
+ isAuthenticated: boolean;
25
+ /** From useAuth() — user has a profile doc */
26
+ hasProfile: boolean;
27
+ }
28
+ /**
29
+ * Handles route protection. Call in app shell component.
30
+ *
31
+ * - Does nothing while loading.
32
+ * - Redirects unauthenticated users from protected routes to loginRoute.
33
+ * - Redirects authenticated users from authRedirectRoutes to defaultRoute.
34
+ * - Saves attempted path for post-login redirect.
35
+ */
36
+ export declare function useAuthGuard(config: AuthGuardConfig): void;
37
+ //# sourceMappingURL=useAuthGuard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAuthGuard.d.ts","sourceRoot":"","sources":["../../src/react/useAuthGuard.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,eAAe;IAC9B,+CAA+C;IAC/C,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,sEAAsE;IACtE,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,qCAAqC;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,YAAY,EAAE,MAAM,CAAC;IACrB,iCAAiC;IACjC,YAAY,CAAC,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,CAAC;IAClE,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gDAAgD;IAChD,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,mBAAmB;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,qBAAqB;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,qBAAqB;IACrB,eAAe,EAAE,OAAO,CAAC;IACzB,8CAA8C;IAC9C,UAAU,EAAE,OAAO,CAAC;CACrB;AAID;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAoE1D"}
@@ -0,0 +1,63 @@
1
+ "use client";
2
+ import { useEffect } from "react";
3
+ const DEFAULT_REDIRECT_KEY = "auth_redirect_path";
4
+ /**
5
+ * Handles route protection. Call in app shell component.
6
+ *
7
+ * - Does nothing while loading.
8
+ * - Redirects unauthenticated users from protected routes to loginRoute.
9
+ * - Redirects authenticated users from authRedirectRoutes to defaultRoute.
10
+ * - Saves attempted path for post-login redirect.
11
+ */
12
+ export function useAuthGuard(config) {
13
+ const { publicRoutes, authRedirectRoutes, loginRoute, defaultRoute, rootRedirect, redirectKey = DEFAULT_REDIRECT_KEY, replace, pathname, loading, isAuthenticated, hasProfile, } = config;
14
+ useEffect(() => {
15
+ if (loading)
16
+ return;
17
+ // Root path special handling
18
+ if (rootRedirect && pathname === "/") {
19
+ replace(isAuthenticated ? rootRedirect.authenticated : rootRedirect.unauthenticated);
20
+ return;
21
+ }
22
+ const isPublic = publicRoutes.some((r) => pathname.startsWith(r)) || pathname.startsWith("/v/");
23
+ const isAuthRedirect = authRedirectRoutes.includes(pathname);
24
+ // Unauthenticated on protected route -> save path, go to login
25
+ if (!isAuthenticated && !isPublic) {
26
+ if (typeof window !== "undefined") {
27
+ localStorage.setItem(redirectKey, pathname);
28
+ }
29
+ replace(loginRoute);
30
+ return;
31
+ }
32
+ // Authenticated user on auth-only route (login, register, etc.)
33
+ if (isAuthenticated && isAuthRedirect) {
34
+ // Still registering -- profile not created yet, stay on page
35
+ if (!hasProfile && typeof window !== "undefined" && localStorage.getItem("isRegistering") === "true") {
36
+ return;
37
+ }
38
+ // Redirect to saved path or default
39
+ let target = defaultRoute;
40
+ if (typeof window !== "undefined") {
41
+ const saved = localStorage.getItem(redirectKey);
42
+ if (saved && !authRedirectRoutes.includes(saved)) {
43
+ target = saved;
44
+ }
45
+ localStorage.removeItem(redirectKey);
46
+ }
47
+ replace(target);
48
+ }
49
+ }, [
50
+ loading,
51
+ isAuthenticated,
52
+ hasProfile,
53
+ pathname,
54
+ publicRoutes,
55
+ authRedirectRoutes,
56
+ loginRoute,
57
+ defaultRoute,
58
+ rootRedirect,
59
+ redirectKey,
60
+ replace,
61
+ ]);
62
+ }
63
+ //# sourceMappingURL=useAuthGuard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAuthGuard.js","sourceRoot":"","sources":["../../src/react/useAuthGuard.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AA2BlC,MAAM,oBAAoB,GAAG,oBAAoB,CAAC;AAElD;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,MAAuB;IAClD,MAAM,EACJ,YAAY,EACZ,kBAAkB,EAClB,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,WAAW,GAAG,oBAAoB,EAClC,OAAO,EACP,QAAQ,EACR,OAAO,EACP,eAAe,EACf,UAAU,GACX,GAAG,MAAM,CAAC;IAEX,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,OAAO;YAAE,OAAO;QAEpB,6BAA6B;QAC7B,IAAI,YAAY,IAAI,QAAQ,KAAK,GAAG,EAAE,CAAC;YACrC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC;YACrF,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GACZ,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QACjF,MAAM,cAAc,GAAG,kBAAkB,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAE7D,+DAA+D;QAC/D,IAAI,CAAC,eAAe,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClC,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;gBAClC,YAAY,CAAC,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;YAC9C,CAAC;YACD,OAAO,CAAC,UAAU,CAAC,CAAC;YACpB,OAAO;QACT,CAAC;QAED,gEAAgE;QAChE,IAAI,eAAe,IAAI,cAAc,EAAE,CAAC;YACtC,6DAA6D;YAC7D,IAAI,CAAC,UAAU,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,YAAY,CAAC,OAAO,CAAC,eAAe,CAAC,KAAK,MAAM,EAAE,CAAC;gBACrG,OAAO;YACT,CAAC;YAED,oCAAoC;YACpC,IAAI,MAAM,GAAG,YAAY,CAAC;YAC1B,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;gBAClC,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;gBAChD,IAAI,KAAK,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;oBACjD,MAAM,GAAG,KAAK,CAAC;gBACjB,CAAC;gBACD,YAAY,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;YACvC,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,EAAE;QACD,OAAO;QACP,eAAe;QACf,UAAU;QACV,QAAQ;QACR,YAAY;QACZ,kBAAkB;QAClB,UAAU;QACV,YAAY;QACZ,YAAY;QACZ,WAAW;QACX,OAAO;KACR,CAAC,CAAC;AACL,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { useEffect, useState } from "react";
2
- import { onAuthStateChanged } from "../auth";
2
+ import { onAuthStateChanged } from "../auth.js";
3
3
  export function useAuthState(auth) {
4
4
  // Initialize state based on current auth status to avoid initial flash
5
5
  const [user, setUser] = useState(() => auth.currentUser);
@@ -1 +1 @@
1
- {"version":3,"file":"useAuthState.js","sourceRoot":"","sources":["../../src/react/useAuthState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAQ7C,MAAM,UAAU,YAAY,CAAC,IAAU;IACrC,uEAAuE;IACvE,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAc,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACtE,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAU,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC;IACjF,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAiB,IAAI,CAAC,CAAC;IAEzD,SAAS,CAAC,GAAG,EAAE;QACb,kEAAkE;QAClE,8EAA8E;QAC9E,uCAAuC;QACvC,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI,EAAE,CAAC;YAC/C,UAAU,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;QAED,MAAM,KAAK,GAAG,kBAAkB,CAC9B,IAAI,EACJ,CAAC,CAAC,EAAE,EAAE;YACJ,OAAO,CAAC,CAAC,CAAC,CAAC;YACX,QAAQ,CAAC,IAAI,CAAC,CAAC;YACf,UAAU,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC,EACD,CAAC,CAAC,EAAE,EAAE;YACJ,QAAQ,CAAC,CAAC,CAAC,CAAC;YACZ,UAAU,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC,CACF,CAAC;QACF,OAAO,KAAK,CAAC;IACf,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAClC,CAAC"}
1
+ {"version":3,"file":"useAuthState.js","sourceRoot":"","sources":["../../src/react/useAuthState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAQhD,MAAM,UAAU,YAAY,CAAC,IAAU;IACrC,uEAAuE;IACvE,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAc,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACtE,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAU,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC;IACjF,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAiB,IAAI,CAAC,CAAC;IAEzD,SAAS,CAAC,GAAG,EAAE;QACb,kEAAkE;QAClE,8EAA8E;QAC9E,uCAAuC;QACvC,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI,EAAE,CAAC;YAC/C,UAAU,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;QAED,MAAM,KAAK,GAAG,kBAAkB,CAC9B,IAAI,EACJ,CAAC,CAAC,EAAE,EAAE;YACJ,OAAO,CAAC,CAAC,CAAC,CAAC;YACX,QAAQ,CAAC,IAAI,CAAC,CAAC;YACf,UAAU,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC,EACD,CAAC,CAAC,EAAE,EAAE;YACJ,QAAQ,CAAC,CAAC,CAAC,CAAC;YACZ,UAAU,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC,CACF,CAAC;QACF,OAAO,KAAK,CAAC;IACf,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAClC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttt-productions/auth-core",
3
- "version": "0.2.6",
3
+ "version": "0.3.2",
4
4
  "description": "Shared Firebase authentication utilities and React hooks for TTT Productions apps",
5
5
  "repository": {
6
6
  "type": "git",