@vunexa/lixa 0.0.1-alpha.3

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) [2025] [@vunexa/lixa]
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,240 @@
1
+ # @vunexa/lixa
2
+
3
+ > Package is in very early stage and can have frequent breaking changes. DO NOT USE it for production
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@vunexa/lixa.svg)](https://www.npmjs.com/package/@vunexa/lixa)
6
+ [![npm downloads](https://img.shields.io/npm/dm/@vunexa/lixa.svg)](https://www.npmjs.com/package/@vunexa/lixa)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
+
9
+ A flexible, provider-agnostic OAuth 2.0 and OpenID Connect (OIDC) client library for backend applications.
10
+ @vunexa/lixa simplifies multi-provider authentication flows (e.g., Google, GitHub), supports extensible session management, and enables custom provider registration.
11
+
12
+ ---
13
+
14
+ ## Features
15
+
16
+ - Multi-provider OAuth/OIDC support with unified API
17
+ - Built-in support for popular providers like Google and GitHub
18
+ - Custom provider registration with extensible provider interface
19
+ - Extensible session management via pluggable strategies
20
+ - PKCE (Proof Key for Code Exchange) support
21
+ - TypeScript-first with strong typing and async/await support
22
+ - 100% test coverage with comprehensive error handling
23
+
24
+ ---
25
+
26
+ ## Installation
27
+
28
+ ```bash
29
+ npm install @vunexa/lixa
30
+ # or
31
+ yarn add @vunexa/lixa
32
+ ```
33
+
34
+ ## Quick Start
35
+
36
+ ### 1. Configure lixa with multiple providers
37
+
38
+ ```typescript
39
+ import { Lixa } from '@vunexa/lixa';
40
+
41
+ const lixa = new Lixa({
42
+ providers: {
43
+ google: {
44
+ clientId: process.env.GOOGLE_CLIENT_ID!,
45
+ clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
46
+ redirectUri: 'https://yourapp.com/auth/google/callback',
47
+ scopes: ['openid', 'email', 'profile'],
48
+ extraConfig: {
49
+ prompt: 'consent',
50
+ access_type: 'offline',
51
+ },
52
+ },
53
+ github: {
54
+ clientId: process.env.GITHUB_CLIENT_ID!,
55
+ clientSecret: process.env.GITHUB_CLIENT_SECRET!,
56
+ redirectUri: 'https://yourapp.com/auth/github/callback',
57
+ scopes: ['read:user', 'user:email'],
58
+ extraConfig: {},
59
+ },
60
+ },
61
+
62
+ // Optional: custom session strategy
63
+ sessionStrategy: {
64
+ createSession: async (tokenData) => {
65
+ // Custom session creation logic
66
+ return {
67
+ token: 'custom-session-token',
68
+ raw: tokenData
69
+ };
70
+ }
71
+ },
72
+ });
73
+ ```
74
+
75
+ ### 2. Redirect users to the provider's authorization URL
76
+
77
+ ```typescript
78
+ app.get("/login", (req, res) => {
79
+ const provider = req.query.provider as string; // 'google' or 'github'
80
+ const state = lixa.generateRandomState();
81
+
82
+ // Store state in session for validation
83
+ req.session.oauthState = state;
84
+
85
+ const authUrl = lixa.getAuthUrl(provider.toUpperCase(), state);
86
+ res.redirect(authUrl);
87
+ });
88
+ ```
89
+
90
+ ### 3. Handle the provider callback and establish a session
91
+
92
+ ```typescript
93
+ app.get("/auth/:provider/callback", async (req, res) => {
94
+ const { code, state } = req.query;
95
+ const provider = req.params.provider;
96
+
97
+ try {
98
+ // Validate state parameter
99
+ if (state !== req.session.oauthState) {
100
+ throw new Error('Invalid state parameter');
101
+ }
102
+
103
+ const session = await lixa.handleCallback({
104
+ provider,
105
+ code: code as string,
106
+ state: state as string,
107
+ });
108
+
109
+ // Session established
110
+ res.cookie("session_token", session.token, {
111
+ httpOnly: true,
112
+ secure: true,
113
+ sameSite: 'strict'
114
+ });
115
+
116
+ res.redirect("/dashboard");
117
+ } catch (error) {
118
+ console.error("Authentication error:", error);
119
+ res.status(500).send("Authentication failed");
120
+ }
121
+ });
122
+ ```
123
+
124
+ ## Advanced Usage
125
+
126
+ ### Custom Provider Registration
127
+
128
+ You can register custom OAuth providers by implementing the `IProvider` interface:
129
+
130
+ ```typescript
131
+ import { Lixa, IProvider } from '@vunexa/lixa';
132
+
133
+ class CustomProvider implements IProvider {
134
+ authorizationEndpoint = 'https://custom-provider.com/oauth/authorize';
135
+ tokenEndpoint = 'https://custom-provider.com/oauth/token';
136
+ userInfoEndpoint = 'https://custom-provider.com/api/user';
137
+ }
138
+
139
+ // Register the custom provider
140
+ Lixa.registerProvider({
141
+ custom: new CustomProvider()
142
+ });
143
+
144
+ // Use it in your configuration
145
+ const lixa = new Lixa({
146
+ providers: {
147
+ custom: {
148
+ clientId: 'your-client-id',
149
+ clientSecret: 'your-client-secret',
150
+ redirectUri: 'https://yourapp.com/auth/custom/callback',
151
+ scopes: ['read:user'],
152
+ }
153
+ }
154
+ });
155
+ ```
156
+
157
+ ### Check Provider Registration
158
+
159
+ ```typescript
160
+ // Check if a provider is registered
161
+ if (Lixa.isProviderRegistered('google')) {
162
+ console.log('Google provider is available');
163
+ }
164
+ ```
165
+
166
+ ## API Reference
167
+
168
+ ### `Lixa` Class
169
+
170
+ #### Constructor
171
+ - `new Lixa(config: LixaConfig)` - Creates a new Lixa instance
172
+
173
+ #### Static Methods
174
+ - `Lixa.registerProvider(providerMap: { [key: string]: IProvider })` - Register custom providers
175
+ - `Lixa.isProviderRegistered(provider: string): boolean` - Check if a provider is registered
176
+
177
+ #### Instance Methods
178
+ - `generateRandomState(): string` - Generate a random state parameter for OAuth flow
179
+ - `getAuthUrl(provider: string, state: string): string` - Get authorization URL for a provider
180
+ - `handleCallback({ provider, code, state }): Promise<Session>` - Handle OAuth callback and create session
181
+
182
+ ### Types
183
+
184
+ ```typescript
185
+ interface ProviderConfig {
186
+ clientId: string;
187
+ clientSecret: string;
188
+ redirectUri: string;
189
+ scopes: string[];
190
+ extraConfig?: Record<string, any>;
191
+ }
192
+
193
+ interface LixaConfig {
194
+ providers: Record<string, ProviderConfig>;
195
+ sessionStrategy?: SessionStrategy;
196
+ }
197
+
198
+ interface SessionStrategy {
199
+ createSession(userInfo: any): Promise<Session>;
200
+ }
201
+
202
+ interface Session {
203
+ token: string;
204
+ raw: any;
205
+ }
206
+
207
+ interface IProvider {
208
+ authorizationEndpoint: string;
209
+ tokenEndpoint: string;
210
+ userInfoEndpoint: string;
211
+ }
212
+ ```
213
+
214
+ ## Built-in Providers
215
+
216
+ - **Google** - OAuth 2.0 and OpenID Connect
217
+ - **GitHub** - OAuth 2.0
218
+
219
+ ## Development
220
+
221
+ ```bash
222
+ # Install dependencies
223
+ npm install
224
+
225
+ # Run tests
226
+ npm test
227
+
228
+ # Run tests with coverage
229
+ npm run test:coverage
230
+
231
+ # Build the library
232
+ npm run build
233
+
234
+ # Lint code
235
+ npm run lint
236
+ ```
237
+
238
+ ## License
239
+
240
+ MIT
@@ -0,0 +1,3 @@
1
+ export { Lixa } from "./lixa";
2
+ export { type ProviderConfig, type LixaConfig, type SessionStrategy, type Session, } from "./types";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,OAAO,GACb,MAAM,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { Lixa } from "./lixa";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC"}
package/dist/lixa.d.ts ADDED
@@ -0,0 +1,25 @@
1
+ import { type LixaConfig, type Session } from "./types";
2
+ import { IProvider } from "./providers";
3
+ /**
4
+ * @public
5
+ */
6
+ declare class Lixa {
7
+ private static CONFIGURED_PROVIDERS;
8
+ private config;
9
+ constructor(config: LixaConfig);
10
+ static isProviderRegistered(provider: string): boolean;
11
+ static registerProvider(providerMap: {
12
+ [key: string]: IProvider;
13
+ }): void;
14
+ generateRandomState(): string;
15
+ getAuthUrl(provider: string, state: string): string;
16
+ handleCallback({ provider, code, state, }: {
17
+ provider: string;
18
+ code: string;
19
+ state?: string;
20
+ }): Promise<Session>;
21
+ private exchangeCodeForToken;
22
+ private findProviderByType;
23
+ }
24
+ export { Lixa };
25
+ //# sourceMappingURL=lixa.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lixa.d.ts","sourceRoot":"","sources":["../src/lixa.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,UAAU,EAAuB,KAAK,OAAO,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,SAAS,EAAkC,MAAM,aAAa,CAAC;AAGxE;;GAEG;AACH,cAAM,IAAI;IACR,OAAO,CAAC,MAAM,CAAC,oBAAoB,CAAqC;IACxE,OAAO,CAAC,MAAM,CAAa;gBAEf,MAAM,EAAE,UAAU;WAUhB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;WAI/C,gBAAgB,CAAC,WAAW,EAAE;QAC1C,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;KAC1B,GAAG,IAAI;IAQD,mBAAmB,IAAI,MAAM;IAI7B,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IAqB7C,cAAc,CAAC,EAC1B,QAAQ,EACR,IAAI,EACJ,KAAK,GACN,EAAE;QACD,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,OAAO,CAAC,OAAO,CAAC;YAuCN,oBAAoB;IAsClC,OAAO,CAAC,kBAAkB;CAG3B;AAED,OAAO,EAAE,IAAI,EAAE,CAAC"}
package/dist/lixa.js ADDED
@@ -0,0 +1,107 @@
1
+ import { randomBytes } from "crypto";
2
+ import { GithubProvider, GoogleProvider } from "./providers";
3
+ import { GITHUB, GOOGLE } from "./utils/constants";
4
+ /**
5
+ * @public
6
+ */
7
+ class Lixa {
8
+ static CONFIGURED_PROVIDERS = new Map();
9
+ config;
10
+ constructor(config) {
11
+ this.config = config;
12
+ if (!Lixa.CONFIGURED_PROVIDERS.has(GITHUB)) {
13
+ Lixa.CONFIGURED_PROVIDERS.set(GITHUB, new GithubProvider());
14
+ }
15
+ if (!Lixa.CONFIGURED_PROVIDERS.has(GOOGLE)) {
16
+ Lixa.CONFIGURED_PROVIDERS.set(GOOGLE, new GoogleProvider());
17
+ }
18
+ }
19
+ static isProviderRegistered(provider) {
20
+ return Lixa.CONFIGURED_PROVIDERS.has(provider.toLowerCase());
21
+ }
22
+ static registerProvider(providerMap) {
23
+ // This is a static method, so we can't access instance properties.
24
+ // Instead, we can modify the prototype to add the new provider.
25
+ Object.entries(providerMap).forEach(([key, providerImpl]) => {
26
+ Lixa.CONFIGURED_PROVIDERS.set(key, providerImpl);
27
+ });
28
+ }
29
+ generateRandomState() {
30
+ return randomBytes(16).toString("hex");
31
+ }
32
+ getAuthUrl(provider, state) {
33
+ const providerType = provider.toLowerCase();
34
+ const providerConfig = this.findProviderByType(providerType);
35
+ const providerImpl = Lixa.CONFIGURED_PROVIDERS.get(providerType);
36
+ if (!providerConfig || !providerImpl) {
37
+ throw new Error(`Provider ${providerType} not configured`);
38
+ }
39
+ const params = new URLSearchParams({
40
+ client_id: providerConfig.clientId,
41
+ redirect_uri: providerConfig.redirectUri,
42
+ scope: providerConfig.scopes.join(" "),
43
+ state,
44
+ response_type: "code",
45
+ ...providerConfig.extraConfig,
46
+ });
47
+ return `${providerImpl.authorizationEndpoint}?${params.toString()}`;
48
+ }
49
+ async handleCallback({ provider, code, state, }) {
50
+ if (!code || code.trim() === "") {
51
+ throw new Error("Invalid or missing code in callback");
52
+ }
53
+ if (!state || state.trim() === "") {
54
+ throw new Error("Invalid or missing state in callback");
55
+ }
56
+ //TODO: Validate state here
57
+ const providerConfig = this.findProviderByType(provider.toLowerCase());
58
+ const providerImpl = Lixa.CONFIGURED_PROVIDERS.get(provider);
59
+ if (!providerConfig || !providerImpl) {
60
+ throw new Error(`Provider ${provider} not configured`);
61
+ }
62
+ // Exchange code for tokens and fetch user info here.
63
+ const tokens = await this.exchangeCodeForToken(code, providerConfig, providerImpl);
64
+ // For simplicity, we'll just return the tokens as the session.
65
+ // In a real implementation, you'd fetch user info and create a session.
66
+ const session = {
67
+ token: tokens.access_token,
68
+ raw: tokens, // Replace with actual user info
69
+ };
70
+ // If a session strategy is provided, use it to create a session.
71
+ if (this.config.sessionStrategy) {
72
+ return this.config.sessionStrategy.createSession(session.raw);
73
+ }
74
+ return session;
75
+ }
76
+ async exchangeCodeForToken(code, providerConfig, providerImpl, codeVerifier) {
77
+ // Build the request body
78
+ const body = {
79
+ client_id: providerConfig.clientId,
80
+ client_secret: providerConfig.clientSecret,
81
+ code,
82
+ redirect_uri: providerConfig.redirectUri,
83
+ grant_type: "authorization_code",
84
+ };
85
+ if (codeVerifier) {
86
+ body.code_verifier = codeVerifier;
87
+ }
88
+ const params = new URLSearchParams(body);
89
+ const response = await fetch(providerImpl.tokenEndpoint, {
90
+ method: "POST",
91
+ headers: {
92
+ "Content-Type": "application/x-www-form-urlencoded",
93
+ Accept: "application/json",
94
+ },
95
+ body: params.toString(),
96
+ });
97
+ if (!response.ok) {
98
+ throw new Error(`Token exchange failed: ${response.status} ${response.statusText}`);
99
+ }
100
+ return response.json();
101
+ }
102
+ findProviderByType(providerType) {
103
+ return this.config.providers[providerType];
104
+ }
105
+ }
106
+ export { Lixa };
107
+ //# sourceMappingURL=lixa.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lixa.js","sourceRoot":"","sources":["../src/lixa.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ interface IProvider {
2
+ authorizationEndpoint: string;
3
+ tokenEndpoint: string;
4
+ userInfoEndpoint: string;
5
+ }
6
+ export { IProvider };
7
+ //# sourceMappingURL=IProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IProvider.d.ts","sourceRoot":"","sources":["../../src/providers/IProvider.ts"],"names":[],"mappings":"AAEA,UAAU,SAAS;IACjB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,OAAO,EAAE,SAAS,EAAE,CAAC"}
@@ -0,0 +1,3 @@
1
+ // Implement an extandable interface for authentication providers
2
+ export {};
3
+ //# sourceMappingURL=IProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IProvider.js","sourceRoot":"","sources":["../../src/providers/IProvider.ts"],"names":[],"mappings":"AAAA,iEAAiE"}
@@ -0,0 +1,9 @@
1
+ import { IProvider } from "./IProvider";
2
+ declare class GithubProvider implements IProvider {
3
+ providerType: string;
4
+ authorizationEndpoint: string;
5
+ tokenEndpoint: string;
6
+ userInfoEndpoint: string;
7
+ }
8
+ export { GithubProvider };
9
+ //# sourceMappingURL=github.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/providers/github.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,cAAM,cAAe,YAAW,SAAS;IACvC,YAAY,SAAY;IACxB,qBAAqB,SAA8C;IACnE,aAAa,SAAiD;IAC9D,gBAAgB,SAAiC;CAClD;AAED,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,8 @@
1
+ class GithubProvider {
2
+ providerType = "GITHUB";
3
+ authorizationEndpoint = "https://github.com/login/oauth/authorize";
4
+ tokenEndpoint = "https://github.com/login/oauth/access_token";
5
+ userInfoEndpoint = "https://api.github.com/user";
6
+ }
7
+ export { GithubProvider };
8
+ //# sourceMappingURL=github.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/providers/github.ts"],"names":[],"mappings":"AAEA,MAAM,cAAc;IAClB,YAAY,GAAG,QAAQ,CAAC;IACxB,qBAAqB,GAAG,0CAA0C,CAAC;IACnE,aAAa,GAAG,6CAA6C,CAAC;IAC9D,gBAAgB,GAAG,6BAA6B,CAAC;CAClD;AAED,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { IProvider } from "./IProvider";
2
+ declare class GoogleProvider implements IProvider {
3
+ providerType: string;
4
+ authorizationEndpoint: string;
5
+ tokenEndpoint: string;
6
+ userInfoEndpoint: string;
7
+ }
8
+ export { GoogleProvider };
9
+ //# sourceMappingURL=google.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"google.d.ts","sourceRoot":"","sources":["../../src/providers/google.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,cAAM,cAAe,YAAW,SAAS;IACvC,YAAY,SAAY;IACxB,qBAAqB,SAAkD;IACvE,aAAa,SAAyC;IACtD,gBAAgB,SAAmD;CACpE;AAED,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,8 @@
1
+ class GoogleProvider {
2
+ providerType = "GOOGLE";
3
+ authorizationEndpoint = "https://accounts.google.com/o/oauth2/v2/auth";
4
+ tokenEndpoint = "https://oauth2.googleapis.com/token";
5
+ userInfoEndpoint = "https://www.googleapis.com/oauth2/v2/userinfo";
6
+ }
7
+ export { GoogleProvider };
8
+ //# sourceMappingURL=google.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"google.js","sourceRoot":"","sources":["../../src/providers/google.ts"],"names":[],"mappings":"AAEA,MAAM,cAAc;IAClB,YAAY,GAAG,QAAQ,CAAC;IACxB,qBAAqB,GAAG,8CAA8C,CAAC;IACvE,aAAa,GAAG,qCAAqC,CAAC;IACtD,gBAAgB,GAAG,+CAA+C,CAAC;CACpE;AAED,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { IProvider } from "./IProvider";
2
+ export { GithubProvider } from "./github";
3
+ export { GoogleProvider } from "./google";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { GithubProvider } from "./github";
2
+ export { GoogleProvider } from "./google";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @public
3
+ */
4
+ export interface ProviderConfig {
5
+ clientId: string;
6
+ clientSecret: string;
7
+ redirectUri: string;
8
+ scopes: string[];
9
+ extraConfig?: Record<string, any>;
10
+ }
11
+ /**
12
+ * @public
13
+ */
14
+ export interface LixaConfig {
15
+ providers: Record<string, ProviderConfig>;
16
+ sessionStrategy?: SessionStrategy;
17
+ }
18
+ /**
19
+ * @public
20
+ */
21
+ export interface SessionStrategy {
22
+ createSession(userInfo: any): Promise<Session>;
23
+ }
24
+ /**
25
+ * @public
26
+ */
27
+ export interface Session {
28
+ token: string;
29
+ raw: any;
30
+ }
31
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC1C,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,aAAa,CAAC,QAAQ,EAAE,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAChD;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,GAAG,CAAC;CACV"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ declare const GOOGLE = "google";
2
+ declare const GITHUB = "github";
3
+ export { GOOGLE, GITHUB };
4
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/utils/constants.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,MAAM,WAAW,CAAC;AACxB,QAAA,MAAM,MAAM,WAAW,CAAC;AAExB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC"}
@@ -0,0 +1,4 @@
1
+ const GOOGLE = "google";
2
+ const GITHUB = "github";
3
+ export { GOOGLE, GITHUB };
4
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/utils/constants.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,GAAG,QAAQ,CAAC;AACxB,MAAM,MAAM,GAAG,QAAQ,CAAC;AAExB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC"}
package/index.d.ts ADDED
@@ -0,0 +1,63 @@
1
+ declare interface IProvider {
2
+ authorizationEndpoint: string;
3
+ tokenEndpoint: string;
4
+ userInfoEndpoint: string;
5
+ }
6
+
7
+ /**
8
+ * @public
9
+ */
10
+ export declare class Lixa {
11
+ private static CONFIGURED_PROVIDERS;
12
+ private config;
13
+ constructor(config: LixaConfig);
14
+ static isProviderRegistered(provider: string): boolean;
15
+ static registerProvider(providerMap: {
16
+ [key: string]: IProvider;
17
+ }): void;
18
+ generateRandomState(): string;
19
+ getAuthUrl(provider: string, state: string): string;
20
+ handleCallback({ provider, code, state, }: {
21
+ provider: string;
22
+ code: string;
23
+ state?: string;
24
+ }): Promise<Session>;
25
+ private exchangeCodeForToken;
26
+ private findProviderByType;
27
+ }
28
+
29
+ /**
30
+ * @public
31
+ */
32
+ export declare interface LixaConfig {
33
+ providers: Record<string, ProviderConfig>;
34
+ sessionStrategy?: SessionStrategy;
35
+ }
36
+
37
+ /**
38
+ * @public
39
+ */
40
+ export declare interface ProviderConfig {
41
+ clientId: string;
42
+ clientSecret: string;
43
+ redirectUri: string;
44
+ scopes: string[];
45
+ extraConfig?: Record<string, any>;
46
+ }
47
+
48
+ /**
49
+ * @public
50
+ */
51
+ export declare interface Session {
52
+ token: string;
53
+ raw: any;
54
+ }
55
+
56
+ /**
57
+ * @public
58
+ */
59
+ export declare interface SessionStrategy {
60
+ createSession(userInfo: any): Promise<Session>;
61
+ }
62
+
63
+ export { }
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@vunexa/lixa",
3
+ "version": "0.0.1-alpha.3",
4
+ "description": "Lixa is a flexible, provider-agnostic OAuth and OpenID Connect (OIDC) client library that simplifies multi-provider authentication flows. It supports seamless integration with providers like Google and GitHub, offers extensible session management, and enables dynamic provider resolution based on callback URLs.",
5
+ "keywords": [
6
+ "oauth",
7
+ "oidc"
8
+ ],
9
+ "license": "MIT",
10
+ "author": "vamsi",
11
+ "type": "module",
12
+ "main": "dist/index.js",
13
+ "types": "index.d.ts",
14
+ "exports": {
15
+ ".": {
16
+ "types": "./index.d.ts",
17
+ "import": "./dist/index.js"
18
+ }
19
+ },
20
+ "scripts": {
21
+ "build": "tsc && npm run test && api-extractor run --local",
22
+ "clean": "rm -rf dist",
23
+ "prepublishOnly": "npm run clean && npm run build",
24
+ "lint": "eslint src/**/*.ts",
25
+ "lint:fix": "eslint src/**/*.ts --fix",
26
+ "test": "jest",
27
+ "test:watch": "jest --watch",
28
+ "test:coverage": "jest --coverage",
29
+ "api-extractor": "api-extractor run --local --verbose",
30
+ "publish:alpha": "npm run build && npm version prerelease --preid=alpha && npm publish --tag alpha",
31
+ "publish:beta": "npm run build && npm version prerelease --preid=beta && npm publish --tag beta",
32
+ "publish:stable": "npm run build && npm version patch && npm publish --tag latest"
33
+ },
34
+ "files": [
35
+ "dist",
36
+ "index.d.ts",
37
+ "README.md",
38
+ "LICENSE"
39
+ ],
40
+ "devDependencies": {
41
+ "@eslint/js": "^9.35.0",
42
+ "@microsoft/api-extractor": "^7.52.11",
43
+ "@types/jest": "^29.5.12",
44
+ "@types/node": "^24.3.1",
45
+ "@typescript-eslint/eslint-plugin": "^8.42.0",
46
+ "@typescript-eslint/parser": "^8.42.0",
47
+ "eslint": "^9.35.0",
48
+ "globals": "^16.3.0",
49
+ "jest": "^29.7.0",
50
+ "ts-jest": "^29.1.2",
51
+ "typescript": "^5.9.2"
52
+ }
53
+ }