@vunexa/lixa 0.0.1-alpha.9 → 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 (52) hide show
  1. package/README.md +263 -143
  2. package/dist/dao/session-cache.d.ts +11 -0
  3. package/dist/dao/session-cache.d.ts.map +1 -0
  4. package/dist/dao/state-cache.d.ts +8 -6
  5. package/dist/dao/state-cache.d.ts.map +1 -1
  6. package/dist/dao/types.d.ts +376 -3
  7. package/dist/dao/types.d.ts.map +1 -1
  8. package/dist/export-types/index.d.ts +1397 -0
  9. package/dist/export-types/tsdoc-metadata.json +11 -0
  10. package/dist/index.cjs +1035 -0
  11. package/dist/index.cjs.map +1 -0
  12. package/dist/index.d.cts +1361 -0
  13. package/dist/index.d.ts +11 -2
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +992 -9
  16. package/dist/index.js.map +1 -1
  17. package/dist/lixa.d.ts +280 -15
  18. package/dist/lixa.d.ts.map +1 -1
  19. package/dist/models/session.d.ts +316 -0
  20. package/dist/models/session.d.ts.map +1 -0
  21. package/dist/providers/IProvider.d.ts +127 -4
  22. package/dist/providers/IProvider.d.ts.map +1 -1
  23. package/dist/providers/index.d.ts +0 -2
  24. package/dist/providers/index.d.ts.map +1 -1
  25. package/dist/types.d.ts +195 -24
  26. package/dist/types.d.ts.map +1 -1
  27. package/dist/utils/user-info.d.ts +82 -0
  28. package/dist/utils/user-info.d.ts.map +1 -0
  29. package/package.json +15 -10
  30. package/dist/dao/state-cache.js +0 -18
  31. package/dist/dao/state-cache.js.map +0 -1
  32. package/dist/dao/types.js +0 -2
  33. package/dist/dao/types.js.map +0 -1
  34. package/dist/lixa.js +0 -244
  35. package/dist/lixa.js.map +0 -1
  36. package/dist/providers/IProvider.js +0 -2
  37. package/dist/providers/IProvider.js.map +0 -1
  38. package/dist/providers/github.d.ts +0 -9
  39. package/dist/providers/github.d.ts.map +0 -1
  40. package/dist/providers/github.js +0 -8
  41. package/dist/providers/github.js.map +0 -1
  42. package/dist/providers/google.d.ts +0 -9
  43. package/dist/providers/google.d.ts.map +0 -1
  44. package/dist/providers/google.js +0 -8
  45. package/dist/providers/google.js.map +0 -1
  46. package/dist/providers/index.js +0 -3
  47. package/dist/providers/index.js.map +0 -1
  48. package/dist/types.js +0 -2
  49. package/dist/types.js.map +0 -1
  50. package/dist/utils/constants.js +0 -4
  51. package/dist/utils/constants.js.map +0 -1
  52. package/index.d.ts +0 -229
@@ -1,6 +1,379 @@
1
- export interface StateDao {
2
- saveState(state: string, data: any, expiresInSeconds: number): Promise<void>;
3
- getState(state: string): Promise<any | null>;
1
+ import type { Session } from "../models/session";
2
+ /**
3
+ * OAuth state data structure.
4
+ *
5
+ * @remarks
6
+ * This structure is used internally by Lixa to store OAuth flow state
7
+ * during the authorization process. It contains the information needed
8
+ * to complete the PKCE flow and route callbacks to the correct provider.
9
+ *
10
+ * @public
11
+ */
12
+ export interface StateData {
13
+ /**
14
+ * Provider name for callback routing.
15
+ * Used to identify which provider configuration to use when handling the callback.
16
+ *
17
+ * @example 'google', 'github', 'custom'
18
+ */
19
+ provider: string;
20
+ /**
21
+ * PKCE code verifier for secure token exchange.
22
+ * A cryptographically random string (64 hex characters) used in the PKCE flow
23
+ * to prevent authorization code interception attacks.
24
+ *
25
+ * @see RFC 7636 - Proof Key for Code Exchange
26
+ */
27
+ codeVerifier: string;
28
+ /**
29
+ * Unix timestamp in milliseconds when the state was created.
30
+ * Used for debugging and validation purposes.
31
+ */
32
+ createdAt: number;
33
+ }
34
+ /**
35
+ * State storage operations interface.
36
+ *
37
+ * @remarks
38
+ * Groups all state storage operations together. All methods must be implemented
39
+ * if this interface is provided.
40
+ *
41
+ * @public
42
+ */
43
+ export interface StateStorage {
44
+ /**
45
+ * Saves OAuth state with expiration.
46
+ *
47
+ * @param state - The state parameter value (random string for CSRF protection)
48
+ * @param data - State data including provider name and PKCE code verifier
49
+ * @param expiresInSeconds - TTL in seconds (typically 300 for 5 minutes)
50
+ */
51
+ saveState(state: string, data: StateData, expiresInSeconds: number): Promise<void>;
52
+ /**
53
+ * Retrieves OAuth state data.
54
+ *
55
+ * @param state - The state parameter value
56
+ * @returns State data or null if not found or expired
57
+ */
58
+ getState(state: string): Promise<StateData | null>;
59
+ /**
60
+ * Deletes OAuth state (called after successful validation).
61
+ *
62
+ * @param state - The state parameter value
63
+ */
4
64
  deleteState(state: string): Promise<void>;
5
65
  }
66
+ /**
67
+ * State handler for OAuth authorization flow.
68
+ *
69
+ * @remarks
70
+ * The StateHandler manages state generation and storage during the OAuth authorization flow.
71
+ *
72
+ * - GenerateState: Optional. Customizes how state parameters and PKCE verifiers are generated.
73
+ * If not provided, uses default implementation (cryptographically secure random strings).
74
+ *
75
+ * - storage: Optional. Provides custom state storage (save/get/delete operations).
76
+ * If not provided, uses in-memory cache (not suitable for production).
77
+ *
78
+ * For production, implement storage with Redis, database, or other distributed cache.
79
+ *
80
+ * @example
81
+ * Full implementation with Redis:
82
+ * ```typescript
83
+ * import { StateHandler, StateData } from '@vunexa/lixa';
84
+ *
85
+ * const stateHandler: StateHandler = {
86
+ * GenerateState: async (provider) => {
87
+ * const state = generateSecureRandomString(32);
88
+ * const codeVerifier = generateSecureRandomString(64);
89
+ * return {
90
+ * state,
91
+ * data: {
92
+ * provider,
93
+ * codeVerifier,
94
+ * createdAt: Date.now()
95
+ * }
96
+ * };
97
+ * },
98
+ *
99
+ * storage: {
100
+ * saveState: async (state, data, expiresInSeconds) => {
101
+ * await redis.setex(`oauth:state:${state}`, expiresInSeconds, JSON.stringify(data));
102
+ * },
103
+ * getState: async (state) => {
104
+ * const data = await redis.get(`oauth:state:${state}`);
105
+ * return data ? JSON.parse(data) : null;
106
+ * },
107
+ * deleteState: async (state) => {
108
+ * await redis.del(`oauth:state:${state}`);
109
+ * }
110
+ * }
111
+ * };
112
+ * ```
113
+ *
114
+ * @example
115
+ * Minimal implementation (uses defaults):
116
+ * ```typescript
117
+ * const stateHandler: StateHandler = {
118
+ * storage: {
119
+ * saveState: async (state, data, expiresInSeconds) => {
120
+ * await redis.setex(state, expiresInSeconds, JSON.stringify(data));
121
+ * },
122
+ * getState: async (state) => {
123
+ * const data = await redis.get(state);
124
+ * return data ? JSON.parse(data) : null;
125
+ * },
126
+ * deleteState: async (state) => {
127
+ * await redis.del(state);
128
+ * }
129
+ * }
130
+ * };
131
+ * ```
132
+ *
133
+ * @public
134
+ */
135
+ export interface StateHandler {
136
+ /**
137
+ * Generates OAuth state parameter and associated data.
138
+ *
139
+ * @param provider - The provider name for callback routing
140
+ * @returns A Promise that resolves to state string and state data
141
+ *
142
+ * @remarks
143
+ * This method generates:
144
+ * - state: A cryptographically secure random string for CSRF protection
145
+ * - codeVerifier: A PKCE code verifier for secure token exchange
146
+ * - createdAt: Timestamp for debugging
147
+ *
148
+ * If not provided, defaults to generating 32-byte hex strings for state
149
+ * and 64-byte hex strings for code verifier.
150
+ *
151
+ * @example
152
+ * ```typescript
153
+ * GenerateState: async (provider) => {
154
+ * const state = crypto.randomBytes(16).toString('hex');
155
+ * const codeVerifier = crypto.randomBytes(32).toString('hex');
156
+ * return {
157
+ * state,
158
+ * data: {
159
+ * provider,
160
+ * codeVerifier,
161
+ * createdAt: Date.now()
162
+ * }
163
+ * };
164
+ * }
165
+ * ```
166
+ */
167
+ generateState?(provider: string): Promise<{
168
+ state: string;
169
+ data: StateData;
170
+ }>;
171
+ /**
172
+ * State storage operations.
173
+ *
174
+ * @remarks
175
+ * Provides methods for saving, retrieving, and deleting OAuth state.
176
+ * All three methods must be implemented together.
177
+ *
178
+ * If not provided, uses in-memory cache (not suitable for production).
179
+ */
180
+ stateStorage?: StateStorage;
181
+ }
182
+ /**
183
+ * Session storage operations interface.
184
+ *
185
+ * @remarks
186
+ * Groups all session storage operations together. All methods must be implemented
187
+ * if this interface is provided.
188
+ *
189
+ * @public
190
+ */
191
+ export interface SessionStorage {
192
+ /**
193
+ * Saves a session with expiration.
194
+ *
195
+ * @param sessionId - Unique session identifier
196
+ * @param session - Session data from GenerateSession()
197
+ * @param expiresInSeconds - TTL in seconds (typically 86400 for 24 hours)
198
+ */
199
+ saveSession<T extends Session>(sessionId: string, session: T, expiresInSeconds: number): Promise<void>;
200
+ /**
201
+ * Retrieves a session by ID.
202
+ *
203
+ * @param sessionId - Unique session identifier
204
+ * @returns Session data or null if not found or expired
205
+ */
206
+ getSession<T extends Session>(sessionId: string): Promise<T | null>;
207
+ /**
208
+ * Deletes a session (e.g., on logout).
209
+ *
210
+ * @param sessionId - Unique session identifier
211
+ */
212
+ deleteSession(sessionId: string): Promise<void>;
213
+ /**
214
+ * Optional helper to retrieve an active session by user email for account linking.
215
+ *
216
+ * @param email - Primary user email
217
+ */
218
+ getSessionByEmail?<T extends Session>(email: string): Promise<{
219
+ sessionId: string;
220
+ session: T;
221
+ } | null>;
222
+ }
223
+ /**
224
+ * Session handler for OAuth authentication.
225
+ *
226
+ * @remarks
227
+ * The SessionHandler manages session generation and storage after successful OAuth authentication.
228
+ *
229
+ * - GenerateSession: Optional. Customizes how OAuth tokens are converted into session data.
230
+ * If not provided, uses default implementation (access token as session token).
231
+ *
232
+ * - storage: Optional. Provides custom session storage (save/get/delete operations).
233
+ * If not provided, uses in-memory cache (not suitable for production).
234
+ *
235
+ * For production, implement both GenerateSession (for user creation/lookup) and storage
236
+ * (for persistent session storage with Redis, database, etc.).
237
+ *
238
+ * @example
239
+ * Full implementation with database:
240
+ * ```typescript
241
+ * import { SessionHandler, Session, OAuthTokenResponse, ProviderMetadata, extractUserInfo } from '@vunexa/lixa';
242
+ *
243
+ * const sessionHandler: SessionHandler = {
244
+ * GenerateSession: async (tokenData, providerMetadata) => {
245
+ * // Extract user info and create/retrieve user
246
+ * const { userInfo } = await extractUserInfo(tokenData, providerMetadata);
247
+ * const user = await db.users.upsert({
248
+ * email: userInfo.email,
249
+ * name: userInfo.name
250
+ * });
251
+ *
252
+ * // Return session data (not stored yet)
253
+ * return {
254
+ * token: tokenData.access_token,
255
+ * raw: {
256
+ * ...tokenData,
257
+ * userId: user.id,
258
+ * provider: providerMetadata.name
259
+ * }
260
+ * };
261
+ * },
262
+ *
263
+ * storage: {
264
+ * saveSession: async (sessionId, session, expiresInSeconds) => {
265
+ * const expiresAt = new Date(Date.now() + expiresInSeconds * 1000);
266
+ * await db.sessions.create({
267
+ * id: sessionId,
268
+ * token: session.token,
269
+ * data: session.raw,
270
+ * expiresAt
271
+ * });
272
+ * },
273
+ *
274
+ * getSession: async (sessionId) => {
275
+ * const record = await db.sessions.findOne({
276
+ * id: sessionId,
277
+ * expiresAt: { $gt: new Date() }
278
+ * });
279
+ * return record ? { token: record.token, raw: record.data } : null;
280
+ * },
281
+ *
282
+ * deleteSession: async (sessionId) => {
283
+ * await db.sessions.delete({ id: sessionId });
284
+ * }
285
+ * }
286
+ * };
287
+ * ```
288
+ *
289
+ * @example
290
+ * Minimal implementation (uses defaults):
291
+ * ```typescript
292
+ * const sessionHandler: SessionHandler = {
293
+ * storage: {
294
+ * saveSession: async (sessionId, session, expiresInSeconds) => {
295
+ * await redis.setex(sessionId, expiresInSeconds, JSON.stringify(session));
296
+ * },
297
+ * getSession: async (sessionId) => {
298
+ * const data = await redis.get(sessionId);
299
+ * return data ? JSON.parse(data) : null;
300
+ * },
301
+ * deleteSession: async (sessionId) => {
302
+ * await redis.del(sessionId);
303
+ * }
304
+ * }
305
+ * };
306
+ * ```
307
+ *
308
+ * @public
309
+ */
310
+ export interface SessionHandler {
311
+ /**
312
+ * Generates session data from OAuth token data.
313
+ *
314
+ * @param tokenData - The token data received from the OAuth provider's token endpoint
315
+ * @param providerMetadata - Provider metadata including name and endpoints
316
+ * @returns A Promise that resolves to session data
317
+ *
318
+ * @remarks
319
+ * This method is responsible for creating session data from OAuth tokens.
320
+ * It is called after successfully exchanging the authorization code for tokens.
321
+ *
322
+ * Token Data:
323
+ * - access_token: OAuth access token
324
+ * - refresh_token: OAuth refresh token (optional)
325
+ * - expires_in: Token expiration time in seconds
326
+ * - token_type: Token type (usually "Bearer")
327
+ * - id_token: OpenID Connect ID token (for OIDC providers)
328
+ * - scope: Granted scopes
329
+ *
330
+ * Provider Metadata:
331
+ * - name: The provider name (e.g., 'google', 'github')
332
+ * - endpoints: Provider endpoints (authorization, token, userInfo)
333
+ *
334
+ * Your implementation should:
335
+ * 1. Extract user info (using extractUserInfo or decode ID token)
336
+ * 2. Create or lookup users in your database
337
+ * 3. Build and return session data with any custom fields
338
+ *
339
+ * Note: This method should NOT store the session. Storage is handled by the storage object.
340
+ *
341
+ * If not provided, defaults to using the access token as the session token.
342
+ *
343
+ * @example
344
+ * ```typescript
345
+ * GenerateSession: async (tokenData, providerMetadata) => {
346
+ * const { userInfo } = await extractUserInfo(tokenData, providerMetadata);
347
+ * const user = await db.users.upsert({ email: userInfo.email });
348
+ *
349
+ * return {
350
+ * token: tokenData.access_token,
351
+ * raw: {
352
+ * ...tokenData,
353
+ * userId: user.id,
354
+ * provider: providerMetadata.name
355
+ * }
356
+ * };
357
+ * }
358
+ * ```
359
+ */
360
+ generateSession?<T extends Session>(tokenData: import('../models/session').OAuthTokenResponse, providerMetadata: import('../models/session').ProviderMetadata): Promise<T>;
361
+ /**
362
+ * Session storage operations.
363
+ *
364
+ * @remarks
365
+ * Provides methods for saving, retrieving, and deleting sessions.
366
+ * All three methods must be implemented together.
367
+ *
368
+ * If not provided, uses in-memory cache (not suitable for production).
369
+ */
370
+ sessionStorage?: SessionStorage;
371
+ /**
372
+ * Optional method to generate session data from OAuth tokens.
373
+ *
374
+ * @remarks
375
+ * If not provided, uses default implementation from LocalSessionHandler.
376
+ */
377
+ generateSession?<T extends Session>(tokenData: import('../models/session').OAuthTokenResponse, providerMetadata: import('../models/session').ProviderMetadata): Promise<T>;
378
+ }
6
379
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/dao/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IAC7C,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/dao/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD;;;;;;;;;GASG;AACH,MAAM,WAAW,SAAS;IACxB;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;;;;OAMG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;;OAMG;IACH,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnF;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IAEnD;;;;OAIG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoEG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACH,aAAa,CAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;IAE9E;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;;OAMG;IACH,WAAW,CAAC,CAAC,SAAS,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvG;;;;;OAKG;IACH,UAAU,CAAC,CAAC,SAAS,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAEpE;;;;OAIG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhD;;;;OAIG;IACH,iBAAiB,CAAC,CAAC,CAAC,SAAS,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,CAAC,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;CACzG;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsFG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgDG;IACH,eAAe,CAAC,CAAC,CAAC,SAAS,OAAO,EAChC,SAAS,EAAE,OAAO,mBAAmB,EAAE,kBAAkB,EACzD,gBAAgB,EAAE,OAAO,mBAAmB,EAAE,gBAAgB,GAC7D,OAAO,CAAC,CAAC,CAAC,CAAC;IAEd;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAEhC;;;;;OAKG;IACH,eAAe,CAAC,CAAC,CAAC,SAAS,OAAO,EAChC,SAAS,EAAE,OAAO,mBAAmB,EAAE,kBAAkB,EACzD,gBAAgB,EAAE,OAAO,mBAAmB,EAAE,gBAAgB,GAC7D,OAAO,CAAC,CAAC,CAAC,CAAC;CACf"}