@enterstellar-ai/adapters 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,769 @@
1
+ import { AuthAdapter, DataAdapter, ErrorAdapter, AnalyticsAdapter, EnterstellarError } from '@enterstellar-ai/types';
2
+ export { AnalyticsAdapter, AuthAdapter, DataAdapter, ErrorAdapter } from '@enterstellar-ai/types';
3
+
4
+ /**
5
+ * @module @enterstellar-ai/adapters/types
6
+ * @description Module-local configuration types for adapter factories.
7
+ *
8
+ * These types define the "input" shape that consumers pass to
9
+ * `createAuthAdapter()`, `createDataAdapter()`, etc. The actual adapter
10
+ * interfaces (`AuthAdapter`, `DataAdapter`, `ErrorAdapter`, `AnalyticsAdapter`)
11
+ * live in `@enterstellar-ai/types/adapters` and are re-exported from the barrel.
12
+ *
13
+ * Each config type mirrors its corresponding adapter interface, plus a
14
+ * mandatory `name` field for identification in error messages and DevTools.
15
+ *
16
+ * @see Bible §4.15
17
+ * @see Design Choices AD1–AD5
18
+ * @see Design Choice T1 — interfaces for behavior, types for data shapes
19
+ */
20
+ /**
21
+ * Configuration for {@link createAuthAdapter}.
22
+ *
23
+ * The consumer provides their implementation of each method. The factory
24
+ * validates the config and wraps each method to catch errors → `EnterstellarError`
25
+ * per Design Choice AD5.
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * const auth = createAuthAdapter({
30
+ * name: 'supabase-auth',
31
+ * getSession: async () => {
32
+ * const { data } = await supabase.auth.getSession();
33
+ * if (!data.session) return null;
34
+ * return { userId: data.session.user.id, roles: ['clinician'] };
35
+ * },
36
+ * hasRole: async (role) => {
37
+ * const session = await supabase.auth.getSession();
38
+ * return session.data.session?.user.role === role;
39
+ * },
40
+ * onAuthChange: (cb) => {
41
+ * const { data } = supabase.auth.onAuthStateChange((_event, session) => {
42
+ * cb(session ? { userId: session.user.id, roles: ['clinician'] } : null);
43
+ * });
44
+ * return () => data.subscription.unsubscribe();
45
+ * },
46
+ * });
47
+ * ```
48
+ */
49
+ type AuthAdapterConfig = {
50
+ /**
51
+ * Human-readable adapter name for error messages and DevTools display.
52
+ *
53
+ * @example `'supabase-auth'`, `'clerk-auth'`, `'firebase-auth'`
54
+ */
55
+ readonly name: string;
56
+ /**
57
+ * Returns the current authentication session, or `null` if unauthenticated.
58
+ *
59
+ * @returns Session object with user ID and role list.
60
+ */
61
+ readonly getSession: () => Promise<{
62
+ userId: string;
63
+ roles: string[];
64
+ } | null>;
65
+ /**
66
+ * Checks whether the current user has a specific role.
67
+ * Essential for RBAC — clinical vs. admin zone visibility.
68
+ *
69
+ * @param role - The role to check (e.g., `'clinician'`, `'admin'`).
70
+ * @returns `true` if the user has the specified role.
71
+ */
72
+ readonly hasRole: (role: string) => Promise<boolean>;
73
+ /**
74
+ * Subscribes to authentication state changes.
75
+ *
76
+ * Essential for reactive auth gating — zones re-evaluate visibility
77
+ * when sessions expire or roles change.
78
+ *
79
+ * @param callback - Called when auth state changes. Receives the new
80
+ * session object, or `null` if the user became unauthenticated.
81
+ * @returns An unsubscribe function (synchronous).
82
+ */
83
+ readonly onAuthChange: (callback: (session: {
84
+ userId: string;
85
+ roles: string[];
86
+ } | null) => void) => () => void;
87
+ };
88
+ /**
89
+ * Configuration for {@link createDataAdapter}.
90
+ *
91
+ * Resolves abstract data source names (e.g., `'patients.vitals'`) to actual
92
+ * data using convention-based dot-notation resolution (AD3).
93
+ *
94
+ * @example
95
+ * ```ts
96
+ * const data = createDataAdapter({
97
+ * name: 'supabase-data',
98
+ * query: async (resource, params) => {
99
+ * const { data } = await supabase.from(resource).select('*').match(params ?? {});
100
+ * return data ?? [];
101
+ * },
102
+ * mutate: async (resource, action, payload) => {
103
+ * if (action === 'create') {
104
+ * const { data } = await supabase.from(resource).insert(payload).select().single();
105
+ * return data;
106
+ * }
107
+ * return null;
108
+ * },
109
+ * subscribe: (resource, callback) => {
110
+ * const channel = supabase.channel(resource)
111
+ * .on('postgres_changes', { event: '*', schema: 'public', table: resource },
112
+ * () => { void query(resource).then(callback); })
113
+ * .subscribe();
114
+ * return () => { void supabase.removeChannel(channel); };
115
+ * },
116
+ * });
117
+ * ```
118
+ */
119
+ type DataAdapterConfig = {
120
+ /**
121
+ * Human-readable adapter name for error messages and DevTools display.
122
+ *
123
+ * @example `'supabase-data'`, `'firebase-data'`, `'prisma-data'`
124
+ */
125
+ readonly name: string;
126
+ /**
127
+ * Queries a resource by name with optional parameters.
128
+ *
129
+ * @param resource - The resource/table/collection to query (dot-notation per AD3).
130
+ * @param params - Optional query parameters (filters, pagination, sorting).
131
+ * @returns Array of records matching the query.
132
+ */
133
+ readonly query: (resource: string, params?: Readonly<Record<string, unknown>>) => Promise<readonly Record<string, unknown>[]>;
134
+ /**
135
+ * Performs a mutation (create, update, delete) on a resource.
136
+ *
137
+ * @param resource - The resource to mutate.
138
+ * @param action - The mutation type: `'create'`, `'update'`, or `'delete'`.
139
+ * @param data - The mutation payload.
140
+ * @returns The mutated record, or `null` for deletes.
141
+ */
142
+ readonly mutate: (resource: string, action: 'create' | 'update' | 'delete', data: Readonly<Record<string, unknown>>) => Promise<Record<string, unknown> | null>;
143
+ /**
144
+ * Subscribes to real-time changes on a resource.
145
+ * Essential for live data updates in Enterstellar zones (AD4 — realtime at v1).
146
+ *
147
+ * @param resource - The resource to subscribe to.
148
+ * @param callback - Called when the resource changes.
149
+ * @returns An unsubscribe function (synchronous).
150
+ */
151
+ readonly subscribe: (resource: string, callback: (data: readonly Record<string, unknown>[]) => void) => () => void;
152
+ };
153
+ /**
154
+ * Configuration for {@link createErrorAdapter}.
155
+ *
156
+ * Implementations provide retry logic, error reporting, and PII sanitization.
157
+ * All methods are async per AD2 — `shouldRetry` and `sanitize` support
158
+ * production use cases such as remote circuit breaker checks and external
159
+ * PII detection services. Raw vendor errors are wrapped into `EnterstellarError`
160
+ * per AD5.
161
+ *
162
+ * @example
163
+ * ```ts
164
+ * const errors = createErrorAdapter({
165
+ * name: 'sentry-error',
166
+ * report: async (error, context) => {
167
+ * Sentry.captureException(error, { extra: context });
168
+ * },
169
+ * shouldRetry: async (error, attempt) => attempt < 3 && isTransient(error),
170
+ * sanitize: async (error) => {
171
+ * const sanitized = new Error(error.message.replace(/\d{3}-\d{2}-\d{4}/g, '[REDACTED]'));
172
+ * sanitized.stack = error.stack;
173
+ * return sanitized;
174
+ * },
175
+ * });
176
+ * ```
177
+ */
178
+ type ErrorAdapterConfig = {
179
+ /**
180
+ * Human-readable adapter name for error messages and DevTools display.
181
+ *
182
+ * @example `'sentry-error'`, `'datadog-error'`, `'console-error'`
183
+ */
184
+ readonly name: string;
185
+ /**
186
+ * Reports an error to the external error tracking service.
187
+ *
188
+ * @param error - The error to report (may be an `EnterstellarError`).
189
+ * @param context - Optional contextual metadata for the error report.
190
+ */
191
+ readonly report: (error: Error, context?: Readonly<Record<string, unknown>>) => Promise<void>;
192
+ /**
193
+ * Determines whether a failed operation should be retried.
194
+ *
195
+ * Async to support production implementations that consult remote
196
+ * circuit breakers or rate-limit services before deciding.
197
+ *
198
+ * @param error - The error that caused the failure.
199
+ * @param attemptNumber - The current retry attempt (1-based).
200
+ * @returns `true` if the operation should be retried.
201
+ */
202
+ readonly shouldRetry: (error: Error, attemptNumber: number) => Promise<boolean>;
203
+ /**
204
+ * Sanitizes an error before it is logged or displayed.
205
+ * Must strip any PII or sensitive data from the error message and stack.
206
+ *
207
+ * Async to support production implementations that call external
208
+ * PII detection services for HIPAA-compliant sanitization.
209
+ *
210
+ * @param error - The error to sanitize.
211
+ * @returns A sanitized copy of the error.
212
+ */
213
+ readonly sanitize: (error: Error) => Promise<Error>;
214
+ };
215
+ /**
216
+ * Configuration for {@link createAnalyticsAdapter}.
217
+ *
218
+ * Implementations forward user interaction events and identity to analytics
219
+ * services. Both methods are fire-and-forget (void return).
220
+ *
221
+ * @example
222
+ * ```ts
223
+ * const analytics = createAnalyticsAdapter({
224
+ * name: 'mixpanel-analytics',
225
+ * track: (event, properties) => {
226
+ * mixpanel.track(event, properties);
227
+ * },
228
+ * identify: (userId, traits) => {
229
+ * mixpanel.identify(userId);
230
+ * if (traits) mixpanel.people.set(traits);
231
+ * },
232
+ * });
233
+ * ```
234
+ */
235
+ type AnalyticsAdapterConfig = {
236
+ /**
237
+ * Human-readable adapter name for error messages and DevTools display.
238
+ *
239
+ * @example `'mixpanel-analytics'`, `'amplitude-analytics'`, `'posthog-analytics'`
240
+ */
241
+ readonly name: string;
242
+ /**
243
+ * Tracks a named event with optional properties.
244
+ * Fire-and-forget — no return value.
245
+ *
246
+ * @param event - The event name (e.g., `'zone_rendered'`, `'intent_resolved'`).
247
+ * @param properties - Optional event properties for segmentation.
248
+ */
249
+ readonly track: (event: string, properties?: Readonly<Record<string, unknown>>) => void;
250
+ /**
251
+ * Identifies the current user for analytics attribution.
252
+ * Fire-and-forget — no return value.
253
+ *
254
+ * @param userId - Unique user identifier.
255
+ * @param traits - Optional user traits (role, plan, etc.).
256
+ */
257
+ readonly identify: (userId: string, traits?: Readonly<Record<string, unknown>>) => void;
258
+ };
259
+ /**
260
+ * Discriminated adapter type name.
261
+ * Used by {@link validateAdapterConfig} to determine which fields to validate.
262
+ */
263
+ type AdapterType = 'auth' | 'data' | 'error' | 'analytics';
264
+
265
+ /**
266
+ * @module @enterstellar-ai/adapters/create-auth-adapter
267
+ * @description Factory functions for creating validated `AuthAdapter` instances.
268
+ *
269
+ * - `createAuthAdapter(config)` — wraps a consumer-provided implementation,
270
+ * validates config via {@link validateAdapterConfig}, and wraps every method
271
+ * in error handling per Design Choice AD5 (raw vendor errors never leak).
272
+ *
273
+ * - `createNoopAuthAdapter()` — returns a no-op adapter for testing and
274
+ * development when no real auth provider is connected.
275
+ *
276
+ * Both factories return a plain object with closures (R1 pattern — no classes).
277
+ *
278
+ * @see Bible §4.15
279
+ * @see Design Choice AD1 — minimal but complete: getSession, hasRole, onAuthChange
280
+ * @see Design Choice AD2 — always async (I/O methods)
281
+ * @see Design Choice AD5 — wrap into EnterstellarError
282
+ */
283
+
284
+ /**
285
+ * Creates a validated `AuthAdapter` from consumer-provided config.
286
+ *
287
+ * The factory:
288
+ * 1. Validates the config (name + required methods) — throws `ENS-7001` on failure.
289
+ * 2. Wraps `getSession()` and `hasRole()` in error handling → `ENS-7005` on throw.
290
+ * 3. Wraps `onAuthChange()` in error handling → `ENS-7002` on throw.
291
+ *
292
+ * Consumers never see raw vendor errors — all failures are `EnterstellarError` (AD5).
293
+ *
294
+ * @param config - The adapter implementation with a `name` and all required methods.
295
+ * @returns A frozen `AuthAdapter` instance.
296
+ * @throws `EnterstellarError` with code `ENS-7001` if config validation fails.
297
+ *
298
+ * @example
299
+ * ```ts
300
+ * import { createAuthAdapter } from '@enterstellar-ai/adapters';
301
+ *
302
+ * const auth = createAuthAdapter({
303
+ * name: 'supabase-auth',
304
+ * getSession: async () => {
305
+ * const { data } = await supabase.auth.getSession();
306
+ * if (!data.session) return null;
307
+ * return { userId: data.session.user.id, roles: ['clinician'] };
308
+ * },
309
+ * hasRole: async (role) => {
310
+ * const session = await supabase.auth.getSession();
311
+ * return session.data.session?.user.role === role;
312
+ * },
313
+ * onAuthChange: (cb) => {
314
+ * const { data } = supabase.auth.onAuthStateChange((_event, session) => {
315
+ * cb(session ? { userId: session.user.id, roles: ['clinician'] } : null);
316
+ * });
317
+ * return () => data.subscription.unsubscribe();
318
+ * },
319
+ * });
320
+ * ```
321
+ */
322
+ declare function createAuthAdapter(config: AuthAdapterConfig): AuthAdapter;
323
+ /**
324
+ * Creates a no-op `AuthAdapter` for testing and development.
325
+ *
326
+ * All methods resolve to safe defaults:
327
+ * - `getSession()` → `null` (unauthenticated)
328
+ * - `hasRole()` → `false` (no permissions)
329
+ * - `onAuthChange()` → no-op unsubscribe function (never fires)
330
+ *
331
+ * @returns A frozen, no-op `AuthAdapter` instance.
332
+ *
333
+ * @example
334
+ * ```ts
335
+ * import { createNoopAuthAdapter } from '@enterstellar-ai/adapters';
336
+ *
337
+ * const auth = createNoopAuthAdapter();
338
+ * await auth.getSession(); // null
339
+ * await auth.hasRole('admin'); // false
340
+ * const unsub = auth.onAuthChange(() => {}); // never called
341
+ * unsub(); // no-op
342
+ * ```
343
+ */
344
+ declare function createNoopAuthAdapter(): AuthAdapter;
345
+
346
+ /**
347
+ * @module @enterstellar-ai/adapters/create-data-adapter
348
+ * @description Factory functions for creating validated `DataAdapter` instances.
349
+ *
350
+ * - `createDataAdapter(config)` — wraps a consumer-provided implementation,
351
+ * validates config via {@link validateAdapterConfig}, and wraps every method
352
+ * in error handling per Design Choice AD5 (raw vendor errors never leak).
353
+ *
354
+ * - `createNoopDataAdapter()` — returns a no-op adapter for testing and
355
+ * development when no real data source is connected.
356
+ *
357
+ * Both factories return a plain object with closures (R1 pattern — no classes).
358
+ *
359
+ * @see Bible §4.15
360
+ * @see Design Choice AD1 — minimal but complete: query, mutate, subscribe
361
+ * @see Design Choice AD2 — always async (except subscribe's sync unsubscribe return)
362
+ * @see Design Choice AD3 — convention-based dot-notation resolver
363
+ * @see Design Choice AD5 — wrap into EnterstellarError
364
+ */
365
+
366
+ /**
367
+ * Creates a validated `DataAdapter` from consumer-provided config.
368
+ *
369
+ * The factory:
370
+ * 1. Validates the config (name + required methods) — throws `ENS-7001` on failure.
371
+ * 2. Wraps `query()` in error handling → `ENS-7003` on throw (includes resource name).
372
+ * 3. Wraps `mutate()` in error handling → `ENS-7004` on throw (includes resource + action).
373
+ * 4. Wraps `subscribe()` in error handling → `ENS-7002` on throw (generic method error).
374
+ *
375
+ * Consumers never see raw vendor errors — all failures are `EnterstellarError` (AD5).
376
+ *
377
+ * @param config - The adapter implementation with a `name` and all required methods.
378
+ * @returns A frozen `DataAdapter` instance.
379
+ * @throws `EnterstellarError` with code `ENS-7001` if config validation fails.
380
+ *
381
+ * @example
382
+ * ```ts
383
+ * import { createDataAdapter } from '@enterstellar-ai/adapters';
384
+ *
385
+ * const data = createDataAdapter({
386
+ * name: 'supabase-data',
387
+ * query: async (resource, params) => {
388
+ * const { data } = await supabase.from(resource).select('*').match(params ?? {});
389
+ * return data ?? [];
390
+ * },
391
+ * mutate: async (resource, action, payload) => {
392
+ * if (action === 'create') {
393
+ * const { data } = await supabase.from(resource).insert(payload).select().single();
394
+ * return data;
395
+ * }
396
+ * return null;
397
+ * },
398
+ * subscribe: (resource, callback) => {
399
+ * const channel = supabase.channel(resource)
400
+ * .on('postgres_changes', { event: '*', schema: 'public', table: resource },
401
+ * () => { data.query(resource).then(callback); })
402
+ * .subscribe();
403
+ * return () => { void supabase.removeChannel(channel); };
404
+ * },
405
+ * });
406
+ * ```
407
+ */
408
+ declare function createDataAdapter(config: DataAdapterConfig): DataAdapter;
409
+ /**
410
+ * Creates a no-op `DataAdapter` for testing and development.
411
+ *
412
+ * All methods resolve to safe defaults:
413
+ * - `query()` → `[]` (empty result set)
414
+ * - `mutate()` → `null` (no record returned)
415
+ * - `subscribe()` → no-op unsubscribe function
416
+ *
417
+ * @returns A frozen, no-op `DataAdapter` instance.
418
+ *
419
+ * @example
420
+ * ```ts
421
+ * import { createNoopDataAdapter } from '@enterstellar-ai/adapters';
422
+ *
423
+ * const data = createNoopDataAdapter();
424
+ * await data.query('patients.vitals'); // []
425
+ * await data.mutate('patients', 'create', { name: 'Test' }); // null
426
+ * const unsub = data.subscribe('patients', () => {}); // noop unsub
427
+ * unsub(); // no-op
428
+ * ```
429
+ */
430
+ declare function createNoopDataAdapter(): DataAdapter;
431
+
432
+ /**
433
+ * @module @enterstellar-ai/adapters/create-error-adapter
434
+ * @description Factory functions for creating validated `ErrorAdapter` instances.
435
+ *
436
+ * - `createErrorAdapter(config)` — wraps a consumer-provided implementation,
437
+ * validates config via {@link validateAdapterConfig}, and wraps every method
438
+ * in error handling per Design Choice AD5 (raw vendor errors never leak).
439
+ *
440
+ * - `createNoopErrorAdapter()` — returns a no-op adapter for testing and
441
+ * development when no real error tracking service is connected.
442
+ *
443
+ * Both factories return a plain object with closures (R1 pattern — no classes).
444
+ *
445
+ * @see Bible §4.15
446
+ * @see Design Choice AD2 — all methods async (I/O + future-proofing)
447
+ * @see Design Choice AD5 — wrap into EnterstellarError
448
+ */
449
+
450
+ /**
451
+ * Creates a validated `ErrorAdapter` from consumer-provided config.
452
+ *
453
+ * The factory:
454
+ * 1. Validates the config (name + required methods) — throws `ENS-7001` on failure.
455
+ * 2. Wraps `report()` in async error handling → `ENS-7002` on throw.
456
+ * 3. Wraps `shouldRetry()` in async error handling → `ENS-7002` on throw.
457
+ * 4. Wraps `sanitize()` in async error handling → `ENS-7002` on throw.
458
+ *
459
+ * All three methods are async per AD2 — even `shouldRetry` and `sanitize`
460
+ * which may seem synchronous in simple implementations, but production
461
+ * adapters may require remote circuit breaker checks or external PII
462
+ * detection services.
463
+ *
464
+ * Consumers never see raw vendor errors — all failures are `EnterstellarError` (AD5).
465
+ *
466
+ * @param config - The adapter implementation with a `name` and all required methods.
467
+ * @returns A frozen `ErrorAdapter` instance.
468
+ * @throws `EnterstellarError` with code `ENS-7001` if config validation fails.
469
+ *
470
+ * @example
471
+ * ```ts
472
+ * import { createErrorAdapter } from '@enterstellar-ai/adapters';
473
+ *
474
+ * const errors = createErrorAdapter({
475
+ * name: 'sentry-error',
476
+ * report: async (error, context) => {
477
+ * Sentry.captureException(error, { extra: context });
478
+ * },
479
+ * shouldRetry: async (error, attempt) => attempt < 3 && isTransient(error),
480
+ * sanitize: async (error) => {
481
+ * const sanitized = new Error(error.message.replace(/SSN-\d+/g, '[REDACTED]'));
482
+ * sanitized.stack = error.stack;
483
+ * return sanitized;
484
+ * },
485
+ * });
486
+ * ```
487
+ */
488
+ declare function createErrorAdapter(config: ErrorAdapterConfig): ErrorAdapter;
489
+ /**
490
+ * Creates a no-op `ErrorAdapter` for testing and development.
491
+ *
492
+ * All methods resolve to safe defaults:
493
+ * - `report()` → void (errors silently consumed)
494
+ * - `shouldRetry()` → `false` (never retry)
495
+ * - `sanitize()` → returns error as-is (no transformation)
496
+ *
497
+ * @returns A frozen, no-op `ErrorAdapter` instance.
498
+ *
499
+ * @example
500
+ * ```ts
501
+ * import { createNoopErrorAdapter } from '@enterstellar-ai/adapters';
502
+ *
503
+ * const errors = createNoopErrorAdapter();
504
+ * await errors.report(new Error('test')); // no-op
505
+ * await errors.shouldRetry(new Error('test'), 1); // false
506
+ * await errors.sanitize(new Error('test')); // returns same error
507
+ * ```
508
+ */
509
+ declare function createNoopErrorAdapter(): ErrorAdapter;
510
+
511
+ /**
512
+ * @module @enterstellar-ai/adapters/create-analytics-adapter
513
+ * @description Factory functions for creating validated `AnalyticsAdapter` instances.
514
+ *
515
+ * - `createAnalyticsAdapter(config)` — wraps a consumer-provided implementation,
516
+ * validates config via {@link validateAdapterConfig}, and wraps every method
517
+ * in error handling per Design Choice AD5 (raw vendor errors never leak).
518
+ *
519
+ * - `createNoopAnalyticsAdapter()` — returns a no-op adapter for testing and
520
+ * development when no real analytics service is connected.
521
+ *
522
+ * Both factories return a plain object with closures (R1 pattern — no classes).
523
+ *
524
+ * @see Bible §4.15
525
+ * @see Design Choice AD1 — minimal but complete: track, identify
526
+ * @see Design Choice AD5 — wrap into EnterstellarError
527
+ */
528
+
529
+ /**
530
+ * Creates a validated `AnalyticsAdapter` from consumer-provided config.
531
+ *
532
+ * The factory:
533
+ * 1. Validates the config (name + required methods) — throws `ENS-7001` on failure.
534
+ * 2. Wraps `track()` in sync error handling → `ENS-7002` on throw.
535
+ * 3. Wraps `identify()` in sync error handling → `ENS-7002` on throw.
536
+ *
537
+ * Both `track()` and `identify()` are fire-and-forget (void return).
538
+ * Consumers never see raw vendor errors — all failures are `EnterstellarError` (AD5).
539
+ *
540
+ * @param config - The adapter implementation with a `name` and all required methods.
541
+ * @returns A frozen `AnalyticsAdapter` instance.
542
+ * @throws `EnterstellarError` with code `ENS-7001` if config validation fails.
543
+ *
544
+ * @example
545
+ * ```ts
546
+ * import { createAnalyticsAdapter } from '@enterstellar-ai/adapters';
547
+ *
548
+ * const analytics = createAnalyticsAdapter({
549
+ * name: 'mixpanel-analytics',
550
+ * track: (event, properties) => {
551
+ * mixpanel.track(event, properties);
552
+ * },
553
+ * identify: (userId, traits) => {
554
+ * mixpanel.identify(userId);
555
+ * if (traits) mixpanel.people.set(traits);
556
+ * },
557
+ * });
558
+ * ```
559
+ */
560
+ declare function createAnalyticsAdapter(config: AnalyticsAdapterConfig): AnalyticsAdapter;
561
+ /**
562
+ * Creates a no-op `AnalyticsAdapter` for testing and development.
563
+ *
564
+ * All methods are silent no-ops:
565
+ * - `track()` → void (events silently consumed)
566
+ * - `identify()` → void (identity silently consumed)
567
+ *
568
+ * @returns A frozen, no-op `AnalyticsAdapter` instance.
569
+ *
570
+ * @example
571
+ * ```ts
572
+ * import { createNoopAnalyticsAdapter } from '@enterstellar-ai/adapters';
573
+ *
574
+ * const analytics = createNoopAnalyticsAdapter();
575
+ * analytics.track('zone_rendered', { zone: 'main' }); // no-op
576
+ * analytics.identify('user-123', { role: 'clinician' }); // no-op
577
+ * ```
578
+ */
579
+ declare function createNoopAnalyticsAdapter(): AnalyticsAdapter;
580
+
581
+ /**
582
+ * @module @enterstellar-ai/adapters/errors
583
+ * @description Error factory functions for the adapters module.
584
+ *
585
+ * Every error is an `EnterstellarError` with:
586
+ * - Machine-readable `code` (`ENS-7xxx`)
587
+ * - Module identifier `'adapters'`
588
+ * - `recoverable` flag per Enterstellar error taxonomy
589
+ *
590
+ * Error taxonomy:
591
+ * - `ENS-7001` — ADAPTER_VALIDATION_FAILED: config missing required methods or invalid name
592
+ * (non-recoverable, developer misconfiguration)
593
+ * - `ENS-7002` — ADAPTER_METHOD_ERROR: adapter method threw during execution (recoverable)
594
+ * - `ENS-7003` — ADAPTER_QUERY_ERROR: DataAdapter query() failed (recoverable)
595
+ * - `ENS-7004` — ADAPTER_MUTATION_ERROR: DataAdapter mutate() failed (recoverable)
596
+ * - `ENS-7005` — ADAPTER_AUTH_ERROR: AuthAdapter session/role check failed (recoverable)
597
+ *
598
+ * @see Coding Rules — Error Taxonomy
599
+ * @see Design Choice AD5 — wrap into EnterstellarError
600
+ * @see Design Choice C14 — error code ranges
601
+ */
602
+
603
+ /**
604
+ * Creates an error for when an adapter config fails validation.
605
+ *
606
+ * This is a **non-recoverable** error — it indicates developer misconfiguration
607
+ * (missing required methods, empty name, non-function fields). The consumer
608
+ * must fix their adapter config before proceeding.
609
+ *
610
+ * @param adapterType - The adapter category that failed validation (e.g., `'auth'`, `'data'`).
611
+ * @param reason - Human-readable explanation of what is invalid.
612
+ * @returns An `EnterstellarError` with code `ENS-7001`.
613
+ *
614
+ * @example
615
+ * ```ts
616
+ * throw adapterValidationError('auth', 'Missing required method: getSession');
617
+ * // EnterstellarError: Adapter validation failed for "auth": Missing required method: getSession
618
+ * // code: 'ENS-7001', module: 'adapters', recoverable: false
619
+ * ```
620
+ */
621
+ declare function adapterValidationError(adapterType: AdapterType, reason: string): EnterstellarError;
622
+ /**
623
+ * Creates an error for when an adapter method throws during execution.
624
+ *
625
+ * This is a **recoverable** error — the underlying infrastructure may have
626
+ * experienced a transient failure. The operation can be retried. The original
627
+ * error is preserved in `cause` for debugging (AD5).
628
+ *
629
+ * @param adapterName - The adapter instance name (e.g., `'supabase-auth'`).
630
+ * @param methodName - The method that threw (e.g., `'getSession'`, `'track'`).
631
+ * @param cause - The original error thrown by the adapter implementation.
632
+ * @returns An `EnterstellarError` with code `ENS-7002`.
633
+ *
634
+ * @example
635
+ * ```ts
636
+ * throw adapterMethodError('supabase-auth', 'getSession', originalError);
637
+ * // EnterstellarError: Adapter "supabase-auth" method "getSession" threw.
638
+ * // code: 'ENS-7002', module: 'adapters', recoverable: true, cause: originalError
639
+ * ```
640
+ */
641
+ declare function adapterMethodError(adapterName: string, methodName: string, cause?: unknown): EnterstellarError;
642
+ /**
643
+ * Creates an error for when a {@link DataAdapter}'s `query()` method fails.
644
+ *
645
+ * This is a **recoverable** error — the data source may be temporarily
646
+ * unavailable. Specialized variant of `ENS-7002` that includes the
647
+ * queried resource name for debugging.
648
+ *
649
+ * @param adapterName - The adapter instance name (e.g., `'supabase-data'`).
650
+ * @param resource - The resource that was being queried (e.g., `'patients.vitals'`).
651
+ * @param cause - The original error thrown by the query implementation.
652
+ * @returns An `EnterstellarError` with code `ENS-7003`.
653
+ *
654
+ * @example
655
+ * ```ts
656
+ * throw adapterQueryError('supabase-data', 'patients.vitals', pgError);
657
+ * // EnterstellarError: Adapter "supabase-data" query failed for resource "patients.vitals".
658
+ * // code: 'ENS-7003', module: 'adapters', recoverable: true, cause: pgError
659
+ * ```
660
+ */
661
+ declare function adapterQueryError(adapterName: string, resource: string, cause?: unknown): EnterstellarError;
662
+ /**
663
+ * Creates an error for when a {@link DataAdapter}'s `mutate()` method fails.
664
+ *
665
+ * This is a **recoverable** error — the data source may be temporarily
666
+ * unavailable. Specialized variant of `ENS-7002` that includes the
667
+ * resource name and mutation action for debugging.
668
+ *
669
+ * @param adapterName - The adapter instance name (e.g., `'supabase-data'`).
670
+ * @param resource - The resource being mutated (e.g., `'patients'`).
671
+ * @param action - The mutation action that failed (`'create'`, `'update'`, or `'delete'`).
672
+ * @param cause - The original error thrown by the mutation implementation.
673
+ * @returns An `EnterstellarError` with code `ENS-7004`.
674
+ *
675
+ * @example
676
+ * ```ts
677
+ * throw adapterMutationError('supabase-data', 'patients', 'update', pgError);
678
+ * // EnterstellarError: Adapter "supabase-data" mutation "update" failed for resource "patients".
679
+ * // code: 'ENS-7004', module: 'adapters', recoverable: true, cause: pgError
680
+ * ```
681
+ */
682
+ declare function adapterMutationError(adapterName: string, resource: string, action: 'create' | 'update' | 'delete', cause?: unknown): EnterstellarError;
683
+ /**
684
+ * Creates an error for when an {@link AuthAdapter}'s session or role check fails.
685
+ *
686
+ * This is a **recoverable** error — the auth provider may be temporarily
687
+ * unavailable, or the session may have expired. Specialized variant of
688
+ * `ENS-7002` for authentication operations.
689
+ *
690
+ * @param adapterName - The adapter instance name (e.g., `'clerk-auth'`).
691
+ * @param operation - The auth operation that failed (e.g., `'getSession'`, `'hasRole'`).
692
+ * @param cause - The original error thrown by the auth implementation.
693
+ * @returns An `EnterstellarError` with code `ENS-7005`.
694
+ *
695
+ * @example
696
+ * ```ts
697
+ * throw adapterAuthError('clerk-auth', 'getSession', sessionExpiredError);
698
+ * // EnterstellarError: Adapter "clerk-auth" auth operation "getSession" failed.
699
+ * // code: 'ENS-7005', module: 'adapters', recoverable: true, cause: sessionExpiredError
700
+ * ```
701
+ */
702
+ declare function adapterAuthError(adapterName: string, operation: string, cause?: unknown): EnterstellarError;
703
+
704
+ /**
705
+ * @module @enterstellar-ai/adapters/validate-adapter
706
+ * @description Shared runtime validation for adapter configuration objects.
707
+ *
708
+ * Called by each `createXxxAdapter()` factory before wrapping the consumer's
709
+ * implementation. Validates that:
710
+ * - The config has a non-empty `name` string
711
+ * - All required methods for the adapter type are present and are functions
712
+ *
713
+ * Throws `ENS-7001` (`adapterValidationError`) on any violation — this is a
714
+ * non-recoverable developer error per Enterstellar error taxonomy.
715
+ *
716
+ * @see Coding Rules — Error Taxonomy (developer errors → fatal throw)
717
+ * @see Design Choice AD1 — minimal but complete interfaces
718
+ */
719
+
720
+ /**
721
+ * Validates that an adapter config object has a valid name and all required methods.
722
+ *
723
+ * This function performs two checks:
724
+ * 1. **Name check:** `config.name` must be a non-empty string.
725
+ * 2. **Method check:** Every method listed in {@link REQUIRED_METHODS} for the
726
+ * given `adapterType` must be present on the config and be `typeof === 'function'`.
727
+ *
728
+ * Throws `ENS-7001` on the first validation failure encountered.
729
+ *
730
+ * @param adapterType - The adapter category being validated (e.g., `'auth'`, `'data'`).
731
+ * @param config - The raw config object to validate.
732
+ * @throws `EnterstellarError` with code `ENS-7001` if validation fails.
733
+ *
734
+ * @example
735
+ * ```ts
736
+ * // Valid — passes silently
737
+ * validateAdapterConfig('auth', {
738
+ * name: 'supabase-auth',
739
+ * getSession: async () => null,
740
+ * hasRole: async () => false,
741
+ * onAuthChange: (cb) => () => {},
742
+ * });
743
+ *
744
+ * // Invalid — throws ENS-7001
745
+ * validateAdapterConfig('auth', { name: '', getSession: null });
746
+ * // EnterstellarError: Adapter validation failed for "auth": "name" must be a non-empty string.
747
+ * ```
748
+ */
749
+ declare function validateAdapterConfig(adapterType: AdapterType, config: Readonly<Record<string, unknown>>): void;
750
+
751
+ /**
752
+ * @module @enterstellar-ai/adapters/version
753
+ * @description Package version constant for `@enterstellar-ai/adapters`.
754
+ *
755
+ * Used by DevTools for version display and runtime compatibility checks.
756
+ * Must be kept in sync with the `version` field in `package.json`.
757
+ *
758
+ * @see Design Choice T14 — version exports
759
+ */
760
+ /**
761
+ * Current version of the `@enterstellar-ai/adapters` package.
762
+ *
763
+ * @remarks
764
+ * This value MUST match the `version` field in `package.json`.
765
+ * Update this constant whenever a new version is released via Changesets.
766
+ */
767
+ declare const ADAPTERS_VERSION: "0.0.0";
768
+
769
+ export { ADAPTERS_VERSION, type AdapterType, type AnalyticsAdapterConfig, type AuthAdapterConfig, type DataAdapterConfig, type ErrorAdapterConfig, adapterAuthError, adapterMethodError, adapterMutationError, adapterQueryError, adapterValidationError, createAnalyticsAdapter, createAuthAdapter, createDataAdapter, createErrorAdapter, createNoopAnalyticsAdapter, createNoopAuthAdapter, createNoopDataAdapter, createNoopErrorAdapter, validateAdapterConfig };