@vunexa/lixa 0.1.6-alpha.7 → 0.1.6-alpha.8

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 CHANGED
@@ -17,8 +17,7 @@ A flexible, provider-agnostic OAuth 2.0 and OpenID Connect (OIDC) client library
17
17
  - **Multi-SSO Account Linking**: Seamlessly merge accounts sharing the same verified email address under a single unified user session.
18
18
  - **Post-Login Resource Connection API**: Connect third-party API providers (GitHub Repositories, Google Drive, Slack) post-authentication and manage resource tokens on the user session.
19
19
  - **Multi-provider OAuth/OIDC support** with unified API.
20
- - **Built-in providers** for Google, GitHub, and more via `@vunexa/lixa-providers`.
21
- - **Custom provider support** with extensible provider interface.
20
+ - **Pre-built Database Storage Adapters**: Official Prisma and Drizzle ORM adapters via `@vunexa/lixa-adapters` with support for PostgreSQL, MySQL, and SQLite.
22
21
  - **Unified session management** via `SessionHandler` (generation + storage).
23
22
  - **Unified state management** via `StateHandler` (PKCE + CSRF protection).
24
23
  - **Automatic PKCE** (Proof Key for Code Exchange) for all OAuth flows.
@@ -17,8 +17,7 @@ A flexible, provider-agnostic OAuth 2.0 and OpenID Connect (OIDC) client library
17
17
  - **Multi-SSO Account Linking**: Seamlessly merge accounts sharing the same verified email address under a single unified user session.
18
18
  - **Post-Login Resource Connection API**: Connect third-party API providers (GitHub Repositories, Google Drive, Slack) post-authentication and manage resource tokens on the user session.
19
19
  - **Multi-provider OAuth/OIDC support** with unified API.
20
- - **Built-in providers** for Google, GitHub, and more via `@vunexa/lixa-providers`.
21
- - **Custom provider support** with extensible provider interface.
20
+ - **Pre-built Database Storage Adapters**: Official Prisma and Drizzle ORM adapters via `@vunexa/lixa-adapters` with support for PostgreSQL, MySQL, and SQLite.
22
21
  - **Unified session management** via `SessionHandler` (generation + storage).
23
22
  - **Unified state management** via `StateHandler` (PKCE + CSRF protection).
24
23
  - **Automatic PKCE** (Proof Key for Code Exchange) for all OAuth flows.
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Base error class for all Lixa authentication and authorization errors.
3
+ *
4
+ * @public
5
+ */
6
+ export declare class LixaError extends Error {
7
+ /**
8
+ * Standard error code string.
9
+ */
10
+ readonly code: string;
11
+ /**
12
+ * Additional error context data.
13
+ */
14
+ readonly details: Record<string, unknown> | undefined;
15
+ constructor(message: string, code?: string, details?: Record<string, unknown>);
16
+ }
17
+ /**
18
+ * Thrown when an OAuth state parameter is invalid, missing, or has expired.
19
+ *
20
+ * @public
21
+ */
22
+ export declare class InvalidStateError extends LixaError {
23
+ constructor(message?: string, details?: Record<string, unknown>);
24
+ }
25
+ /**
26
+ * Thrown when attempting to use a provider that is not configured in the Lixa instance.
27
+ *
28
+ * @public
29
+ */
30
+ export declare class ProviderNotConfiguredError extends LixaError {
31
+ constructor(provider: string, details?: Record<string, unknown>);
32
+ }
33
+ /**
34
+ * Thrown when a provider configuration is invalid or missing required credentials.
35
+ *
36
+ * @public
37
+ */
38
+ export declare class InvalidProviderConfigError extends LixaError {
39
+ constructor(message: string, details?: Record<string, unknown>);
40
+ }
41
+ /**
42
+ * Thrown when OAuth callback parameters (e.g. authorization code or state) are missing or malformed.
43
+ *
44
+ * @public
45
+ */
46
+ export declare class InvalidOAuthCallbackError extends LixaError {
47
+ constructor(message: string, details?: Record<string, unknown>);
48
+ }
49
+ /**
50
+ * Thrown when exchanging an authorization code for OAuth tokens fails at the provider endpoint.
51
+ *
52
+ * @public
53
+ */
54
+ export declare class TokenExchangeError extends LixaError {
55
+ readonly status: number | undefined;
56
+ constructor(message: string, status?: number, details?: Record<string, unknown>);
57
+ }
58
+ /**
59
+ * Thrown when a user session is not found or has expired.
60
+ *
61
+ * @public
62
+ */
63
+ export declare class SessionNotFoundError extends LixaError {
64
+ constructor(message?: string, details?: Record<string, unknown>);
65
+ }
66
+ /**
67
+ * Thrown when account linking fails, e.g. when unverified email linking is rejected.
68
+ *
69
+ * @public
70
+ */
71
+ export declare class EmailNotVerifiedError extends LixaError {
72
+ constructor(email?: string, details?: Record<string, unknown>);
73
+ }
74
+ /**
75
+ * Thrown when unlinking an account violates security constraints (e.g. unlinking the only login provider).
76
+ *
77
+ * @public
78
+ */
79
+ export declare class AccountUnlinkError extends LixaError {
80
+ constructor(message: string, details?: Record<string, unknown>);
81
+ }
82
+ /**
83
+ * Thrown when a refresh token is missing or token refresh fails for a connected resource.
84
+ *
85
+ * @public
86
+ */
87
+ export declare class RefreshTokenError extends LixaError {
88
+ constructor(message: string, details?: Record<string, unknown>);
89
+ }
90
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,qBAAa,SAAU,SAAQ,KAAK;IAClC;;OAEG;IACH,SAAgB,IAAI,EAAE,MAAM,CAAC;IAE7B;;OAEG;IACH,SAAgB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;gBAEjD,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,MAAqB,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAS5F;AAED;;;;GAIG;AACH,qBAAa,iBAAkB,SAAQ,SAAS;gBAClC,OAAO,GAAE,MAAmC,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAG5F;AAED;;;;GAIG;AACH,qBAAa,0BAA2B,SAAQ,SAAS;gBAC3C,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAShE;AAED;;;;GAIG;AACH,qBAAa,0BAA2B,SAAQ,SAAS;gBAC3C,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAG/D;AAED;;;;GAIG;AACH,qBAAa,yBAA0B,SAAQ,SAAS;gBAC1C,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAG/D;AAED;;;;GAIG;AACH,qBAAa,kBAAmB,SAAQ,SAAS;IAC/C,SAAgB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;gBAE/B,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAIhF;AAED;;;;GAIG;AACH,qBAAa,oBAAqB,SAAQ,SAAS;gBACrC,OAAO,GAAE,MAAkD,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAG3G;AAED;;;;GAIG;AACH,qBAAa,qBAAsB,SAAQ,SAAS;gBACtC,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAO9D;AAED;;;;GAIG;AACH,qBAAa,kBAAmB,SAAQ,SAAS;gBACnC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAG/D;AAED;;;;GAIG;AACH,qBAAa,iBAAkB,SAAQ,SAAS;gBAClC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAG/D"}
@@ -123,6 +123,41 @@ export declare enum AccountLinkingStrategy {
123
123
  ISOLATED = "ISOLATED"
124
124
  }
125
125
 
126
+ /**
127
+ * Thrown when unlinking an account violates security constraints (e.g. unlinking the only login provider).
128
+ *
129
+ * @public
130
+ */
131
+ export declare class AccountUnlinkError extends LixaError {
132
+ constructor(message: string, details?: Record<string, unknown>);
133
+ }
134
+
135
+ /**
136
+ * Generates an expired session cookie payload to clear the session on logout.
137
+ *
138
+ * @param options - Optional overrides for cookie name or attributes
139
+ *
140
+ * @example
141
+ * ```typescript
142
+ * const cookie = clearSessionCookie();
143
+ * res.setHeader("Set-Cookie", cookie.header);
144
+ * // or with Express:
145
+ * res.clearCookie(cookie.name, cookie.options);
146
+ * ```
147
+ *
148
+ * @public
149
+ */
150
+ export declare function clearSessionCookie(options?: CookieOptions): CookiePayload;
151
+
152
+ /**
153
+ * Generates an expired OAuth state cookie payload to clean up the state cookie after callback.
154
+ *
155
+ * @param options - Optional overrides for cookie attributes
156
+ *
157
+ * @public
158
+ */
159
+ export declare function clearStateCookie(options?: CookieOptions): CookiePayload;
160
+
126
161
  /**
127
162
  * Type representing the keys of configured providers
128
163
  */
@@ -151,6 +186,91 @@ export declare interface ConnectedResource {
151
186
  connectedAt: number;
152
187
  }
153
188
 
189
+ /**
190
+ * Sensible default cookie configuration options.
191
+ * Follows RFC 6265bis and OAuth 2.0 security best practices.
192
+ *
193
+ * @public
194
+ */
195
+ export declare interface CookieOptions {
196
+ /**
197
+ * Cookie name.
198
+ * @default 'lixa_session'
199
+ */
200
+ name?: string | undefined;
201
+ /**
202
+ * Cookie path.
203
+ * @default '/'
204
+ */
205
+ path?: string | undefined;
206
+ /**
207
+ * Maximum age of the cookie in seconds.
208
+ */
209
+ maxAge?: number | undefined;
210
+ /**
211
+ * Prevents client-side scripts from accessing the cookie (XSS protection).
212
+ * @default true
213
+ */
214
+ httpOnly?: boolean | undefined;
215
+ /**
216
+ * Ensures the cookie is only transmitted over secure HTTPS connections.
217
+ * @default false in development, true in production
218
+ */
219
+ secure?: boolean | undefined;
220
+ /**
221
+ * Controls whether the cookie is sent with cross-site requests (CSRF protection).
222
+ * @default 'lax'
223
+ */
224
+ sameSite?: "lax" | "strict" | "none" | undefined;
225
+ /**
226
+ * Cookie domain.
227
+ */
228
+ domain?: string | undefined;
229
+ }
230
+
231
+ /**
232
+ * Cookie payload containing name, value, options, and formatted header.
233
+ *
234
+ * @public
235
+ */
236
+ export declare interface CookiePayload {
237
+ name: string;
238
+ value: string;
239
+ options: CookieOptions;
240
+ /**
241
+ * Formatted `Set-Cookie` header value string.
242
+ */
243
+ header: string;
244
+ }
245
+
246
+ /**
247
+ * Generates a session cookie payload with secure default options.
248
+ *
249
+ * @param sessionId - The session identifier string
250
+ * @param options - Optional overrides for cookie attributes
251
+ *
252
+ * @example
253
+ * ```typescript
254
+ * const cookie = createSessionCookie(sessionId);
255
+ * res.setHeader("Set-Cookie", cookie.header);
256
+ * // or with Express:
257
+ * res.cookie(cookie.name, cookie.value, cookie.options);
258
+ * ```
259
+ *
260
+ * @public
261
+ */
262
+ export declare function createSessionCookie(sessionId: string, options?: CookieOptions): CookiePayload;
263
+
264
+ /**
265
+ * Generates an OAuth CSRF state cookie payload for in-flight authorization flows.
266
+ *
267
+ * @param state - The random state string
268
+ * @param options - Optional overrides for cookie attributes
269
+ *
270
+ * @public
271
+ */
272
+ export declare function createStateCookie(state: string, options?: CookieOptions): CookiePayload;
273
+
154
274
  /**
155
275
  * Decode JWT ID token to extract user information
156
276
  *
@@ -158,6 +278,30 @@ export declare interface ConnectedResource {
158
278
  */
159
279
  export declare function decodeIdToken(idToken: string): UserInfo;
160
280
 
281
+ /**
282
+ * Default session cookie name.
283
+ * @public
284
+ */
285
+ export declare const DEFAULT_SESSION_COOKIE_NAME = "lixa_session";
286
+
287
+ /**
288
+ * Default session max age in seconds (24 hours).
289
+ * @public
290
+ */
291
+ export declare const DEFAULT_SESSION_MAX_AGE_SECONDS: number;
292
+
293
+ /**
294
+ * Default OAuth state cookie name.
295
+ * @public
296
+ */
297
+ export declare const DEFAULT_STATE_COOKIE_NAME = "lixa_oauth_state";
298
+
299
+ /**
300
+ * Default OAuth state max age in seconds (10 minutes).
301
+ * @public
302
+ */
303
+ export declare const DEFAULT_STATE_MAX_AGE_SECONDS: number;
304
+
161
305
  /**
162
306
  * Determine OAuth provider from ID token issuer
163
307
  *
@@ -165,6 +309,15 @@ export declare function decodeIdToken(idToken: string): UserInfo;
165
309
  */
166
310
  export declare function determineProviderFromIssuer(userInfo: UserInfo): string | null;
167
311
 
312
+ /**
313
+ * Thrown when account linking fails, e.g. when unverified email linking is rejected.
314
+ *
315
+ * @public
316
+ */
317
+ export declare class EmailNotVerifiedError extends LixaError {
318
+ constructor(email?: string, details?: Record<string, unknown>);
319
+ }
320
+
168
321
  /**
169
322
  * Extract user info from OAuth token data
170
323
  *
@@ -219,6 +372,33 @@ export declare function extractUserInfo(tokenData: OAuthTokenResponse, providerM
219
372
  */
220
373
  export declare function fetchUserInfo(accessToken: string, userInfoEndpoint: string): Promise<UserInfo>;
221
374
 
375
+ /**
376
+ * Thrown when OAuth callback parameters (e.g. authorization code or state) are missing or malformed.
377
+ *
378
+ * @public
379
+ */
380
+ export declare class InvalidOAuthCallbackError extends LixaError {
381
+ constructor(message: string, details?: Record<string, unknown>);
382
+ }
383
+
384
+ /**
385
+ * Thrown when a provider configuration is invalid or missing required credentials.
386
+ *
387
+ * @public
388
+ */
389
+ export declare class InvalidProviderConfigError extends LixaError {
390
+ constructor(message: string, details?: Record<string, unknown>);
391
+ }
392
+
393
+ /**
394
+ * Thrown when an OAuth state parameter is invalid, missing, or has expired.
395
+ *
396
+ * @public
397
+ */
398
+ export declare class InvalidStateError extends LixaError {
399
+ constructor(message?: string, details?: Record<string, unknown>);
400
+ }
401
+
222
402
  /**
223
403
  * Interface for OAuth 2.0 and OpenID Connect provider implementations.
224
404
  *
@@ -359,6 +539,12 @@ export declare interface IProvider {
359
539
  authScopes?: string[];
360
540
  }
361
541
 
542
+ /**
543
+ * Checks if the runtime environment is production.
544
+ * @public
545
+ */
546
+ export declare function isProductionEnvironment(): boolean;
547
+
362
548
  /**
363
549
  * Represents a linked provider account within a user's session.
364
550
  *
@@ -460,7 +646,7 @@ export declare class Lixa<TConfig extends LixaConfig<Record<string, ProviderConf
460
646
  *
461
647
  * @param name - The provider name
462
648
  * @param config - The provider configuration
463
- * @throws Error when required fields are missing or invalid
649
+ * @throws InvalidProviderConfigError when required fields are missing or invalid
464
650
  */
465
651
  private validateProviderConfig;
466
652
  /**
@@ -468,7 +654,7 @@ export declare class Lixa<TConfig extends LixaConfig<Record<string, ProviderConf
468
654
  *
469
655
  * @param name - The provider name
470
656
  * @param provider - The provider implementation
471
- * @throws Error when required properties are missing
657
+ * @throws InvalidProviderConfigError when required properties are missing
472
658
  */
473
659
  private validateProviderImplementation;
474
660
  /**
@@ -803,7 +989,16 @@ export declare class Lixa<TConfig extends LixaConfig<Record<string, ProviderConf
803
989
  * Disconnects a resource provider from an active session and user account.
804
990
  */
805
991
  disconnectResource(sessionId: string, provider: string): Promise<boolean>;
992
+ /**
993
+ * Retrieves active session details from session storage.
994
+ */
806
995
  fetchSessionInfo(sessionId: string): Promise<Session | null>;
996
+ /**
997
+ * Deletes a session from session storage (e.g. on logout).
998
+ *
999
+ * @param sessionId - Active session identifier
1000
+ */
1001
+ deleteSession(sessionId: string): Promise<void>;
807
1002
  private exchangeCodeForToken;
808
1003
  private findProviderByType;
809
1004
  }
@@ -864,6 +1059,23 @@ export declare interface LixaConfig<TProviders extends Record<string, ProviderCo
864
1059
  debug?: boolean;
865
1060
  }
866
1061
 
1062
+ /**
1063
+ * Base error class for all Lixa authentication and authorization errors.
1064
+ *
1065
+ * @public
1066
+ */
1067
+ export declare class LixaError extends Error {
1068
+ /**
1069
+ * Standard error code string.
1070
+ */
1071
+ readonly code: string;
1072
+ /**
1073
+ * Additional error context data.
1074
+ */
1075
+ readonly details: Record<string, unknown> | undefined;
1076
+ constructor(message: string, code?: string, details?: Record<string, unknown>);
1077
+ }
1078
+
867
1079
  /**
868
1080
  * OAuth 2.0 token response structure.
869
1081
  * Based on RFC 6749 Section 5.1 and OpenID Connect Core 1.0 Section 3.1.3.3
@@ -986,6 +1198,24 @@ export declare interface ProviderMetadata {
986
1198
  };
987
1199
  }
988
1200
 
1201
+ /**
1202
+ * Thrown when attempting to use a provider that is not configured in the Lixa instance.
1203
+ *
1204
+ * @public
1205
+ */
1206
+ export declare class ProviderNotConfiguredError extends LixaError {
1207
+ constructor(provider: string, details?: Record<string, unknown>);
1208
+ }
1209
+
1210
+ /**
1211
+ * Thrown when a refresh token is missing or token refresh fails for a connected resource.
1212
+ *
1213
+ * @public
1214
+ */
1215
+ export declare class RefreshTokenError extends LixaError {
1216
+ constructor(message: string, details?: Record<string, unknown>);
1217
+ }
1218
+
989
1219
  /**
990
1220
  * Resource handler configuration.
991
1221
  *
@@ -1048,6 +1278,18 @@ export declare type SafeLixaConfig<TProviders extends Record<string, ProviderCon
1048
1278
  providers: TProviders;
1049
1279
  };
1050
1280
 
1281
+ /**
1282
+ * Serializes a cookie name, value, and options into a standard `Set-Cookie` header string.
1283
+ *
1284
+ * @param name - Cookie name
1285
+ * @param value - Cookie value
1286
+ * @param options - Cookie attributes
1287
+ * @returns Formatted `Set-Cookie` string
1288
+ *
1289
+ * @public
1290
+ */
1291
+ export declare function serializeCookie(name: string, value: string, options?: CookieOptions): string;
1292
+
1051
1293
  /**
1052
1294
  * Represents a user session after successful OAuth authentication.
1053
1295
  *
@@ -1248,6 +1490,15 @@ export declare interface SessionHandler {
1248
1490
  generateSession?<T extends Session>(tokenData: OAuthTokenResponse, providerMetadata: ProviderMetadata): Promise<T>;
1249
1491
  }
1250
1492
 
1493
+ /**
1494
+ * Thrown when a user session is not found or has expired.
1495
+ *
1496
+ * @public
1497
+ */
1498
+ export declare class SessionNotFoundError extends LixaError {
1499
+ constructor(message?: string, details?: Record<string, unknown>);
1500
+ }
1501
+
1251
1502
  /**
1252
1503
  * Session storage operations interface.
1253
1504
  *
@@ -1473,6 +1724,16 @@ export declare interface StateStorage {
1473
1724
  deleteState(state: string): Promise<void>;
1474
1725
  }
1475
1726
 
1727
+ /**
1728
+ * Thrown when exchanging an authorization code for OAuth tokens fails at the provider endpoint.
1729
+ *
1730
+ * @public
1731
+ */
1732
+ export declare class TokenExchangeError extends LixaError {
1733
+ readonly status: number | undefined;
1734
+ constructor(message: string, status?: number, details?: Record<string, unknown>);
1735
+ }
1736
+
1476
1737
  /**
1477
1738
  * User information extracted from OAuth provider
1478
1739
  *