@enterstellar-ai/adapter-firebase 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.
@@ -0,0 +1,235 @@
1
+ import { AuthAdapter, DataAdapter } from '@enterstellar-ai/types';
2
+ import { Auth } from 'firebase/auth';
3
+ import { Firestore } from 'firebase/firestore';
4
+
5
+ /**
6
+ * @module @enterstellar-ai/adapter-firebase/types
7
+ * @description Configuration types for Firebase adapter factories.
8
+ *
9
+ * These types define the input shapes consumers pass to
10
+ * `createFirebaseAuthAdapter()` and `createFirebaseDataAdapter()`.
11
+ * The factories map Firebase SDK calls to Enterstellar adapter interfaces.
12
+ *
13
+ * @see Bible §4.15
14
+ * @see Design Choice AD1 — minimal but complete: getSession, hasRole, onAuthChange
15
+ */
16
+
17
+ /**
18
+ * Configuration for {@link createFirebaseAuthAdapter}.
19
+ *
20
+ * Takes a Firebase `Auth` instance and optional overrides. The factory maps
21
+ * Firebase auth calls to the Enterstellar `AuthAdapter` interface.
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * import { getAuth } from 'firebase/auth';
26
+ * import { createFirebaseAuthAdapter } from '@enterstellar-ai/adapter-firebase';
27
+ *
28
+ * const auth = getAuth(app);
29
+ * const adapter = createFirebaseAuthAdapter({ auth });
30
+ * ```
31
+ */
32
+ type FirebaseAuthConfig = {
33
+ /**
34
+ * The Firebase Auth instance.
35
+ * Must be initialized with `getAuth()` from `firebase/auth`.
36
+ */
37
+ readonly auth: Auth;
38
+ /**
39
+ * Human-readable adapter name for error messages and DevTools display.
40
+ * @default `'firebase-auth'`
41
+ */
42
+ readonly name?: string;
43
+ /**
44
+ * Custom role extraction function.
45
+ *
46
+ * Called with the raw Firebase `User` object after a successful auth check.
47
+ * Returns an array of role strings for RBAC zone gating.
48
+ *
49
+ * @default Extracts from `getIdTokenResult().claims.roles` (falls back to `[]`).
50
+ * @param user - The raw Firebase user object.
51
+ * @returns Array of role strings (e.g., `['clinician', 'admin']`).
52
+ *
53
+ * @example
54
+ * ```ts
55
+ * // Extract roles from custom claims
56
+ * roleExtractor: (user) => (user as any).customClaims?.roles ?? []
57
+ * ```
58
+ */
59
+ readonly roleExtractor?: (user: unknown) => string[];
60
+ };
61
+ /**
62
+ * Configuration for {@link createFirebaseDataAdapter}.
63
+ *
64
+ * Takes a Firestore instance and optional overrides. The factory maps
65
+ * Firestore query/mutate/subscribe calls to the Enterstellar `DataAdapter` interface.
66
+ *
67
+ * @example
68
+ * ```ts
69
+ * import { getFirestore } from 'firebase/firestore';
70
+ * import { createFirebaseDataAdapter } from '@enterstellar-ai/adapter-firebase';
71
+ *
72
+ * const firestore = getFirestore(app);
73
+ * const data = createFirebaseDataAdapter({ firestore });
74
+ * ```
75
+ */
76
+ type FirebaseDataConfig = {
77
+ /**
78
+ * The Firestore instance.
79
+ * Must be initialized with `getFirestore()` from `firebase/firestore`.
80
+ */
81
+ readonly firestore: Firestore;
82
+ /**
83
+ * Human-readable adapter name for error messages and DevTools display.
84
+ * @default `'firebase-data'`
85
+ */
86
+ readonly name?: string;
87
+ };
88
+
89
+ /**
90
+ * @module @enterstellar-ai/adapter-firebase/create-firebase-auth-adapter
91
+ * @description Factory function for creating a Firebase-backed `AuthAdapter`.
92
+ *
93
+ * This factory maps Firebase Auth SDK calls to the Enterstellar `AuthAdapter` interface:
94
+ * - `getSession()` → `auth.currentUser` + `getIdTokenResult()` → `{ userId, roles } | null`
95
+ * - `hasRole(role)` → `getSession()` → checks `roles.includes(role)`
96
+ * - `onAuthChange(cb)` → `onAuthStateChanged(auth, cb)` → returns `unsubscribe`
97
+ *
98
+ * It builds an `AuthAdapterConfig` and delegates to `createAuthAdapter()` from
99
+ * `@enterstellar-ai/adapters`, which handles all validation (ENS-7001) and AD5 error
100
+ * wrapping (ENS-7005 / ENS-7002). This factory is purely an SDK-to-Enterstellar translator.
101
+ *
102
+ * ## Role Extraction Strategy
103
+ *
104
+ * Firebase stores RBAC roles in custom claims via `getIdTokenResult().claims`.
105
+ * The default behavior extracts roles from `claims['roles']` (an async operation).
106
+ * If a custom `roleExtractor` is provided, it is called synchronously with the
107
+ * raw Firebase `User` object — this enables `onAuthChange()` to include roles
108
+ * in the callback (since `onAuthChange` is synchronous).
109
+ *
110
+ * When no custom `roleExtractor` is provided and `onAuthChange()` fires,
111
+ * roles default to `[]` in the callback. Full role resolution happens
112
+ * through `getSession()` or `hasRole()` (which can await `getIdTokenResult()`).
113
+ *
114
+ * @see Bible §4.15
115
+ * @see Design Choice AD1 — minimal but complete: getSession, hasRole, onAuthChange
116
+ * @see Design Choice AD5 — error wrapping delegated to createAuthAdapter()
117
+ */
118
+
119
+ /**
120
+ * Creates a Firebase-backed `AuthAdapter`.
121
+ *
122
+ * Maps Firebase Auth SDK methods to the Enterstellar `AuthAdapter` interface,
123
+ * then delegates to `createAuthAdapter()` from `@enterstellar-ai/adapters` for
124
+ * config validation and AD5 error wrapping.
125
+ *
126
+ * @param config - Firebase auth configuration with `Auth` instance and optional overrides.
127
+ * @returns A frozen, validated `AuthAdapter` instance.
128
+ * @throws `EnterstellarError` with code `ENS-7001` if config validation fails.
129
+ *
130
+ * @example
131
+ * ```ts
132
+ * import { initializeApp } from 'firebase/app';
133
+ * import { getAuth } from 'firebase/auth';
134
+ * import { createFirebaseAuthAdapter } from '@enterstellar-ai/adapter-firebase';
135
+ *
136
+ * const app = initializeApp({ projectId: 'my-project', ... });
137
+ * const firebaseAuth = getAuth(app);
138
+ *
139
+ * const auth = createFirebaseAuthAdapter({ auth: firebaseAuth });
140
+ *
141
+ * // With custom role extraction (synchronous — enables roles in onAuthChange)
142
+ * const authWithRoles = createFirebaseAuthAdapter({
143
+ * auth: firebaseAuth,
144
+ * roleExtractor: (user) => {
145
+ * const u = user as { customClaims?: { roles?: string[] } };
146
+ * return u.customClaims?.roles ?? [];
147
+ * },
148
+ * });
149
+ *
150
+ * // Usage
151
+ * const session = await auth.getSession(); // { userId, roles } | null
152
+ * const isAdmin = await auth.hasRole('admin'); // boolean
153
+ * const unsub = auth.onAuthChange((session) => {
154
+ * console.log('Auth state changed:', session);
155
+ * });
156
+ * ```
157
+ */
158
+ declare function createFirebaseAuthAdapter(config: FirebaseAuthConfig): AuthAdapter;
159
+
160
+ /**
161
+ * @module @enterstellar-ai/adapter-firebase/create-firebase-data-adapter
162
+ * @description Factory function for creating a Firestore-backed `DataAdapter`.
163
+ *
164
+ * This factory maps Firestore SDK calls to the Enterstellar `DataAdapter` interface:
165
+ * - `query(resource, params?)` → `getDocs(collection(...))` + `where()` constraints
166
+ * - `mutate(resource, action, data)` → `addDoc` / `updateDoc` / `deleteDoc`
167
+ * - `subscribe(resource, cb)` → `onSnapshot(collection(...), cb)` → returns `unsubscribe`
168
+ *
169
+ * It builds a `DataAdapterConfig` and delegates to `createDataAdapter()` from
170
+ * `@enterstellar-ai/adapters`, which handles all validation (ENS-7001) and AD5 error
171
+ * wrapping (ENS-7003 / ENS-7004 / ENS-7002). This factory is purely an
172
+ * SDK-to-Enterstellar translator.
173
+ *
174
+ * @see Bible §4.15
175
+ * @see Design Choice AD3 — convention-based dot-notation for resource names
176
+ * @see Design Choice AD5 — error wrapping delegated to createDataAdapter()
177
+ */
178
+
179
+ /**
180
+ * Creates a Firestore-backed `DataAdapter`.
181
+ *
182
+ * Maps Firestore SDK methods to the Enterstellar `DataAdapter` interface,
183
+ * then delegates to `createDataAdapter()` from `@enterstellar-ai/adapters`
184
+ * for config validation and AD5 error wrapping.
185
+ *
186
+ * @param config - Firestore data configuration with Firestore instance and optional overrides.
187
+ * @returns A frozen, validated `DataAdapter` instance.
188
+ * @throws `EnterstellarError` with code `ENS-7001` if config validation fails.
189
+ *
190
+ * @example
191
+ * ```ts
192
+ * import { initializeApp } from 'firebase/app';
193
+ * import { getFirestore } from 'firebase/firestore';
194
+ * import { createFirebaseDataAdapter } from '@enterstellar-ai/adapter-firebase';
195
+ *
196
+ * const app = initializeApp({ projectId: 'my-project', ... });
197
+ * const firestore = getFirestore(app);
198
+ * const data = createFirebaseDataAdapter({ firestore });
199
+ *
200
+ * // Query with filters
201
+ * const patients = await data.query('patients', { status: 'active' });
202
+ *
203
+ * // Mutate — create a document
204
+ * const newPatient = await data.mutate('patients', 'create', {
205
+ * name: 'Jane Doe',
206
+ * status: 'active',
207
+ * });
208
+ *
209
+ * // Subscribe to realtime changes
210
+ * const unsub = data.subscribe('patients', (records) => {
211
+ * console.log('Patients updated:', records);
212
+ * });
213
+ * ```
214
+ */
215
+ declare function createFirebaseDataAdapter(config: FirebaseDataConfig): DataAdapter;
216
+
217
+ /**
218
+ * @module @enterstellar-ai/adapter-firebase/version
219
+ * @description Package version constant for `@enterstellar-ai/adapter-firebase`.
220
+ *
221
+ * Used by DevTools for version display and runtime compatibility checks.
222
+ * Must be kept in sync with the `version` field in `package.json`.
223
+ *
224
+ * @see Design Choice T14 — version exports
225
+ */
226
+ /**
227
+ * Current version of the `@enterstellar-ai/adapter-firebase` package.
228
+ *
229
+ * @remarks
230
+ * This value MUST match the `version` field in `package.json`.
231
+ * Update this constant whenever a new version is released via Changesets.
232
+ */
233
+ declare const FIREBASE_ADAPTER_VERSION: "0.0.0";
234
+
235
+ export { FIREBASE_ADAPTER_VERSION, type FirebaseAuthConfig, type FirebaseDataConfig, createFirebaseAuthAdapter, createFirebaseDataAdapter };
@@ -0,0 +1,235 @@
1
+ import { AuthAdapter, DataAdapter } from '@enterstellar-ai/types';
2
+ import { Auth } from 'firebase/auth';
3
+ import { Firestore } from 'firebase/firestore';
4
+
5
+ /**
6
+ * @module @enterstellar-ai/adapter-firebase/types
7
+ * @description Configuration types for Firebase adapter factories.
8
+ *
9
+ * These types define the input shapes consumers pass to
10
+ * `createFirebaseAuthAdapter()` and `createFirebaseDataAdapter()`.
11
+ * The factories map Firebase SDK calls to Enterstellar adapter interfaces.
12
+ *
13
+ * @see Bible §4.15
14
+ * @see Design Choice AD1 — minimal but complete: getSession, hasRole, onAuthChange
15
+ */
16
+
17
+ /**
18
+ * Configuration for {@link createFirebaseAuthAdapter}.
19
+ *
20
+ * Takes a Firebase `Auth` instance and optional overrides. The factory maps
21
+ * Firebase auth calls to the Enterstellar `AuthAdapter` interface.
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * import { getAuth } from 'firebase/auth';
26
+ * import { createFirebaseAuthAdapter } from '@enterstellar-ai/adapter-firebase';
27
+ *
28
+ * const auth = getAuth(app);
29
+ * const adapter = createFirebaseAuthAdapter({ auth });
30
+ * ```
31
+ */
32
+ type FirebaseAuthConfig = {
33
+ /**
34
+ * The Firebase Auth instance.
35
+ * Must be initialized with `getAuth()` from `firebase/auth`.
36
+ */
37
+ readonly auth: Auth;
38
+ /**
39
+ * Human-readable adapter name for error messages and DevTools display.
40
+ * @default `'firebase-auth'`
41
+ */
42
+ readonly name?: string;
43
+ /**
44
+ * Custom role extraction function.
45
+ *
46
+ * Called with the raw Firebase `User` object after a successful auth check.
47
+ * Returns an array of role strings for RBAC zone gating.
48
+ *
49
+ * @default Extracts from `getIdTokenResult().claims.roles` (falls back to `[]`).
50
+ * @param user - The raw Firebase user object.
51
+ * @returns Array of role strings (e.g., `['clinician', 'admin']`).
52
+ *
53
+ * @example
54
+ * ```ts
55
+ * // Extract roles from custom claims
56
+ * roleExtractor: (user) => (user as any).customClaims?.roles ?? []
57
+ * ```
58
+ */
59
+ readonly roleExtractor?: (user: unknown) => string[];
60
+ };
61
+ /**
62
+ * Configuration for {@link createFirebaseDataAdapter}.
63
+ *
64
+ * Takes a Firestore instance and optional overrides. The factory maps
65
+ * Firestore query/mutate/subscribe calls to the Enterstellar `DataAdapter` interface.
66
+ *
67
+ * @example
68
+ * ```ts
69
+ * import { getFirestore } from 'firebase/firestore';
70
+ * import { createFirebaseDataAdapter } from '@enterstellar-ai/adapter-firebase';
71
+ *
72
+ * const firestore = getFirestore(app);
73
+ * const data = createFirebaseDataAdapter({ firestore });
74
+ * ```
75
+ */
76
+ type FirebaseDataConfig = {
77
+ /**
78
+ * The Firestore instance.
79
+ * Must be initialized with `getFirestore()` from `firebase/firestore`.
80
+ */
81
+ readonly firestore: Firestore;
82
+ /**
83
+ * Human-readable adapter name for error messages and DevTools display.
84
+ * @default `'firebase-data'`
85
+ */
86
+ readonly name?: string;
87
+ };
88
+
89
+ /**
90
+ * @module @enterstellar-ai/adapter-firebase/create-firebase-auth-adapter
91
+ * @description Factory function for creating a Firebase-backed `AuthAdapter`.
92
+ *
93
+ * This factory maps Firebase Auth SDK calls to the Enterstellar `AuthAdapter` interface:
94
+ * - `getSession()` → `auth.currentUser` + `getIdTokenResult()` → `{ userId, roles } | null`
95
+ * - `hasRole(role)` → `getSession()` → checks `roles.includes(role)`
96
+ * - `onAuthChange(cb)` → `onAuthStateChanged(auth, cb)` → returns `unsubscribe`
97
+ *
98
+ * It builds an `AuthAdapterConfig` and delegates to `createAuthAdapter()` from
99
+ * `@enterstellar-ai/adapters`, which handles all validation (ENS-7001) and AD5 error
100
+ * wrapping (ENS-7005 / ENS-7002). This factory is purely an SDK-to-Enterstellar translator.
101
+ *
102
+ * ## Role Extraction Strategy
103
+ *
104
+ * Firebase stores RBAC roles in custom claims via `getIdTokenResult().claims`.
105
+ * The default behavior extracts roles from `claims['roles']` (an async operation).
106
+ * If a custom `roleExtractor` is provided, it is called synchronously with the
107
+ * raw Firebase `User` object — this enables `onAuthChange()` to include roles
108
+ * in the callback (since `onAuthChange` is synchronous).
109
+ *
110
+ * When no custom `roleExtractor` is provided and `onAuthChange()` fires,
111
+ * roles default to `[]` in the callback. Full role resolution happens
112
+ * through `getSession()` or `hasRole()` (which can await `getIdTokenResult()`).
113
+ *
114
+ * @see Bible §4.15
115
+ * @see Design Choice AD1 — minimal but complete: getSession, hasRole, onAuthChange
116
+ * @see Design Choice AD5 — error wrapping delegated to createAuthAdapter()
117
+ */
118
+
119
+ /**
120
+ * Creates a Firebase-backed `AuthAdapter`.
121
+ *
122
+ * Maps Firebase Auth SDK methods to the Enterstellar `AuthAdapter` interface,
123
+ * then delegates to `createAuthAdapter()` from `@enterstellar-ai/adapters` for
124
+ * config validation and AD5 error wrapping.
125
+ *
126
+ * @param config - Firebase auth configuration with `Auth` instance and optional overrides.
127
+ * @returns A frozen, validated `AuthAdapter` instance.
128
+ * @throws `EnterstellarError` with code `ENS-7001` if config validation fails.
129
+ *
130
+ * @example
131
+ * ```ts
132
+ * import { initializeApp } from 'firebase/app';
133
+ * import { getAuth } from 'firebase/auth';
134
+ * import { createFirebaseAuthAdapter } from '@enterstellar-ai/adapter-firebase';
135
+ *
136
+ * const app = initializeApp({ projectId: 'my-project', ... });
137
+ * const firebaseAuth = getAuth(app);
138
+ *
139
+ * const auth = createFirebaseAuthAdapter({ auth: firebaseAuth });
140
+ *
141
+ * // With custom role extraction (synchronous — enables roles in onAuthChange)
142
+ * const authWithRoles = createFirebaseAuthAdapter({
143
+ * auth: firebaseAuth,
144
+ * roleExtractor: (user) => {
145
+ * const u = user as { customClaims?: { roles?: string[] } };
146
+ * return u.customClaims?.roles ?? [];
147
+ * },
148
+ * });
149
+ *
150
+ * // Usage
151
+ * const session = await auth.getSession(); // { userId, roles } | null
152
+ * const isAdmin = await auth.hasRole('admin'); // boolean
153
+ * const unsub = auth.onAuthChange((session) => {
154
+ * console.log('Auth state changed:', session);
155
+ * });
156
+ * ```
157
+ */
158
+ declare function createFirebaseAuthAdapter(config: FirebaseAuthConfig): AuthAdapter;
159
+
160
+ /**
161
+ * @module @enterstellar-ai/adapter-firebase/create-firebase-data-adapter
162
+ * @description Factory function for creating a Firestore-backed `DataAdapter`.
163
+ *
164
+ * This factory maps Firestore SDK calls to the Enterstellar `DataAdapter` interface:
165
+ * - `query(resource, params?)` → `getDocs(collection(...))` + `where()` constraints
166
+ * - `mutate(resource, action, data)` → `addDoc` / `updateDoc` / `deleteDoc`
167
+ * - `subscribe(resource, cb)` → `onSnapshot(collection(...), cb)` → returns `unsubscribe`
168
+ *
169
+ * It builds a `DataAdapterConfig` and delegates to `createDataAdapter()` from
170
+ * `@enterstellar-ai/adapters`, which handles all validation (ENS-7001) and AD5 error
171
+ * wrapping (ENS-7003 / ENS-7004 / ENS-7002). This factory is purely an
172
+ * SDK-to-Enterstellar translator.
173
+ *
174
+ * @see Bible §4.15
175
+ * @see Design Choice AD3 — convention-based dot-notation for resource names
176
+ * @see Design Choice AD5 — error wrapping delegated to createDataAdapter()
177
+ */
178
+
179
+ /**
180
+ * Creates a Firestore-backed `DataAdapter`.
181
+ *
182
+ * Maps Firestore SDK methods to the Enterstellar `DataAdapter` interface,
183
+ * then delegates to `createDataAdapter()` from `@enterstellar-ai/adapters`
184
+ * for config validation and AD5 error wrapping.
185
+ *
186
+ * @param config - Firestore data configuration with Firestore instance and optional overrides.
187
+ * @returns A frozen, validated `DataAdapter` instance.
188
+ * @throws `EnterstellarError` with code `ENS-7001` if config validation fails.
189
+ *
190
+ * @example
191
+ * ```ts
192
+ * import { initializeApp } from 'firebase/app';
193
+ * import { getFirestore } from 'firebase/firestore';
194
+ * import { createFirebaseDataAdapter } from '@enterstellar-ai/adapter-firebase';
195
+ *
196
+ * const app = initializeApp({ projectId: 'my-project', ... });
197
+ * const firestore = getFirestore(app);
198
+ * const data = createFirebaseDataAdapter({ firestore });
199
+ *
200
+ * // Query with filters
201
+ * const patients = await data.query('patients', { status: 'active' });
202
+ *
203
+ * // Mutate — create a document
204
+ * const newPatient = await data.mutate('patients', 'create', {
205
+ * name: 'Jane Doe',
206
+ * status: 'active',
207
+ * });
208
+ *
209
+ * // Subscribe to realtime changes
210
+ * const unsub = data.subscribe('patients', (records) => {
211
+ * console.log('Patients updated:', records);
212
+ * });
213
+ * ```
214
+ */
215
+ declare function createFirebaseDataAdapter(config: FirebaseDataConfig): DataAdapter;
216
+
217
+ /**
218
+ * @module @enterstellar-ai/adapter-firebase/version
219
+ * @description Package version constant for `@enterstellar-ai/adapter-firebase`.
220
+ *
221
+ * Used by DevTools for version display and runtime compatibility checks.
222
+ * Must be kept in sync with the `version` field in `package.json`.
223
+ *
224
+ * @see Design Choice T14 — version exports
225
+ */
226
+ /**
227
+ * Current version of the `@enterstellar-ai/adapter-firebase` package.
228
+ *
229
+ * @remarks
230
+ * This value MUST match the `version` field in `package.json`.
231
+ * Update this constant whenever a new version is released via Changesets.
232
+ */
233
+ declare const FIREBASE_ADAPTER_VERSION: "0.0.0";
234
+
235
+ export { FIREBASE_ADAPTER_VERSION, type FirebaseAuthConfig, type FirebaseDataConfig, createFirebaseAuthAdapter, createFirebaseDataAdapter };