@dalgoridim/headless-cms 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.
Files changed (87) hide show
  1. package/LICENSE +10 -0
  2. package/README.md +178 -0
  3. package/dist/adapters/firestore/index.cjs +152 -0
  4. package/dist/adapters/firestore/index.cjs.map +1 -0
  5. package/dist/adapters/firestore/index.d.cts +39 -0
  6. package/dist/adapters/firestore/index.d.ts +39 -0
  7. package/dist/adapters/firestore/index.js +120 -0
  8. package/dist/adapters/firestore/index.js.map +1 -0
  9. package/dist/adapters/postgres/index.cjs +299 -0
  10. package/dist/adapters/postgres/index.cjs.map +1 -0
  11. package/dist/adapters/postgres/index.d.cts +59 -0
  12. package/dist/adapters/postgres/index.d.ts +59 -0
  13. package/dist/adapters/postgres/index.js +277 -0
  14. package/dist/adapters/postgres/index.js.map +1 -0
  15. package/dist/auth/firebase/client/index.cjs +153 -0
  16. package/dist/auth/firebase/client/index.cjs.map +1 -0
  17. package/dist/auth/firebase/client/index.d.cts +29 -0
  18. package/dist/auth/firebase/client/index.d.ts +29 -0
  19. package/dist/auth/firebase/client/index.js +138 -0
  20. package/dist/auth/firebase/client/index.js.map +1 -0
  21. package/dist/auth/firebase/index.cjs +81 -0
  22. package/dist/auth/firebase/index.cjs.map +1 -0
  23. package/dist/auth/firebase/index.d.cts +23 -0
  24. package/dist/auth/firebase/index.d.ts +23 -0
  25. package/dist/auth/firebase/index.js +46 -0
  26. package/dist/auth/firebase/index.js.map +1 -0
  27. package/dist/auth/nextauth/index.cjs +51 -0
  28. package/dist/auth/nextauth/index.cjs.map +1 -0
  29. package/dist/auth/nextauth/index.d.cts +30 -0
  30. package/dist/auth/nextauth/index.d.ts +30 -0
  31. package/dist/auth/nextauth/index.js +25 -0
  32. package/dist/auth/nextauth/index.js.map +1 -0
  33. package/dist/client/index.cjs +1018 -0
  34. package/dist/client/index.cjs.map +1 -0
  35. package/dist/client/index.d.cts +96 -0
  36. package/dist/client/index.d.ts +96 -0
  37. package/dist/client/index.js +994 -0
  38. package/dist/client/index.js.map +1 -0
  39. package/dist/index.cjs +19 -0
  40. package/dist/index.cjs.map +1 -0
  41. package/dist/index.d.cts +122 -0
  42. package/dist/index.d.ts +122 -0
  43. package/dist/index.js +1 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/server/index.cjs +128 -0
  46. package/dist/server/index.cjs.map +1 -0
  47. package/dist/server/index.d.cts +52 -0
  48. package/dist/server/index.d.ts +52 -0
  49. package/dist/server/index.js +99 -0
  50. package/dist/server/index.js.map +1 -0
  51. package/dist/storage/cloudinary/index.cjs +55 -0
  52. package/dist/storage/cloudinary/index.cjs.map +1 -0
  53. package/dist/storage/cloudinary/index.d.cts +17 -0
  54. package/dist/storage/cloudinary/index.d.ts +17 -0
  55. package/dist/storage/cloudinary/index.js +30 -0
  56. package/dist/storage/cloudinary/index.js.map +1 -0
  57. package/dist/storage/cloudinary/server.cjs +56 -0
  58. package/dist/storage/cloudinary/server.cjs.map +1 -0
  59. package/dist/storage/cloudinary/server.d.cts +16 -0
  60. package/dist/storage/cloudinary/server.d.ts +16 -0
  61. package/dist/storage/cloudinary/server.js +31 -0
  62. package/dist/storage/cloudinary/server.js.map +1 -0
  63. package/dist/storage/local/index.cjs +44 -0
  64. package/dist/storage/local/index.cjs.map +1 -0
  65. package/dist/storage/local/index.d.cts +15 -0
  66. package/dist/storage/local/index.d.ts +15 -0
  67. package/dist/storage/local/index.js +19 -0
  68. package/dist/storage/local/index.js.map +1 -0
  69. package/dist/storage/local/server.cjs +61 -0
  70. package/dist/storage/local/server.cjs.map +1 -0
  71. package/dist/storage/local/server.d.cts +16 -0
  72. package/dist/storage/local/server.d.ts +16 -0
  73. package/dist/storage/local/server.js +26 -0
  74. package/dist/storage/local/server.js.map +1 -0
  75. package/dist/storage/s3/index.cjs +52 -0
  76. package/dist/storage/s3/index.cjs.map +1 -0
  77. package/dist/storage/s3/index.d.cts +14 -0
  78. package/dist/storage/s3/index.d.ts +14 -0
  79. package/dist/storage/s3/index.js +27 -0
  80. package/dist/storage/s3/index.js.map +1 -0
  81. package/dist/storage/s3/server.cjs +61 -0
  82. package/dist/storage/s3/server.cjs.map +1 -0
  83. package/dist/storage/s3/server.d.cts +19 -0
  84. package/dist/storage/s3/server.d.ts +19 -0
  85. package/dist/storage/s3/server.js +36 -0
  86. package/dist/storage/s3/server.js.map +1 -0
  87. package/package.json +165 -0
@@ -0,0 +1,138 @@
1
+ "use client";
2
+
3
+ // src/auth/firebase/client/index.tsx
4
+ import {
5
+ createContext,
6
+ useContext,
7
+ useEffect,
8
+ useState
9
+ } from "react";
10
+ import {
11
+ signInWithPopup,
12
+ signInWithEmailAndPassword,
13
+ signOut,
14
+ onAuthStateChanged
15
+ } from "firebase/auth";
16
+ import { CmsAuthProvider } from "@dalgoridim/headless-cms/client";
17
+ import { jsx } from "react/jsx-runtime";
18
+ var FirebaseAuthContext = createContext(
19
+ void 0
20
+ );
21
+ function setCookie(name, value) {
22
+ document.cookie = `${name}=${encodeURIComponent(value)}; path=/`;
23
+ }
24
+ function deleteCookie(name) {
25
+ document.cookie = `${name}=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
26
+ }
27
+ function FirebaseAuthProvider({
28
+ children,
29
+ auth,
30
+ googleProvider,
31
+ cookieName = "adminToken",
32
+ onLogout
33
+ }) {
34
+ const [user, setUser] = useState(null);
35
+ const [isAdmin, setIsAdmin] = useState(false);
36
+ const [isEditing, setIsEditing] = useState(false);
37
+ useEffect(() => {
38
+ const unsubscribe = onAuthStateChanged(auth, async (u) => {
39
+ if (!u) {
40
+ setUser(null);
41
+ setIsAdmin(false);
42
+ deleteCookie(cookieName);
43
+ return;
44
+ }
45
+ const tokenResult = await u.getIdTokenResult();
46
+ const admin = !!tokenResult.claims.admin;
47
+ if (!admin) {
48
+ await signOut(auth);
49
+ setUser(null);
50
+ setIsAdmin(false);
51
+ deleteCookie(cookieName);
52
+ return;
53
+ }
54
+ setUser(u);
55
+ setIsAdmin(true);
56
+ setCookie(cookieName, tokenResult.token);
57
+ });
58
+ return () => unsubscribe();
59
+ }, [auth, cookieName]);
60
+ useEffect(() => {
61
+ const originalFetch = window.fetch;
62
+ window.fetch = async (...args) => {
63
+ const response = await originalFetch(...args);
64
+ if (response.status === 401) {
65
+ try {
66
+ const data = await response.clone().json();
67
+ if (data == null ? void 0 : data.logout) {
68
+ await signOut(auth);
69
+ setUser(null);
70
+ setIsAdmin(false);
71
+ setIsEditing(false);
72
+ deleteCookie(cookieName);
73
+ onLogout == null ? void 0 : onLogout();
74
+ }
75
+ } catch (e) {
76
+ }
77
+ }
78
+ return response;
79
+ };
80
+ return () => {
81
+ window.fetch = originalFetch;
82
+ };
83
+ }, [auth, cookieName, onLogout]);
84
+ const requireAdminClaim = async (u) => {
85
+ const tokenResult = await u.getIdTokenResult();
86
+ if (!tokenResult.claims.admin) {
87
+ await signOut(auth);
88
+ throw new Error("Unauthorized");
89
+ }
90
+ setUser(u);
91
+ setIsAdmin(true);
92
+ setCookie(cookieName, tokenResult.token);
93
+ };
94
+ const loginWithGoogle = async () => {
95
+ if (!googleProvider)
96
+ throw new Error("FirebaseAuthProvider: googleProvider not configured");
97
+ const result = await signInWithPopup(auth, googleProvider);
98
+ await requireAdminClaim(result.user);
99
+ };
100
+ const loginWithEmail = async (email, password) => {
101
+ const result = await signInWithEmailAndPassword(auth, email, password);
102
+ await requireAdminClaim(result.user);
103
+ };
104
+ const logout = async () => {
105
+ await signOut(auth);
106
+ setUser(null);
107
+ setIsAdmin(false);
108
+ setIsEditing(false);
109
+ deleteCookie(cookieName);
110
+ };
111
+ const toggleEdit = () => setIsEditing((p) => !p);
112
+ return /* @__PURE__ */ jsx(
113
+ FirebaseAuthContext.Provider,
114
+ {
115
+ value: {
116
+ user,
117
+ isAdmin,
118
+ isEditing,
119
+ toggleEdit,
120
+ loginWithGoogle,
121
+ loginWithEmail,
122
+ logout
123
+ },
124
+ children: /* @__PURE__ */ jsx(CmsAuthProvider, { value: { isAdmin, isEditing, toggleEdit }, children })
125
+ }
126
+ );
127
+ }
128
+ function useFirebaseAuth() {
129
+ const ctx = useContext(FirebaseAuthContext);
130
+ if (!ctx)
131
+ throw new Error("useFirebaseAuth must be used within a FirebaseAuthProvider");
132
+ return ctx;
133
+ }
134
+ export {
135
+ FirebaseAuthProvider,
136
+ useFirebaseAuth
137
+ };
138
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/auth/firebase/client/index.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n useContext,\n useEffect,\n useState,\n type ReactNode,\n} from \"react\";\nimport {\n signInWithPopup,\n signInWithEmailAndPassword,\n signOut,\n onAuthStateChanged,\n type Auth,\n type User,\n type GoogleAuthProvider,\n} from \"firebase/auth\";\n// Imported via the public specifier so we share the SAME context instance as\n// the consumer's edit primitives at runtime (see tsup `external` + tsconfig paths).\nimport { CmsAuthProvider } from \"@dalgoridim/headless-cms/client\";\n\nexport interface FirebaseAuthProviderProps {\n children: ReactNode;\n /** A Firebase `Auth` instance from the consumer's app config. */\n auth: Auth;\n /** Optional Google provider for `loginWithGoogle`. */\n googleProvider?: GoogleAuthProvider;\n /** Cookie name for the ID token. Default `adminToken`. */\n cookieName?: string;\n /** Called when a 401 `{ logout: true }` response is intercepted. */\n onLogout?: () => void;\n}\n\ninterface FirebaseAuthContextValue {\n user: User | null;\n isAdmin: boolean;\n isEditing: boolean;\n toggleEdit: () => void;\n loginWithGoogle: () => Promise<void>;\n loginWithEmail: (email: string, password: string) => Promise<void>;\n logout: () => Promise<void>;\n}\n\nconst FirebaseAuthContext = createContext<FirebaseAuthContextValue | undefined>(\n undefined,\n);\n\nfunction setCookie(name: string, value: string) {\n document.cookie = `${name}=${encodeURIComponent(value)}; path=/`;\n}\nfunction deleteCookie(name: string) {\n document.cookie = `${name}=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT`;\n}\n\nexport function FirebaseAuthProvider({\n children,\n auth,\n googleProvider,\n cookieName = \"adminToken\",\n onLogout,\n}: FirebaseAuthProviderProps) {\n const [user, setUser] = useState<User | null>(null);\n const [isAdmin, setIsAdmin] = useState(false);\n const [isEditing, setIsEditing] = useState(false);\n\n useEffect(() => {\n const unsubscribe = onAuthStateChanged(auth, async (u) => {\n if (!u) {\n setUser(null);\n setIsAdmin(false);\n deleteCookie(cookieName);\n return;\n }\n const tokenResult = await u.getIdTokenResult();\n const admin = !!tokenResult.claims.admin;\n if (!admin) {\n await signOut(auth);\n setUser(null);\n setIsAdmin(false);\n deleteCookie(cookieName);\n return;\n }\n setUser(u);\n setIsAdmin(true);\n setCookie(cookieName, tokenResult.token);\n });\n return () => unsubscribe();\n }, [auth, cookieName]);\n\n // Intercept admin 401s so an expired session forces sign-out.\n useEffect(() => {\n const originalFetch = window.fetch;\n window.fetch = async (...args: Parameters<typeof fetch>) => {\n const response = await originalFetch(...args);\n if (response.status === 401) {\n try {\n const data = await response.clone().json();\n if (data?.logout) {\n await signOut(auth);\n setUser(null);\n setIsAdmin(false);\n setIsEditing(false);\n deleteCookie(cookieName);\n onLogout?.();\n }\n } catch {\n /* not a JSON body — ignore */\n }\n }\n return response;\n };\n return () => {\n window.fetch = originalFetch;\n };\n }, [auth, cookieName, onLogout]);\n\n const requireAdminClaim = async (u: User) => {\n const tokenResult = await u.getIdTokenResult();\n if (!tokenResult.claims.admin) {\n await signOut(auth);\n throw new Error(\"Unauthorized\");\n }\n setUser(u);\n setIsAdmin(true);\n setCookie(cookieName, tokenResult.token);\n };\n\n const loginWithGoogle = async () => {\n if (!googleProvider)\n throw new Error(\"FirebaseAuthProvider: googleProvider not configured\");\n const result = await signInWithPopup(auth, googleProvider);\n await requireAdminClaim(result.user);\n };\n\n const loginWithEmail = async (email: string, password: string) => {\n const result = await signInWithEmailAndPassword(auth, email, password);\n await requireAdminClaim(result.user);\n };\n\n const logout = async () => {\n await signOut(auth);\n setUser(null);\n setIsAdmin(false);\n setIsEditing(false);\n deleteCookie(cookieName);\n };\n\n const toggleEdit = () => setIsEditing((p) => !p);\n\n return (\n <FirebaseAuthContext.Provider\n value={{\n user,\n isAdmin,\n isEditing,\n toggleEdit,\n loginWithGoogle,\n loginWithEmail,\n logout,\n }}\n >\n <CmsAuthProvider value={{ isAdmin, isEditing, toggleEdit }}>\n {children}\n </CmsAuthProvider>\n </FirebaseAuthContext.Provider>\n );\n}\n\n/** Extended Firebase auth API (login/logout/user) for login pages and toolbars. */\nexport function useFirebaseAuth(): FirebaseAuthContextValue {\n const ctx = useContext(FirebaseAuthContext);\n if (!ctx)\n throw new Error(\"useFirebaseAuth must be used within a FirebaseAuthProvider\");\n return ctx;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/auth/firebase/index.ts
31
+ var firebase_exports = {};
32
+ __export(firebase_exports, {
33
+ firebaseAuth: () => firebaseAuth
34
+ });
35
+ module.exports = __toCommonJS(firebase_exports);
36
+ var import_firebase_admin = __toESM(require("firebase-admin"), 1);
37
+ function readCookie(req, name) {
38
+ const header = req.headers.get("cookie");
39
+ if (!header) return null;
40
+ for (const part of header.split(";")) {
41
+ const [k, ...v] = part.trim().split("=");
42
+ if (k === name) return decodeURIComponent(v.join("="));
43
+ }
44
+ return null;
45
+ }
46
+ function firebaseAuth(config) {
47
+ var _a;
48
+ const cookieName = (_a = config.cookieName) != null ? _a : "adminToken";
49
+ const allowed = config.adminEmails.map((e) => e.trim());
50
+ if (!import_firebase_admin.default.apps.length && config.credentials) {
51
+ const c = config.credentials;
52
+ import_firebase_admin.default.initializeApp({
53
+ credential: import_firebase_admin.default.credential.cert({
54
+ projectId: c.projectId,
55
+ clientEmail: c.clientEmail,
56
+ privateKey: c.privateKey
57
+ }),
58
+ databaseURL: c.databaseURL
59
+ });
60
+ }
61
+ return {
62
+ async verifyRequest(req) {
63
+ var _a2;
64
+ const token = readCookie(req, cookieName);
65
+ if (!token) return null;
66
+ let decoded;
67
+ try {
68
+ decoded = await import_firebase_admin.default.auth().verifyIdToken(token);
69
+ } catch (e) {
70
+ return null;
71
+ }
72
+ const isAdmin = !!decoded.admin && allowed.includes((_a2 = decoded.email) != null ? _a2 : "");
73
+ return { userId: decoded.uid, email: decoded.email, isAdmin };
74
+ }
75
+ };
76
+ }
77
+ // Annotate the CommonJS export names for ESM import in node:
78
+ 0 && (module.exports = {
79
+ firebaseAuth
80
+ });
81
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/auth/firebase/index.ts"],"sourcesContent":["import admin from \"firebase-admin\";\nimport type { AuthAdapter, AuthIdentity } from \"../../types\";\n\nexport interface FirebaseAuthConfig {\n /** Allowlist of admin emails. Both the `admin` claim AND this list must agree. */\n adminEmails: string[];\n /** Cookie carrying the Firebase ID token. Default `adminToken`. */\n cookieName?: string;\n /** Service-account credentials (only used if firebase-admin isn't initialized). */\n credentials?: {\n projectId?: string;\n clientEmail?: string;\n privateKey?: string;\n databaseURL?: string;\n };\n}\n\nfunction readCookie(req: Request, name: string): string | null {\n const header = req.headers.get(\"cookie\");\n if (!header) return null;\n for (const part of header.split(\";\")) {\n const [k, ...v] = part.trim().split(\"=\");\n if (k === name) return decodeURIComponent(v.join(\"=\"));\n }\n return null;\n}\n\n/**\n * Server auth adapter backed by Firebase ID tokens. Verifies the token from the\n * cookie and requires both the `admin` custom claim and membership in\n * `adminEmails`.\n */\nexport function firebaseAuth(config: FirebaseAuthConfig): AuthAdapter {\n const cookieName = config.cookieName ?? \"adminToken\";\n const allowed = config.adminEmails.map((e) => e.trim());\n\n if (!admin.apps.length && config.credentials) {\n const c = config.credentials;\n admin.initializeApp({\n credential: admin.credential.cert({\n projectId: c.projectId,\n clientEmail: c.clientEmail,\n privateKey: c.privateKey,\n }),\n databaseURL: c.databaseURL,\n });\n }\n\n return {\n async verifyRequest(req: Request): Promise<AuthIdentity | null> {\n const token = readCookie(req, cookieName);\n if (!token) return null;\n\n let decoded;\n try {\n decoded = await admin.auth().verifyIdToken(token);\n } catch {\n // Expired/invalid token → treat as unauthorized so the gate returns a\n // 401 { logout: true } and the client can force sign-out.\n return null;\n }\n\n const isAdmin =\n !!decoded.admin && allowed.includes(decoded.email ?? \"\");\n\n return { userId: decoded.uid, email: decoded.email, isAdmin };\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAAkB;AAiBlB,SAAS,WAAW,KAAc,MAA6B;AAC7D,QAAM,SAAS,IAAI,QAAQ,IAAI,QAAQ;AACvC,MAAI,CAAC,OAAQ,QAAO;AACpB,aAAW,QAAQ,OAAO,MAAM,GAAG,GAAG;AACpC,UAAM,CAAC,GAAG,GAAG,CAAC,IAAI,KAAK,KAAK,EAAE,MAAM,GAAG;AACvC,QAAI,MAAM,KAAM,QAAO,mBAAmB,EAAE,KAAK,GAAG,CAAC;AAAA,EACvD;AACA,SAAO;AACT;AAOO,SAAS,aAAa,QAAyC;AAhCtE;AAiCE,QAAM,cAAa,YAAO,eAAP,YAAqB;AACxC,QAAM,UAAU,OAAO,YAAY,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AAEtD,MAAI,CAAC,sBAAAA,QAAM,KAAK,UAAU,OAAO,aAAa;AAC5C,UAAM,IAAI,OAAO;AACjB,0BAAAA,QAAM,cAAc;AAAA,MAClB,YAAY,sBAAAA,QAAM,WAAW,KAAK;AAAA,QAChC,WAAW,EAAE;AAAA,QACb,aAAa,EAAE;AAAA,QACf,YAAY,EAAE;AAAA,MAChB,CAAC;AAAA,MACD,aAAa,EAAE;AAAA,IACjB,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,MAAM,cAAc,KAA4C;AAjDpE,UAAAC;AAkDM,YAAM,QAAQ,WAAW,KAAK,UAAU;AACxC,UAAI,CAAC,MAAO,QAAO;AAEnB,UAAI;AACJ,UAAI;AACF,kBAAU,MAAM,sBAAAD,QAAM,KAAK,EAAE,cAAc,KAAK;AAAA,MAClD,SAAQ;AAGN,eAAO;AAAA,MACT;AAEA,YAAM,UACJ,CAAC,CAAC,QAAQ,SAAS,QAAQ,UAASC,MAAA,QAAQ,UAAR,OAAAA,MAAiB,EAAE;AAEzD,aAAO,EAAE,QAAQ,QAAQ,KAAK,OAAO,QAAQ,OAAO,QAAQ;AAAA,IAC9D;AAAA,EACF;AACF;","names":["admin","_a"]}
@@ -0,0 +1,23 @@
1
+ import { AuthAdapter } from '../../index.cjs';
2
+
3
+ interface FirebaseAuthConfig {
4
+ /** Allowlist of admin emails. Both the `admin` claim AND this list must agree. */
5
+ adminEmails: string[];
6
+ /** Cookie carrying the Firebase ID token. Default `adminToken`. */
7
+ cookieName?: string;
8
+ /** Service-account credentials (only used if firebase-admin isn't initialized). */
9
+ credentials?: {
10
+ projectId?: string;
11
+ clientEmail?: string;
12
+ privateKey?: string;
13
+ databaseURL?: string;
14
+ };
15
+ }
16
+ /**
17
+ * Server auth adapter backed by Firebase ID tokens. Verifies the token from the
18
+ * cookie and requires both the `admin` custom claim and membership in
19
+ * `adminEmails`.
20
+ */
21
+ declare function firebaseAuth(config: FirebaseAuthConfig): AuthAdapter;
22
+
23
+ export { type FirebaseAuthConfig, firebaseAuth };
@@ -0,0 +1,23 @@
1
+ import { AuthAdapter } from '../../index.js';
2
+
3
+ interface FirebaseAuthConfig {
4
+ /** Allowlist of admin emails. Both the `admin` claim AND this list must agree. */
5
+ adminEmails: string[];
6
+ /** Cookie carrying the Firebase ID token. Default `adminToken`. */
7
+ cookieName?: string;
8
+ /** Service-account credentials (only used if firebase-admin isn't initialized). */
9
+ credentials?: {
10
+ projectId?: string;
11
+ clientEmail?: string;
12
+ privateKey?: string;
13
+ databaseURL?: string;
14
+ };
15
+ }
16
+ /**
17
+ * Server auth adapter backed by Firebase ID tokens. Verifies the token from the
18
+ * cookie and requires both the `admin` custom claim and membership in
19
+ * `adminEmails`.
20
+ */
21
+ declare function firebaseAuth(config: FirebaseAuthConfig): AuthAdapter;
22
+
23
+ export { type FirebaseAuthConfig, firebaseAuth };
@@ -0,0 +1,46 @@
1
+ // src/auth/firebase/index.ts
2
+ import admin from "firebase-admin";
3
+ function readCookie(req, name) {
4
+ const header = req.headers.get("cookie");
5
+ if (!header) return null;
6
+ for (const part of header.split(";")) {
7
+ const [k, ...v] = part.trim().split("=");
8
+ if (k === name) return decodeURIComponent(v.join("="));
9
+ }
10
+ return null;
11
+ }
12
+ function firebaseAuth(config) {
13
+ var _a;
14
+ const cookieName = (_a = config.cookieName) != null ? _a : "adminToken";
15
+ const allowed = config.adminEmails.map((e) => e.trim());
16
+ if (!admin.apps.length && config.credentials) {
17
+ const c = config.credentials;
18
+ admin.initializeApp({
19
+ credential: admin.credential.cert({
20
+ projectId: c.projectId,
21
+ clientEmail: c.clientEmail,
22
+ privateKey: c.privateKey
23
+ }),
24
+ databaseURL: c.databaseURL
25
+ });
26
+ }
27
+ return {
28
+ async verifyRequest(req) {
29
+ var _a2;
30
+ const token = readCookie(req, cookieName);
31
+ if (!token) return null;
32
+ let decoded;
33
+ try {
34
+ decoded = await admin.auth().verifyIdToken(token);
35
+ } catch (e) {
36
+ return null;
37
+ }
38
+ const isAdmin = !!decoded.admin && allowed.includes((_a2 = decoded.email) != null ? _a2 : "");
39
+ return { userId: decoded.uid, email: decoded.email, isAdmin };
40
+ }
41
+ };
42
+ }
43
+ export {
44
+ firebaseAuth
45
+ };
46
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/auth/firebase/index.ts"],"sourcesContent":["import admin from \"firebase-admin\";\nimport type { AuthAdapter, AuthIdentity } from \"../../types\";\n\nexport interface FirebaseAuthConfig {\n /** Allowlist of admin emails. Both the `admin` claim AND this list must agree. */\n adminEmails: string[];\n /** Cookie carrying the Firebase ID token. Default `adminToken`. */\n cookieName?: string;\n /** Service-account credentials (only used if firebase-admin isn't initialized). */\n credentials?: {\n projectId?: string;\n clientEmail?: string;\n privateKey?: string;\n databaseURL?: string;\n };\n}\n\nfunction readCookie(req: Request, name: string): string | null {\n const header = req.headers.get(\"cookie\");\n if (!header) return null;\n for (const part of header.split(\";\")) {\n const [k, ...v] = part.trim().split(\"=\");\n if (k === name) return decodeURIComponent(v.join(\"=\"));\n }\n return null;\n}\n\n/**\n * Server auth adapter backed by Firebase ID tokens. Verifies the token from the\n * cookie and requires both the `admin` custom claim and membership in\n * `adminEmails`.\n */\nexport function firebaseAuth(config: FirebaseAuthConfig): AuthAdapter {\n const cookieName = config.cookieName ?? \"adminToken\";\n const allowed = config.adminEmails.map((e) => e.trim());\n\n if (!admin.apps.length && config.credentials) {\n const c = config.credentials;\n admin.initializeApp({\n credential: admin.credential.cert({\n projectId: c.projectId,\n clientEmail: c.clientEmail,\n privateKey: c.privateKey,\n }),\n databaseURL: c.databaseURL,\n });\n }\n\n return {\n async verifyRequest(req: Request): Promise<AuthIdentity | null> {\n const token = readCookie(req, cookieName);\n if (!token) return null;\n\n let decoded;\n try {\n decoded = await admin.auth().verifyIdToken(token);\n } catch {\n // Expired/invalid token → treat as unauthorized so the gate returns a\n // 401 { logout: true } and the client can force sign-out.\n return null;\n }\n\n const isAdmin =\n !!decoded.admin && allowed.includes(decoded.email ?? \"\");\n\n return { userId: decoded.uid, email: decoded.email, isAdmin };\n },\n };\n}\n"],"mappings":";AAAA,OAAO,WAAW;AAiBlB,SAAS,WAAW,KAAc,MAA6B;AAC7D,QAAM,SAAS,IAAI,QAAQ,IAAI,QAAQ;AACvC,MAAI,CAAC,OAAQ,QAAO;AACpB,aAAW,QAAQ,OAAO,MAAM,GAAG,GAAG;AACpC,UAAM,CAAC,GAAG,GAAG,CAAC,IAAI,KAAK,KAAK,EAAE,MAAM,GAAG;AACvC,QAAI,MAAM,KAAM,QAAO,mBAAmB,EAAE,KAAK,GAAG,CAAC;AAAA,EACvD;AACA,SAAO;AACT;AAOO,SAAS,aAAa,QAAyC;AAhCtE;AAiCE,QAAM,cAAa,YAAO,eAAP,YAAqB;AACxC,QAAM,UAAU,OAAO,YAAY,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AAEtD,MAAI,CAAC,MAAM,KAAK,UAAU,OAAO,aAAa;AAC5C,UAAM,IAAI,OAAO;AACjB,UAAM,cAAc;AAAA,MAClB,YAAY,MAAM,WAAW,KAAK;AAAA,QAChC,WAAW,EAAE;AAAA,QACb,aAAa,EAAE;AAAA,QACf,YAAY,EAAE;AAAA,MAChB,CAAC;AAAA,MACD,aAAa,EAAE;AAAA,IACjB,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,MAAM,cAAc,KAA4C;AAjDpE,UAAAA;AAkDM,YAAM,QAAQ,WAAW,KAAK,UAAU;AACxC,UAAI,CAAC,MAAO,QAAO;AAEnB,UAAI;AACJ,UAAI;AACF,kBAAU,MAAM,MAAM,KAAK,EAAE,cAAc,KAAK;AAAA,MAClD,SAAQ;AAGN,eAAO;AAAA,MACT;AAEA,YAAM,UACJ,CAAC,CAAC,QAAQ,SAAS,QAAQ,UAASA,MAAA,QAAQ,UAAR,OAAAA,MAAiB,EAAE;AAEzD,aAAO,EAAE,QAAQ,QAAQ,KAAK,OAAO,QAAQ,OAAO,QAAQ;AAAA,IAC9D;AAAA,EACF;AACF;","names":["_a"]}
@@ -0,0 +1,51 @@
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
+
20
+ // src/auth/nextauth/index.ts
21
+ var nextauth_exports = {};
22
+ __export(nextauth_exports, {
23
+ customAuth: () => customAuth,
24
+ nextAuthAuth: () => nextAuthAuth
25
+ });
26
+ module.exports = __toCommonJS(nextauth_exports);
27
+ function nextAuthAuth(config) {
28
+ const allowed = config.adminEmails.map((e) => e.trim());
29
+ return {
30
+ async verifyRequest(req) {
31
+ var _a, _b, _c, _d;
32
+ const session = await config.getSession(req);
33
+ const email = (_b = (_a = session == null ? void 0 : session.user) == null ? void 0 : _a.email) != null ? _b : void 0;
34
+ if (!email) return null;
35
+ return {
36
+ userId: (_d = (_c = session == null ? void 0 : session.user) == null ? void 0 : _c.id) != null ? _d : email,
37
+ email,
38
+ isAdmin: allowed.includes(email)
39
+ };
40
+ }
41
+ };
42
+ }
43
+ function customAuth(verify) {
44
+ return { verifyRequest: verify };
45
+ }
46
+ // Annotate the CommonJS export names for ESM import in node:
47
+ 0 && (module.exports = {
48
+ customAuth,
49
+ nextAuthAuth
50
+ });
51
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/auth/nextauth/index.ts"],"sourcesContent":["import type { AuthAdapter, AuthIdentity } from \"../../types\";\n\n/** Minimal shape this adapter reads from a NextAuth session. */\nexport interface SessionLike {\n user?: {\n id?: string;\n email?: string | null;\n name?: string | null;\n } | null;\n}\n\nexport interface NextAuthConfig {\n /**\n * Resolve the session for a request — typically your NextAuth `auth()` helper,\n * wrapped to ignore the `Request` argument, e.g. `getSession: () => auth()`.\n */\n getSession: (req: Request) => Promise<SessionLike | null>;\n /** Allowlist of admin emails. */\n adminEmails: string[];\n}\n\n/**\n * Auth adapter for NextAuth (Auth.js). Admin status requires the session email\n * to be present in `adminEmails`.\n */\nexport function nextAuthAuth(config: NextAuthConfig): AuthAdapter {\n const allowed = config.adminEmails.map((e) => e.trim());\n\n return {\n async verifyRequest(req: Request): Promise<AuthIdentity | null> {\n const session = await config.getSession(req);\n const email = session?.user?.email ?? undefined;\n if (!email) return null;\n return {\n userId: session?.user?.id ?? email,\n email,\n isAdmin: allowed.includes(email),\n };\n },\n };\n}\n\n/**\n * Escape hatch for fully custom auth: supply your own request verifier.\n */\nexport function customAuth(\n verify: (req: Request) => Promise<AuthIdentity | null>,\n): AuthAdapter {\n return { verifyRequest: verify };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAyBO,SAAS,aAAa,QAAqC;AAChE,QAAM,UAAU,OAAO,YAAY,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AAEtD,SAAO;AAAA,IACL,MAAM,cAAc,KAA4C;AA7BpE;AA8BM,YAAM,UAAU,MAAM,OAAO,WAAW,GAAG;AAC3C,YAAM,SAAQ,8CAAS,SAAT,mBAAe,UAAf,YAAwB;AACtC,UAAI,CAAC,MAAO,QAAO;AACnB,aAAO;AAAA,QACL,SAAQ,8CAAS,SAAT,mBAAe,OAAf,YAAqB;AAAA,QAC7B;AAAA,QACA,SAAS,QAAQ,SAAS,KAAK;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AACF;AAKO,SAAS,WACd,QACa;AACb,SAAO,EAAE,eAAe,OAAO;AACjC;","names":[]}
@@ -0,0 +1,30 @@
1
+ import { AuthIdentity, AuthAdapter } from '../../index.cjs';
2
+
3
+ /** Minimal shape this adapter reads from a NextAuth session. */
4
+ interface SessionLike {
5
+ user?: {
6
+ id?: string;
7
+ email?: string | null;
8
+ name?: string | null;
9
+ } | null;
10
+ }
11
+ interface NextAuthConfig {
12
+ /**
13
+ * Resolve the session for a request — typically your NextAuth `auth()` helper,
14
+ * wrapped to ignore the `Request` argument, e.g. `getSession: () => auth()`.
15
+ */
16
+ getSession: (req: Request) => Promise<SessionLike | null>;
17
+ /** Allowlist of admin emails. */
18
+ adminEmails: string[];
19
+ }
20
+ /**
21
+ * Auth adapter for NextAuth (Auth.js). Admin status requires the session email
22
+ * to be present in `adminEmails`.
23
+ */
24
+ declare function nextAuthAuth(config: NextAuthConfig): AuthAdapter;
25
+ /**
26
+ * Escape hatch for fully custom auth: supply your own request verifier.
27
+ */
28
+ declare function customAuth(verify: (req: Request) => Promise<AuthIdentity | null>): AuthAdapter;
29
+
30
+ export { type NextAuthConfig, type SessionLike, customAuth, nextAuthAuth };
@@ -0,0 +1,30 @@
1
+ import { AuthIdentity, AuthAdapter } from '../../index.js';
2
+
3
+ /** Minimal shape this adapter reads from a NextAuth session. */
4
+ interface SessionLike {
5
+ user?: {
6
+ id?: string;
7
+ email?: string | null;
8
+ name?: string | null;
9
+ } | null;
10
+ }
11
+ interface NextAuthConfig {
12
+ /**
13
+ * Resolve the session for a request — typically your NextAuth `auth()` helper,
14
+ * wrapped to ignore the `Request` argument, e.g. `getSession: () => auth()`.
15
+ */
16
+ getSession: (req: Request) => Promise<SessionLike | null>;
17
+ /** Allowlist of admin emails. */
18
+ adminEmails: string[];
19
+ }
20
+ /**
21
+ * Auth adapter for NextAuth (Auth.js). Admin status requires the session email
22
+ * to be present in `adminEmails`.
23
+ */
24
+ declare function nextAuthAuth(config: NextAuthConfig): AuthAdapter;
25
+ /**
26
+ * Escape hatch for fully custom auth: supply your own request verifier.
27
+ */
28
+ declare function customAuth(verify: (req: Request) => Promise<AuthIdentity | null>): AuthAdapter;
29
+
30
+ export { type NextAuthConfig, type SessionLike, customAuth, nextAuthAuth };
@@ -0,0 +1,25 @@
1
+ // src/auth/nextauth/index.ts
2
+ function nextAuthAuth(config) {
3
+ const allowed = config.adminEmails.map((e) => e.trim());
4
+ return {
5
+ async verifyRequest(req) {
6
+ var _a, _b, _c, _d;
7
+ const session = await config.getSession(req);
8
+ const email = (_b = (_a = session == null ? void 0 : session.user) == null ? void 0 : _a.email) != null ? _b : void 0;
9
+ if (!email) return null;
10
+ return {
11
+ userId: (_d = (_c = session == null ? void 0 : session.user) == null ? void 0 : _c.id) != null ? _d : email,
12
+ email,
13
+ isAdmin: allowed.includes(email)
14
+ };
15
+ }
16
+ };
17
+ }
18
+ function customAuth(verify) {
19
+ return { verifyRequest: verify };
20
+ }
21
+ export {
22
+ customAuth,
23
+ nextAuthAuth
24
+ };
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/auth/nextauth/index.ts"],"sourcesContent":["import type { AuthAdapter, AuthIdentity } from \"../../types\";\n\n/** Minimal shape this adapter reads from a NextAuth session. */\nexport interface SessionLike {\n user?: {\n id?: string;\n email?: string | null;\n name?: string | null;\n } | null;\n}\n\nexport interface NextAuthConfig {\n /**\n * Resolve the session for a request — typically your NextAuth `auth()` helper,\n * wrapped to ignore the `Request` argument, e.g. `getSession: () => auth()`.\n */\n getSession: (req: Request) => Promise<SessionLike | null>;\n /** Allowlist of admin emails. */\n adminEmails: string[];\n}\n\n/**\n * Auth adapter for NextAuth (Auth.js). Admin status requires the session email\n * to be present in `adminEmails`.\n */\nexport function nextAuthAuth(config: NextAuthConfig): AuthAdapter {\n const allowed = config.adminEmails.map((e) => e.trim());\n\n return {\n async verifyRequest(req: Request): Promise<AuthIdentity | null> {\n const session = await config.getSession(req);\n const email = session?.user?.email ?? undefined;\n if (!email) return null;\n return {\n userId: session?.user?.id ?? email,\n email,\n isAdmin: allowed.includes(email),\n };\n },\n };\n}\n\n/**\n * Escape hatch for fully custom auth: supply your own request verifier.\n */\nexport function customAuth(\n verify: (req: Request) => Promise<AuthIdentity | null>,\n): AuthAdapter {\n return { verifyRequest: verify };\n}\n"],"mappings":";AAyBO,SAAS,aAAa,QAAqC;AAChE,QAAM,UAAU,OAAO,YAAY,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AAEtD,SAAO;AAAA,IACL,MAAM,cAAc,KAA4C;AA7BpE;AA8BM,YAAM,UAAU,MAAM,OAAO,WAAW,GAAG;AAC3C,YAAM,SAAQ,8CAAS,SAAT,mBAAe,UAAf,YAAwB;AACtC,UAAI,CAAC,MAAO,QAAO;AACnB,aAAO;AAAA,QACL,SAAQ,8CAAS,SAAT,mBAAe,OAAf,YAAqB;AAAA,QAC7B;AAAA,QACA,SAAS,QAAQ,SAAS,KAAK;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AACF;AAKO,SAAS,WACd,QACa;AACb,SAAO,EAAE,eAAe,OAAO;AACjC;","names":[]}