@ciridae/auth 0.1.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/README.md +18 -0
- package/dist/CiridaeAuthProvider.d.ts +15 -0
- package/dist/CiridaeAuthProvider.js +65 -0
- package/dist/authServiceUrls.d.ts +11 -0
- package/dist/authServiceUrls.js +38 -0
- package/dist/authSession.d.ts +15 -0
- package/dist/authSession.js +1 -0
- package/dist/authenticatedUser.d.ts +17 -0
- package/dist/authenticatedUser.js +13 -0
- package/dist/createCiridaeAuth.d.ts +23 -0
- package/dist/createCiridaeAuth.js +109 -0
- package/dist/entries/client.d.ts +4 -0
- package/dist/entries/client.js +4 -0
- package/dist/entries/react.d.ts +2 -0
- package/dist/entries/react.js +2 -0
- package/dist/useCompleteCiridaeSignIn.d.ts +18 -0
- package/dist/useCompleteCiridaeSignIn.js +40 -0
- package/package.json +42 -0
package/README.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# @ciridae/auth
|
|
2
|
+
|
|
3
|
+
Shared browser authentication capabilities and React session lifecycle for Ciridae applications.
|
|
4
|
+
|
|
5
|
+
Install from npm:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @ciridae/auth
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Use the published package for new and updated consumers.
|
|
12
|
+
|
|
13
|
+
Create one auth facade and pass it to the optional React integration:
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { createCiridaeAuth } from "@ciridae/auth/client";
|
|
17
|
+
import { CiridaeAuthProvider } from "@ciridae/auth/react";
|
|
18
|
+
```
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { FirebaseUid } from "./authenticatedUser.js";
|
|
2
|
+
import type { AuthSession } from "./authSession.js";
|
|
3
|
+
import type { CiridaeAuth } from "./createCiridaeAuth.js";
|
|
4
|
+
type CiridaeAuthContextValue = {
|
|
5
|
+
auth: CiridaeAuth;
|
|
6
|
+
session: AuthSession;
|
|
7
|
+
signOut(): Promise<string | null>;
|
|
8
|
+
};
|
|
9
|
+
export declare function CiridaeAuthProvider({ children, auth, onAuthenticatedUserChange, }: {
|
|
10
|
+
children: React.ReactNode;
|
|
11
|
+
auth: CiridaeAuth;
|
|
12
|
+
onAuthenticatedUserChange?: (previousUserId: FirebaseUid | null, nextUserId: FirebaseUid | null) => void;
|
|
13
|
+
}): import("@types/react").JSX.Element;
|
|
14
|
+
export declare function useCiridaeAuth(): CiridaeAuthContextValue;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
3
|
+
const CiridaeAuthContext = createContext(null);
|
|
4
|
+
export function CiridaeAuthProvider({ children, auth, onAuthenticatedUserChange, }) {
|
|
5
|
+
const [session, setSession] = useState({ status: "unknown" });
|
|
6
|
+
const latestSettledUserId = useRef(undefined);
|
|
7
|
+
const signingOutUser = useRef(null);
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
let cancelled = false;
|
|
10
|
+
let unsubscribe;
|
|
11
|
+
void auth
|
|
12
|
+
.subscribe((user) => {
|
|
13
|
+
if (cancelled)
|
|
14
|
+
return;
|
|
15
|
+
const nextUserId = user?.uid ?? null;
|
|
16
|
+
if (latestSettledUserId.current !== undefined &&
|
|
17
|
+
latestSettledUserId.current !== nextUserId) {
|
|
18
|
+
onAuthenticatedUserChange?.(latestSettledUserId.current, nextUserId);
|
|
19
|
+
}
|
|
20
|
+
latestSettledUserId.current = nextUserId;
|
|
21
|
+
if (signingOutUser.current && user === null)
|
|
22
|
+
return;
|
|
23
|
+
setSession(user ? { status: "signedIn", user } : { status: "signedOut" });
|
|
24
|
+
})
|
|
25
|
+
.then((nextUnsubscribe) => {
|
|
26
|
+
if (cancelled)
|
|
27
|
+
nextUnsubscribe();
|
|
28
|
+
else
|
|
29
|
+
unsubscribe = nextUnsubscribe;
|
|
30
|
+
})
|
|
31
|
+
.catch((error) => {
|
|
32
|
+
if (!cancelled)
|
|
33
|
+
setSession({ status: "unavailable", error });
|
|
34
|
+
});
|
|
35
|
+
return () => {
|
|
36
|
+
cancelled = true;
|
|
37
|
+
unsubscribe?.();
|
|
38
|
+
};
|
|
39
|
+
}, [auth, onAuthenticatedUserChange]);
|
|
40
|
+
const value = useMemo(() => ({
|
|
41
|
+
auth,
|
|
42
|
+
session,
|
|
43
|
+
async signOut() {
|
|
44
|
+
if (session.status !== "signedIn")
|
|
45
|
+
return null;
|
|
46
|
+
signingOutUser.current = session;
|
|
47
|
+
setSession({ status: "signingOut", user: session.user });
|
|
48
|
+
try {
|
|
49
|
+
return await auth.signOut();
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
signingOutUser.current = null;
|
|
53
|
+
setSession(session);
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
}), [auth, session]);
|
|
58
|
+
return _jsx(CiridaeAuthContext.Provider, { value: value, children: children });
|
|
59
|
+
}
|
|
60
|
+
export function useCiridaeAuth() {
|
|
61
|
+
const context = useContext(CiridaeAuthContext);
|
|
62
|
+
if (!context)
|
|
63
|
+
throw new Error("useCiridaeAuth must render below CiridaeAuthProvider.");
|
|
64
|
+
return context;
|
|
65
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type CiridaeAuthServiceConfiguration = {
|
|
2
|
+
authServiceFrontendUrl: string;
|
|
3
|
+
callbackUrl: string;
|
|
4
|
+
projectId: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function buildCiridaeSignInUrl({ configuration, redirectPath, }: {
|
|
7
|
+
configuration: CiridaeAuthServiceConfiguration;
|
|
8
|
+
redirectPath: string;
|
|
9
|
+
}): string;
|
|
10
|
+
export declare function buildCiridaeSignOutUrl(configuration: CiridaeAuthServiceConfiguration): string;
|
|
11
|
+
export declare function parseSameOriginPath(value: string | null, fallback?: string): string;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export function buildCiridaeSignInUrl({ configuration, redirectPath, }) {
|
|
2
|
+
const callbackUrl = new URL(configuration.callbackUrl);
|
|
3
|
+
callbackUrl.searchParams.set("redirect_path", requireSameOriginPath(redirectPath));
|
|
4
|
+
const signInUrl = new URL(configuration.authServiceFrontendUrl);
|
|
5
|
+
signInUrl.searchParams.set("project_id", requireValue("projectId", configuration.projectId));
|
|
6
|
+
signInUrl.searchParams.set("redirect_url", callbackUrl.toString());
|
|
7
|
+
return signInUrl.toString();
|
|
8
|
+
}
|
|
9
|
+
export function buildCiridaeSignOutUrl(configuration) {
|
|
10
|
+
const signInUrl = new URL(configuration.authServiceFrontendUrl);
|
|
11
|
+
signInUrl.searchParams.set("project_id", requireValue("projectId", configuration.projectId));
|
|
12
|
+
signInUrl.searchParams.set("redirect_url", new URL(configuration.callbackUrl).toString());
|
|
13
|
+
const signOutUrl = new URL("/signout", configuration.authServiceFrontendUrl);
|
|
14
|
+
signOutUrl.searchParams.set("redirect_url", signInUrl.toString());
|
|
15
|
+
return signOutUrl.toString();
|
|
16
|
+
}
|
|
17
|
+
export function parseSameOriginPath(value, fallback = "/") {
|
|
18
|
+
if (!value?.startsWith("/") || value.startsWith("//"))
|
|
19
|
+
return fallback;
|
|
20
|
+
try {
|
|
21
|
+
const url = new URL(value, "https://ciridae-auth.local");
|
|
22
|
+
return `${url.pathname}${url.search}${url.hash}`;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return fallback;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function requireSameOriginPath(value) {
|
|
29
|
+
const parsed = parseSameOriginPath(value, "");
|
|
30
|
+
if (parsed)
|
|
31
|
+
return parsed;
|
|
32
|
+
throw new Error("redirectPath must be a same-origin path.");
|
|
33
|
+
}
|
|
34
|
+
function requireValue(name, value) {
|
|
35
|
+
if (value.trim())
|
|
36
|
+
return value;
|
|
37
|
+
throw new Error(`${name} is required.`);
|
|
38
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { AuthenticatedUser } from "./authenticatedUser.js";
|
|
2
|
+
export type AuthSession = {
|
|
3
|
+
status: "unknown";
|
|
4
|
+
} | {
|
|
5
|
+
status: "unavailable";
|
|
6
|
+
error: unknown;
|
|
7
|
+
} | {
|
|
8
|
+
status: "signedOut";
|
|
9
|
+
} | {
|
|
10
|
+
status: "signingOut";
|
|
11
|
+
user: AuthenticatedUser;
|
|
12
|
+
} | {
|
|
13
|
+
status: "signedIn";
|
|
14
|
+
user: AuthenticatedUser;
|
|
15
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { User } from "firebase/auth";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
export declare const FirebaseUidSchema: z.core.$ZodBranded<z.ZodString, "FirebaseUid", "out">;
|
|
4
|
+
export type FirebaseUid = z.infer<typeof FirebaseUidSchema>;
|
|
5
|
+
export declare const UserEmailSchema: z.core.$ZodBranded<z.ZodEmail, "UserEmail", "out">;
|
|
6
|
+
export type UserEmail = z.infer<typeof UserEmailSchema>;
|
|
7
|
+
export declare const AuthenticatedUserSchema: z.ZodObject<{
|
|
8
|
+
displayName: z.ZodNullable<z.ZodString>;
|
|
9
|
+
email: z.ZodNullable<z.core.$ZodBranded<z.ZodEmail, "UserEmail", "out">>;
|
|
10
|
+
emailVerified: z.ZodBoolean;
|
|
11
|
+
photoURL: z.ZodNullable<z.ZodString>;
|
|
12
|
+
uid: z.core.$ZodBranded<z.ZodString, "FirebaseUid", "out">;
|
|
13
|
+
}, z.core.$strip>;
|
|
14
|
+
export type AuthenticatedUser = z.infer<typeof AuthenticatedUserSchema>;
|
|
15
|
+
type FirebaseAuthenticatedUser = Pick<User, "displayName" | "email" | "emailVerified" | "photoURL" | "uid">;
|
|
16
|
+
export declare function parseAuthenticatedUser(user: FirebaseAuthenticatedUser): AuthenticatedUser;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const FirebaseUidSchema = z.string().min(1).max(128).brand();
|
|
3
|
+
export const UserEmailSchema = z.email().brand();
|
|
4
|
+
export const AuthenticatedUserSchema = z.object({
|
|
5
|
+
displayName: z.string().nullable(),
|
|
6
|
+
email: UserEmailSchema.nullable(),
|
|
7
|
+
emailVerified: z.boolean(),
|
|
8
|
+
photoURL: z.string().nullable(),
|
|
9
|
+
uid: FirebaseUidSchema,
|
|
10
|
+
});
|
|
11
|
+
export function parseAuthenticatedUser(user) {
|
|
12
|
+
return AuthenticatedUserSchema.parse(user);
|
|
13
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type AuthenticatedUser } from "./authenticatedUser.js";
|
|
2
|
+
import { type CiridaeAuthServiceConfiguration } from "./authServiceUrls.js";
|
|
3
|
+
export type CiridaeAuth = {
|
|
4
|
+
readonly mode: "firebase" | "localDevelopment";
|
|
5
|
+
getAccessToken(): Promise<string | null>;
|
|
6
|
+
getAuthenticatedUser(): AuthenticatedUser | null;
|
|
7
|
+
getSignInUrl(redirectPath: string): string | null;
|
|
8
|
+
completeSignIn(customToken: string): Promise<void>;
|
|
9
|
+
clearSession(): Promise<void>;
|
|
10
|
+
signOut(): Promise<string | null>;
|
|
11
|
+
subscribe(onAuthenticatedUser: (user: AuthenticatedUser | null) => void): Promise<() => void>;
|
|
12
|
+
};
|
|
13
|
+
export type CiridaeAuthConfiguration = {
|
|
14
|
+
identity: {
|
|
15
|
+
mode: "firebase";
|
|
16
|
+
apiKey: string;
|
|
17
|
+
authDomain: string;
|
|
18
|
+
} | {
|
|
19
|
+
mode: "localDevelopment";
|
|
20
|
+
};
|
|
21
|
+
authService: CiridaeAuthServiceConfiguration;
|
|
22
|
+
};
|
|
23
|
+
export declare function createCiridaeAuth(configuration: CiridaeAuthConfiguration): CiridaeAuth;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { getApps, initializeApp } from "firebase/app";
|
|
2
|
+
import { getAuth, inMemoryPersistence, onAuthStateChanged, setPersistence, signInWithCustomToken, signOut as firebaseSignOut, } from "firebase/auth";
|
|
3
|
+
import { AuthenticatedUserSchema } from "./authenticatedUser.js";
|
|
4
|
+
import { buildCiridaeSignInUrl, buildCiridaeSignOutUrl, } from "./authServiceUrls.js";
|
|
5
|
+
const FIREBASE_APP_NAME = "ciridae-browser-auth";
|
|
6
|
+
const LOCAL_DEVELOPMENT_TOKEN = "dev-only-auth-bypass";
|
|
7
|
+
const LOCAL_DEVELOPMENT_USER = AuthenticatedUserSchema.parse({
|
|
8
|
+
displayName: "Local Developer",
|
|
9
|
+
email: "dev-only-auth-bypass@ciridae.dev",
|
|
10
|
+
emailVerified: true,
|
|
11
|
+
photoURL: null,
|
|
12
|
+
uid: LOCAL_DEVELOPMENT_TOKEN,
|
|
13
|
+
});
|
|
14
|
+
export function createCiridaeAuth(configuration) {
|
|
15
|
+
if (configuration.identity.mode === "localDevelopment") {
|
|
16
|
+
return createLocalDevelopmentAuth(configuration.authService);
|
|
17
|
+
}
|
|
18
|
+
return createFirebaseAuth(configuration.identity, configuration.authService);
|
|
19
|
+
}
|
|
20
|
+
function createLocalDevelopmentAuth(authServiceConfiguration) {
|
|
21
|
+
return {
|
|
22
|
+
mode: "localDevelopment",
|
|
23
|
+
async getAccessToken() {
|
|
24
|
+
return LOCAL_DEVELOPMENT_TOKEN;
|
|
25
|
+
},
|
|
26
|
+
getAuthenticatedUser() {
|
|
27
|
+
return LOCAL_DEVELOPMENT_USER;
|
|
28
|
+
},
|
|
29
|
+
getSignInUrl(redirectPath) {
|
|
30
|
+
return getSignInUrl(authServiceConfiguration, redirectPath);
|
|
31
|
+
},
|
|
32
|
+
async completeSignIn() {
|
|
33
|
+
throw new Error("Sign in is unavailable in local development auth mode.");
|
|
34
|
+
},
|
|
35
|
+
async clearSession() {
|
|
36
|
+
return undefined;
|
|
37
|
+
},
|
|
38
|
+
async signOut() {
|
|
39
|
+
return null;
|
|
40
|
+
},
|
|
41
|
+
async subscribe(onAuthenticatedUser) {
|
|
42
|
+
onAuthenticatedUser(LOCAL_DEVELOPMENT_USER);
|
|
43
|
+
return () => undefined;
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function createFirebaseAuth(identityConfiguration, authServiceConfiguration) {
|
|
48
|
+
let auth;
|
|
49
|
+
function getFirebaseAuth() {
|
|
50
|
+
if (auth)
|
|
51
|
+
return auth;
|
|
52
|
+
const firebaseOptions = {
|
|
53
|
+
apiKey: requireSetting("apiKey", identityConfiguration.apiKey),
|
|
54
|
+
authDomain: requireSetting("authDomain", identityConfiguration.authDomain),
|
|
55
|
+
};
|
|
56
|
+
const existingApp = getApps().find((app) => app.name === FIREBASE_APP_NAME);
|
|
57
|
+
const app = existingApp ?? initializeApp(firebaseOptions, FIREBASE_APP_NAME);
|
|
58
|
+
auth = getAuth(app);
|
|
59
|
+
return auth;
|
|
60
|
+
}
|
|
61
|
+
async function clearSession() {
|
|
62
|
+
await firebaseSignOut(getFirebaseAuth());
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
mode: "firebase",
|
|
66
|
+
async getAccessToken() {
|
|
67
|
+
return getFirebaseAuth().currentUser?.getIdToken() ?? null;
|
|
68
|
+
},
|
|
69
|
+
getAuthenticatedUser() {
|
|
70
|
+
const user = getFirebaseAuth().currentUser;
|
|
71
|
+
return user ? AuthenticatedUserSchema.parse(user) : null;
|
|
72
|
+
},
|
|
73
|
+
getSignInUrl(redirectPath) {
|
|
74
|
+
return getSignInUrl(authServiceConfiguration, redirectPath);
|
|
75
|
+
},
|
|
76
|
+
async completeSignIn(customToken) {
|
|
77
|
+
await signInWithCustomToken(getFirebaseAuth(), customToken);
|
|
78
|
+
},
|
|
79
|
+
clearSession,
|
|
80
|
+
async signOut() {
|
|
81
|
+
await clearSession();
|
|
82
|
+
return hasAuthServiceConfiguration(authServiceConfiguration)
|
|
83
|
+
? buildCiridaeSignOutUrl(authServiceConfiguration)
|
|
84
|
+
: null;
|
|
85
|
+
},
|
|
86
|
+
async subscribe(onAuthenticatedUser) {
|
|
87
|
+
const firebaseAuth = getFirebaseAuth();
|
|
88
|
+
await setPersistence(firebaseAuth, inMemoryPersistence);
|
|
89
|
+
return onAuthStateChanged(firebaseAuth, (user) => {
|
|
90
|
+
onAuthenticatedUser(user ? AuthenticatedUserSchema.parse(user) : null);
|
|
91
|
+
});
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function getSignInUrl(configuration, redirectPath) {
|
|
96
|
+
return hasAuthServiceConfiguration(configuration)
|
|
97
|
+
? buildCiridaeSignInUrl({ configuration, redirectPath })
|
|
98
|
+
: null;
|
|
99
|
+
}
|
|
100
|
+
function hasAuthServiceConfiguration(configuration) {
|
|
101
|
+
return Boolean(configuration.authServiceFrontendUrl.trim() &&
|
|
102
|
+
configuration.callbackUrl.trim() &&
|
|
103
|
+
configuration.projectId.trim());
|
|
104
|
+
}
|
|
105
|
+
function requireSetting(name, value) {
|
|
106
|
+
if (value.trim())
|
|
107
|
+
return value;
|
|
108
|
+
throw new Error(`${name} is required when Firebase authentication is enabled.`);
|
|
109
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type CompleteCiridaeSignInState = {
|
|
2
|
+
status: "waitingForAuth";
|
|
3
|
+
} | {
|
|
4
|
+
status: "authUnavailable";
|
|
5
|
+
} | {
|
|
6
|
+
status: "signingIn";
|
|
7
|
+
} | {
|
|
8
|
+
status: "missingToken";
|
|
9
|
+
} | {
|
|
10
|
+
status: "failed";
|
|
11
|
+
} | {
|
|
12
|
+
status: "redirecting";
|
|
13
|
+
};
|
|
14
|
+
export declare function useCompleteCiridaeSignIn({ customToken, onComplete, redirectPath, }: {
|
|
15
|
+
customToken: string | null;
|
|
16
|
+
onComplete: (redirectPath: string) => void;
|
|
17
|
+
redirectPath: string;
|
|
18
|
+
}): CompleteCiridaeSignInState;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from "react";
|
|
2
|
+
import { useCiridaeAuth } from "./CiridaeAuthProvider.js";
|
|
3
|
+
export function useCompleteCiridaeSignIn({ customToken, onComplete, redirectPath, }) {
|
|
4
|
+
const { auth, session } = useCiridaeAuth();
|
|
5
|
+
const [failedToken, setFailedToken] = useState(null);
|
|
6
|
+
const signInAttempt = useRef(null);
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
if (session.status !== "signedOut" || !customToken)
|
|
9
|
+
return;
|
|
10
|
+
if (signInAttempt.current?.customToken !== customToken) {
|
|
11
|
+
signInAttempt.current = {
|
|
12
|
+
customToken,
|
|
13
|
+
promise: auth.completeSignIn(customToken),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
let cancelled = false;
|
|
17
|
+
void signInAttempt.current.promise.catch(() => {
|
|
18
|
+
if (!cancelled)
|
|
19
|
+
setFailedToken(customToken);
|
|
20
|
+
});
|
|
21
|
+
return () => {
|
|
22
|
+
cancelled = true;
|
|
23
|
+
};
|
|
24
|
+
}, [auth, customToken, session.status]);
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (session.status === "signedIn")
|
|
27
|
+
onComplete(redirectPath);
|
|
28
|
+
}, [onComplete, redirectPath, session.status]);
|
|
29
|
+
if (session.status === "unknown")
|
|
30
|
+
return { status: "waitingForAuth" };
|
|
31
|
+
if (session.status === "unavailable")
|
|
32
|
+
return { status: "authUnavailable" };
|
|
33
|
+
if (session.status === "signedIn")
|
|
34
|
+
return { status: "redirecting" };
|
|
35
|
+
if (failedToken === customToken)
|
|
36
|
+
return { status: "failed" };
|
|
37
|
+
if (!customToken)
|
|
38
|
+
return { status: "missingToken" };
|
|
39
|
+
return { status: "signingIn" };
|
|
40
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ciridae/auth",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"private": false,
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=22.18"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/ciridae-ai/ciridae.git",
|
|
12
|
+
"directory": "packages/auth"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/ciridae-ai/ciridae#readme",
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "public"
|
|
17
|
+
},
|
|
18
|
+
"exports": {
|
|
19
|
+
"./package.json": "./package.json",
|
|
20
|
+
"./*": {
|
|
21
|
+
"types": "./dist/entries/*.d.ts",
|
|
22
|
+
"default": "./dist/entries/*.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist",
|
|
27
|
+
"README.md"
|
|
28
|
+
],
|
|
29
|
+
"peerDependencies": {
|
|
30
|
+
"@types/react": ">=18",
|
|
31
|
+
"react": ">=18"
|
|
32
|
+
},
|
|
33
|
+
"peerDependenciesMeta": {
|
|
34
|
+
"@types/react": {
|
|
35
|
+
"optional": true
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"firebase": "12.15.0",
|
|
40
|
+
"zod": "^4.4.3"
|
|
41
|
+
}
|
|
42
|
+
}
|