@lanonasis/oauth-client 2.0.0 → 2.0.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/README.md +164 -15
- package/dist/{api-key-storage-web-J3W8nQi2.d.cts → api-key-storage-web-DUyiN9mC.d.cts} +11 -5
- package/dist/{api-key-storage-web-J3W8nQi2.d.ts → api-key-storage-web-DUyiN9mC.d.ts} +11 -5
- package/dist/browser.d.cts +2 -2
- package/dist/browser.d.ts +2 -2
- package/dist/{constants-BOZ6jJU4.d.cts → constants-BZPTHasL.d.cts} +1 -1
- package/dist/{constants-BOZ6jJU4.d.ts → constants-BZPTHasL.d.ts} +1 -1
- package/dist/index.cjs +61 -38
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +61 -38
- package/dist/react/index.d.cts +2 -2
- package/dist/react/index.d.ts +2 -2
- package/dist/server/index.d.cts +2 -2
- package/dist/server/index.d.ts +2 -2
- package/package.json +42 -16
package/README.md
CHANGED
|
@@ -1,16 +1,32 @@
|
|
|
1
1
|
# @lanonasis/oauth-client
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**THE single authentication package** for the Lanonasis ecosystem. Consolidates all auth patterns: OAuth2 PKCE, API keys, magic links, React hooks, and Express middleware.
|
|
4
|
+
|
|
5
|
+
> **v2.0**: Now includes `/react` and `/server` exports! Migrating from `@lanonasis/shared-auth`? See [Migration Guide](#migration-from-lanonasisshared-auth).
|
|
4
6
|
|
|
5
7
|
## Features
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
|
|
9
|
+
### Core Authentication
|
|
10
|
+
- **OAuth2 PKCE Flow**: Terminal and desktop (Electron) environments
|
|
11
|
+
- **API Key Authentication**: Dashboard-generated keys for instant access
|
|
12
|
+
- **Magic Link / OTP Flow**: Passwordless email authentication
|
|
13
|
+
- **Token Storage**: Secure backends (Keytar, encrypted files, WebCrypto)
|
|
14
|
+
|
|
15
|
+
### React Integration (`/react`)
|
|
16
|
+
- **`useSSO()`**: React hook for SSO authentication state
|
|
17
|
+
- **`useSSOSync()`**: Cross-subdomain session synchronization
|
|
18
|
+
- **Cookie utilities**: `parseUserCookie`, `hasSessionCookie`, `clearUserCookie`
|
|
19
|
+
|
|
20
|
+
### Server Integration (`/server`)
|
|
21
|
+
- **`requireAuth()`**: Express middleware enforcing authentication
|
|
22
|
+
- **`optionalAuth()`**: Attach user if authenticated, allow anonymous
|
|
23
|
+
- **`requireRole(role)`**: Role-based access control middleware
|
|
24
|
+
- **Cookie parsing**: `getSSOUserFromRequest`, `getSessionTokenFromRequest`
|
|
25
|
+
|
|
26
|
+
### Additional Features
|
|
27
|
+
- MCP client (WebSocket/SSE) with auto-refreshing tokens
|
|
28
|
+
- ESM + CJS bundles with dedicated browser export
|
|
29
|
+
- TypeScript types included
|
|
14
30
|
|
|
15
31
|
## Installation
|
|
16
32
|
```bash
|
|
@@ -76,6 +92,82 @@ const flow = new DesktopOAuthFlow({
|
|
|
76
92
|
const tokens = await flow.authenticate();
|
|
77
93
|
```
|
|
78
94
|
|
|
95
|
+
### Magic Link / OTP Flow (Passwordless)
|
|
96
|
+
```ts
|
|
97
|
+
import { MagicLinkFlow } from '@lanonasis/oauth-client';
|
|
98
|
+
|
|
99
|
+
const flow = new MagicLinkFlow({
|
|
100
|
+
authBaseUrl: 'https://auth.lanonasis.com'
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// Send OTP to user's email
|
|
104
|
+
await flow.sendOTP('user@example.com');
|
|
105
|
+
|
|
106
|
+
// User enters the code they received
|
|
107
|
+
const tokens = await flow.verifyOTP('user@example.com', '123456');
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### React Hooks (`/react`)
|
|
111
|
+
```tsx
|
|
112
|
+
import { useSSO, useSSOSync } from '@lanonasis/oauth-client/react';
|
|
113
|
+
|
|
114
|
+
function MyComponent() {
|
|
115
|
+
const { user, isAuthenticated, isLoading, error } = useSSO({
|
|
116
|
+
authGatewayUrl: 'https://auth.lanonasis.com',
|
|
117
|
+
projectScope: 'my-app'
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
if (isLoading) return <div>Loading...</div>;
|
|
121
|
+
if (!isAuthenticated) return <div>Please log in</div>;
|
|
122
|
+
|
|
123
|
+
return <div>Hello, {user.email}!</div>;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// For cross-subdomain session sync
|
|
127
|
+
function App() {
|
|
128
|
+
useSSOSync({ pollInterval: 30000 });
|
|
129
|
+
return <MyComponent />;
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Server Middleware (`/server`)
|
|
134
|
+
```ts
|
|
135
|
+
import express from 'express';
|
|
136
|
+
import {
|
|
137
|
+
requireAuth,
|
|
138
|
+
optionalAuth,
|
|
139
|
+
requireRole,
|
|
140
|
+
getSSOUserFromRequest
|
|
141
|
+
} from '@lanonasis/oauth-client/server';
|
|
142
|
+
|
|
143
|
+
const app = express();
|
|
144
|
+
|
|
145
|
+
// Require authentication
|
|
146
|
+
app.get('/api/profile', requireAuth(), (req, res) => {
|
|
147
|
+
res.json({ user: req.user });
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// Optional authentication (attach user if present)
|
|
151
|
+
app.get('/api/public', optionalAuth(), (req, res) => {
|
|
152
|
+
if (req.user) {
|
|
153
|
+
res.json({ message: `Hello ${req.user.email}` });
|
|
154
|
+
} else {
|
|
155
|
+
res.json({ message: 'Hello guest' });
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// Role-based access control
|
|
160
|
+
app.delete('/api/admin/users/:id', requireAuth(), requireRole('admin'), (req, res) => {
|
|
161
|
+
// Only admins can reach here
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// Manual user extraction
|
|
165
|
+
app.get('/api/check', (req, res) => {
|
|
166
|
+
const user = getSSOUserFromRequest(req);
|
|
167
|
+
res.json({ authenticated: !!user });
|
|
168
|
+
});
|
|
169
|
+
```
|
|
170
|
+
|
|
79
171
|
### Token storage
|
|
80
172
|
```ts
|
|
81
173
|
import { TokenStorage } from '@lanonasis/oauth-client';
|
|
@@ -85,15 +177,20 @@ await storage.store(tokens);
|
|
|
85
177
|
const restored = await storage.retrieve();
|
|
86
178
|
```
|
|
87
179
|
|
|
88
|
-
|
|
180
|
+
In Node and Electron environments, secure storage now lazy-loads `keytar` so the ESM bundle can still use the native OS keychain when available. If native keychain access is unavailable, storage falls back to the encrypted local file backend automatically.
|
|
181
|
+
|
|
182
|
+
### API key storage
|
|
89
183
|
```ts
|
|
90
184
|
import { ApiKeyStorage } from '@lanonasis/oauth-client';
|
|
91
185
|
|
|
92
186
|
const apiKeys = new ApiKeyStorage();
|
|
93
187
|
await apiKeys.store({ apiKey: 'lns_abc123', environment: 'production' });
|
|
94
|
-
const
|
|
188
|
+
const apiKey = await apiKeys.getApiKey(); // returns the original key for outbound auth headers
|
|
95
189
|
```
|
|
96
190
|
|
|
191
|
+
Node/Electron secure storage preserves the original secret value so clients can send it back
|
|
192
|
+
in `X-API-Key` or `Authorization` headers when talking to remote services.
|
|
193
|
+
|
|
97
194
|
## Configuration
|
|
98
195
|
|
|
99
196
|
### API Key Mode
|
|
@@ -116,10 +213,11 @@ const hashed = await apiKeys.getApiKey(); // returns sha256 hex digest
|
|
|
116
213
|
- The terminal/device code flow remains Node-only; in browser previews use API key or desktop flow.
|
|
117
214
|
|
|
118
215
|
## Publishing (maintainers)
|
|
119
|
-
1)
|
|
120
|
-
2)
|
|
121
|
-
3)
|
|
122
|
-
4)
|
|
216
|
+
1) Install and verify: `npm install && npm test && npm run build`
|
|
217
|
+
2) Audit release deps: `bun audit`
|
|
218
|
+
3) Verify contents: ensure `dist`, `README.md`, and `LICENSE` are present.
|
|
219
|
+
4) Publish: `npm publish --access public` (registry must have 2FA as configured).
|
|
220
|
+
5) Tag in git (optional): `git tag oauth-client-v2.0.3 && git push --tags`
|
|
123
221
|
|
|
124
222
|
## Files shipped
|
|
125
223
|
- `dist/*` compiled CJS/ESM bundles + types
|
|
@@ -145,5 +243,56 @@ This SDK implements client-side equivalents of the auth-gateway's authentication
|
|
|
145
243
|
|
|
146
244
|
See [auth-gateway/AUTHENTICATION-METHODS.md](../../apps/onasis-core/services/auth-gateway/AUTHENTICATION-METHODS.md) for complete server-side documentation.
|
|
147
245
|
|
|
246
|
+
## Exports
|
|
247
|
+
|
|
248
|
+
| Export | Description | Use Case |
|
|
249
|
+
|--------|-------------|----------|
|
|
250
|
+
| `@lanonasis/oauth-client` | Main entry - OAuth flows, MCP client, storage | Node.js CLI, servers |
|
|
251
|
+
| `@lanonasis/oauth-client/browser` | Browser-safe bundle (no Node deps) | Web apps, SPAs |
|
|
252
|
+
| `@lanonasis/oauth-client/react` | React hooks + browser cookie utils | React/Next.js apps |
|
|
253
|
+
| `@lanonasis/oauth-client/server` | Express middleware + server cookie utils | Express/Node servers |
|
|
254
|
+
|
|
255
|
+
## Migration from @lanonasis/shared-auth
|
|
256
|
+
|
|
257
|
+
`@lanonasis/shared-auth` is now **deprecated**. All functionality has been consolidated into `@lanonasis/oauth-client`.
|
|
258
|
+
|
|
259
|
+
### Import Changes
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
// ❌ BEFORE (deprecated)
|
|
263
|
+
import { useSSO, useSSOSync } from '@lanonasis/shared-auth';
|
|
264
|
+
import { getSSOUserFromRequest } from '@lanonasis/shared-auth/server';
|
|
265
|
+
|
|
266
|
+
// ✅ AFTER (recommended)
|
|
267
|
+
import { useSSO, useSSOSync } from '@lanonasis/oauth-client/react';
|
|
268
|
+
import { getSSOUserFromRequest, requireAuth } from '@lanonasis/oauth-client/server';
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Package.json Changes
|
|
272
|
+
|
|
273
|
+
```json
|
|
274
|
+
{
|
|
275
|
+
"dependencies": {
|
|
276
|
+
// ❌ Remove
|
|
277
|
+
"@lanonasis/shared-auth": "^1.x.x",
|
|
278
|
+
|
|
279
|
+
// ✅ Add/Update
|
|
280
|
+
"@lanonasis/oauth-client": "^2.0.0"
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### New Middleware (Bonus!)
|
|
286
|
+
|
|
287
|
+
The migration gives you access to new middleware that wasn't in shared-auth:
|
|
288
|
+
|
|
289
|
+
```ts
|
|
290
|
+
import { requireAuth, optionalAuth, requireRole } from '@lanonasis/oauth-client/server';
|
|
291
|
+
|
|
292
|
+
// These are new! Replace manual auth checks
|
|
293
|
+
app.get('/api/protected', requireAuth(), handler);
|
|
294
|
+
app.delete('/api/admin/*', requireAuth(), requireRole('admin'), handler);
|
|
295
|
+
```
|
|
296
|
+
|
|
148
297
|
## License
|
|
149
298
|
MIT © Lan Onasis
|
|
@@ -106,7 +106,8 @@ declare class TokenStorage implements TokenStorageAdapter {
|
|
|
106
106
|
private readonly storageKey;
|
|
107
107
|
private readonly webEncryptionKeyStorage;
|
|
108
108
|
private keytar;
|
|
109
|
-
|
|
109
|
+
private keytarLoadAttempted;
|
|
110
|
+
private getKeytar;
|
|
110
111
|
store(tokens: TokenResponse): Promise<void>;
|
|
111
112
|
retrieve(): Promise<TokenResponse | null>;
|
|
112
113
|
clear(): Promise<void>;
|
|
@@ -182,8 +183,9 @@ declare class ApiKeyStorage {
|
|
|
182
183
|
private readonly legacyConfigKey;
|
|
183
184
|
private readonly webEncryptionKeyStorage;
|
|
184
185
|
private keytar;
|
|
186
|
+
private keytarLoadAttempted;
|
|
185
187
|
private migrationCompleted;
|
|
186
|
-
|
|
188
|
+
private getKeytar;
|
|
187
189
|
/**
|
|
188
190
|
* Initialize and migrate from legacy storage if needed
|
|
189
191
|
*/
|
|
@@ -235,8 +237,12 @@ declare class ApiKeyStorage {
|
|
|
235
237
|
private base64Encode;
|
|
236
238
|
private base64Decode;
|
|
237
239
|
/**
|
|
238
|
-
* Normalize
|
|
239
|
-
*
|
|
240
|
+
* Normalize stored credentials without transforming their value.
|
|
241
|
+
*
|
|
242
|
+
* These secrets are stored in encrypted local storage/keychains and must remain
|
|
243
|
+
* usable for outbound authentication headers (for example X-API-Key or Bearer).
|
|
244
|
+
* Hashing here would make the original credential unrecoverable and break
|
|
245
|
+
* clients that need to send the raw key/token back to a remote service.
|
|
240
246
|
*/
|
|
241
247
|
private normalizeApiKey;
|
|
242
248
|
}
|
|
@@ -257,4 +263,4 @@ declare class ApiKeyStorageWeb {
|
|
|
257
263
|
private base64Decode;
|
|
258
264
|
}
|
|
259
265
|
|
|
260
|
-
export {
|
|
266
|
+
export { ApiKeyStorageWeb as A, BaseOAuthFlow as B, DesktopOAuthFlow as D, type GrantType as G, type OAuthConfig as O, type PKCEChallenge as P, type TokenStorageAdapter as T, type AuthError as a, AuthGatewayClient as b, type AuthGatewayClientConfig as c, type AuthTokenType as d, type AuthValidationResult as e, type DeviceCodeResponse as f, type TokenExchangeOptions as g, type TokenExchangeResponse as h, type TokenResponse as i, TokenStorageWeb as j, type ApiKeyData as k, ApiKeyStorage as l, TokenStorage as m };
|
|
@@ -106,7 +106,8 @@ declare class TokenStorage implements TokenStorageAdapter {
|
|
|
106
106
|
private readonly storageKey;
|
|
107
107
|
private readonly webEncryptionKeyStorage;
|
|
108
108
|
private keytar;
|
|
109
|
-
|
|
109
|
+
private keytarLoadAttempted;
|
|
110
|
+
private getKeytar;
|
|
110
111
|
store(tokens: TokenResponse): Promise<void>;
|
|
111
112
|
retrieve(): Promise<TokenResponse | null>;
|
|
112
113
|
clear(): Promise<void>;
|
|
@@ -182,8 +183,9 @@ declare class ApiKeyStorage {
|
|
|
182
183
|
private readonly legacyConfigKey;
|
|
183
184
|
private readonly webEncryptionKeyStorage;
|
|
184
185
|
private keytar;
|
|
186
|
+
private keytarLoadAttempted;
|
|
185
187
|
private migrationCompleted;
|
|
186
|
-
|
|
188
|
+
private getKeytar;
|
|
187
189
|
/**
|
|
188
190
|
* Initialize and migrate from legacy storage if needed
|
|
189
191
|
*/
|
|
@@ -235,8 +237,12 @@ declare class ApiKeyStorage {
|
|
|
235
237
|
private base64Encode;
|
|
236
238
|
private base64Decode;
|
|
237
239
|
/**
|
|
238
|
-
* Normalize
|
|
239
|
-
*
|
|
240
|
+
* Normalize stored credentials without transforming their value.
|
|
241
|
+
*
|
|
242
|
+
* These secrets are stored in encrypted local storage/keychains and must remain
|
|
243
|
+
* usable for outbound authentication headers (for example X-API-Key or Bearer).
|
|
244
|
+
* Hashing here would make the original credential unrecoverable and break
|
|
245
|
+
* clients that need to send the raw key/token back to a remote service.
|
|
240
246
|
*/
|
|
241
247
|
private normalizeApiKey;
|
|
242
248
|
}
|
|
@@ -257,4 +263,4 @@ declare class ApiKeyStorageWeb {
|
|
|
257
263
|
private base64Decode;
|
|
258
264
|
}
|
|
259
265
|
|
|
260
|
-
export {
|
|
266
|
+
export { ApiKeyStorageWeb as A, BaseOAuthFlow as B, DesktopOAuthFlow as D, type GrantType as G, type OAuthConfig as O, type PKCEChallenge as P, type TokenStorageAdapter as T, type AuthError as a, AuthGatewayClient as b, type AuthGatewayClientConfig as c, type AuthTokenType as d, type AuthValidationResult as e, type DeviceCodeResponse as f, type TokenExchangeOptions as g, type TokenExchangeResponse as h, type TokenResponse as i, TokenStorageWeb as j, type ApiKeyData as k, ApiKeyStorage as l, TokenStorage as m };
|
package/dist/browser.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { O as OAuthConfig, T as TokenStorageAdapter } from './api-key-storage-web-
|
|
2
|
-
export {
|
|
1
|
+
import { O as OAuthConfig, T as TokenStorageAdapter } from './api-key-storage-web-DUyiN9mC.cjs';
|
|
2
|
+
export { A as ApiKeyStorageWeb, a as AuthError, b as AuthGatewayClient, c as AuthGatewayClientConfig, d as AuthTokenType, e as AuthValidationResult, B as BaseOAuthFlow, D as DesktopOAuthFlow, f as DeviceCodeResponse, G as GrantType, P as PKCEChallenge, g as TokenExchangeOptions, h as TokenExchangeResponse, i as TokenResponse, j as TokenStorageWeb } from './api-key-storage-web-DUyiN9mC.cjs';
|
|
3
3
|
|
|
4
4
|
interface MCPClientConfig extends Partial<OAuthConfig> {
|
|
5
5
|
mcpEndpoint?: string;
|
package/dist/browser.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { O as OAuthConfig, T as TokenStorageAdapter } from './api-key-storage-web-
|
|
2
|
-
export {
|
|
1
|
+
import { O as OAuthConfig, T as TokenStorageAdapter } from './api-key-storage-web-DUyiN9mC.js';
|
|
2
|
+
export { A as ApiKeyStorageWeb, a as AuthError, b as AuthGatewayClient, c as AuthGatewayClientConfig, d as AuthTokenType, e as AuthValidationResult, B as BaseOAuthFlow, D as DesktopOAuthFlow, f as DeviceCodeResponse, G as GrantType, P as PKCEChallenge, g as TokenExchangeOptions, h as TokenExchangeResponse, i as TokenResponse, j as TokenStorageWeb } from './api-key-storage-web-DUyiN9mC.js';
|
|
3
3
|
|
|
4
4
|
interface MCPClientConfig extends Partial<OAuthConfig> {
|
|
5
5
|
mcpEndpoint?: string;
|
|
@@ -107,4 +107,4 @@ declare const DEFAULT_POLL_INTERVAL = 30000;
|
|
|
107
107
|
*/
|
|
108
108
|
declare const DEFAULT_PROJECT_SCOPE = "lanonasis-maas";
|
|
109
109
|
|
|
110
|
-
export { COOKIE_NAMES as C, DEFAULT_AUTH_GATEWAY as D, type SSOConfig as S, type UseSSOReturn as U, type SupabaseSession as a, type SSOSyncConfig as b, type UseSSOSyncReturn as c, type SSOUser as d,
|
|
110
|
+
export { COOKIE_NAMES as C, DEFAULT_AUTH_GATEWAY as D, type SSOConfig as S, type UseSSOReturn as U, type SupabaseSession as a, type SSOSyncConfig as b, type UseSSOSyncReturn as c, type SSOUser as d, DEFAULT_COOKIE_DOMAIN as e, DEFAULT_POLL_INTERVAL as f, DEFAULT_PROJECT_SCOPE as g, type SSOState as h };
|
|
@@ -107,4 +107,4 @@ declare const DEFAULT_POLL_INTERVAL = 30000;
|
|
|
107
107
|
*/
|
|
108
108
|
declare const DEFAULT_PROJECT_SCOPE = "lanonasis-maas";
|
|
109
109
|
|
|
110
|
-
export { COOKIE_NAMES as C, DEFAULT_AUTH_GATEWAY as D, type SSOConfig as S, type UseSSOReturn as U, type SupabaseSession as a, type SSOSyncConfig as b, type UseSSOSyncReturn as c, type SSOUser as d,
|
|
110
|
+
export { COOKIE_NAMES as C, DEFAULT_AUTH_GATEWAY as D, type SSOConfig as S, type UseSSOReturn as U, type SupabaseSession as a, type SSOSyncConfig as b, type UseSSOSyncReturn as c, type SSOUser as d, DEFAULT_COOKIE_DOMAIN as e, DEFAULT_POLL_INTERVAL as f, DEFAULT_PROJECT_SCOPE as g, type SSOState as h };
|
package/dist/index.cjs
CHANGED
|
@@ -661,13 +661,25 @@ var TokenStorage = class {
|
|
|
661
661
|
constructor() {
|
|
662
662
|
this.storageKey = "lanonasis_mcp_tokens";
|
|
663
663
|
this.webEncryptionKeyStorage = "lanonasis_web_token_enc_key";
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
664
|
+
this.keytar = null;
|
|
665
|
+
this.keytarLoadAttempted = false;
|
|
666
|
+
}
|
|
667
|
+
async getKeytar() {
|
|
668
|
+
if (!this.isNode()) {
|
|
669
|
+
return null;
|
|
670
670
|
}
|
|
671
|
+
if (this.keytarLoadAttempted) {
|
|
672
|
+
return this.keytar;
|
|
673
|
+
}
|
|
674
|
+
this.keytarLoadAttempted = true;
|
|
675
|
+
try {
|
|
676
|
+
const keytarModule = await import("keytar");
|
|
677
|
+
this.keytar = keytarModule.default ?? keytarModule;
|
|
678
|
+
} catch {
|
|
679
|
+
this.keytar = null;
|
|
680
|
+
console.warn("Keytar not available - falling back to file storage");
|
|
681
|
+
}
|
|
682
|
+
return this.keytar;
|
|
671
683
|
}
|
|
672
684
|
async store(tokens) {
|
|
673
685
|
const tokensWithTimestamp = {
|
|
@@ -676,8 +688,9 @@ var TokenStorage = class {
|
|
|
676
688
|
};
|
|
677
689
|
const tokenString = JSON.stringify(tokensWithTimestamp);
|
|
678
690
|
if (this.isNode()) {
|
|
679
|
-
|
|
680
|
-
|
|
691
|
+
const keytar = await this.getKeytar();
|
|
692
|
+
if (keytar) {
|
|
693
|
+
await keytar.setPassword("lanonasis-mcp", "tokens", tokenString);
|
|
681
694
|
} else {
|
|
682
695
|
await this.storeToFile(tokenString);
|
|
683
696
|
}
|
|
@@ -694,8 +707,9 @@ var TokenStorage = class {
|
|
|
694
707
|
let tokenString = null;
|
|
695
708
|
try {
|
|
696
709
|
if (this.isNode()) {
|
|
697
|
-
|
|
698
|
-
|
|
710
|
+
const keytar = await this.getKeytar();
|
|
711
|
+
if (keytar) {
|
|
712
|
+
tokenString = await keytar.getPassword("lanonasis-mcp", "tokens");
|
|
699
713
|
}
|
|
700
714
|
if (!tokenString) {
|
|
701
715
|
tokenString = await this.retrieveFromFile();
|
|
@@ -719,8 +733,9 @@ var TokenStorage = class {
|
|
|
719
733
|
}
|
|
720
734
|
async clear() {
|
|
721
735
|
if (this.isNode()) {
|
|
722
|
-
|
|
723
|
-
|
|
736
|
+
const keytar = await this.getKeytar();
|
|
737
|
+
if (keytar) {
|
|
738
|
+
await keytar.deletePassword("lanonasis-mcp", "tokens");
|
|
724
739
|
}
|
|
725
740
|
await this.deleteFile();
|
|
726
741
|
} else if (this.isElectron()) {
|
|
@@ -965,14 +980,26 @@ var ApiKeyStorage = class {
|
|
|
965
980
|
this.storageKey = "lanonasis_api_key";
|
|
966
981
|
this.legacyConfigKey = "lanonasis_legacy_api_key";
|
|
967
982
|
this.webEncryptionKeyStorage = "lanonasis_web_enc_key";
|
|
983
|
+
this.keytar = null;
|
|
984
|
+
this.keytarLoadAttempted = false;
|
|
968
985
|
this.migrationCompleted = false;
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
986
|
+
}
|
|
987
|
+
async getKeytar() {
|
|
988
|
+
if (!this.isNode()) {
|
|
989
|
+
return null;
|
|
990
|
+
}
|
|
991
|
+
if (this.keytarLoadAttempted) {
|
|
992
|
+
return this.keytar;
|
|
993
|
+
}
|
|
994
|
+
this.keytarLoadAttempted = true;
|
|
995
|
+
try {
|
|
996
|
+
const keytarModule = await import("keytar");
|
|
997
|
+
this.keytar = keytarModule.default ?? keytarModule;
|
|
998
|
+
} catch {
|
|
999
|
+
this.keytar = null;
|
|
1000
|
+
console.warn("Keytar not available - falling back to encrypted file storage");
|
|
975
1001
|
}
|
|
1002
|
+
return this.keytar;
|
|
976
1003
|
}
|
|
977
1004
|
/**
|
|
978
1005
|
* Initialize and migrate from legacy storage if needed
|
|
@@ -992,9 +1019,10 @@ var ApiKeyStorage = class {
|
|
|
992
1019
|
};
|
|
993
1020
|
const keyString = JSON.stringify(dataWithTimestamp);
|
|
994
1021
|
if (this.isNode()) {
|
|
995
|
-
|
|
1022
|
+
const keytar = await this.getKeytar();
|
|
1023
|
+
if (keytar) {
|
|
996
1024
|
try {
|
|
997
|
-
await
|
|
1025
|
+
await keytar.setPassword("lanonasis-mcp", this.storageKey, keyString);
|
|
998
1026
|
return;
|
|
999
1027
|
} catch (error) {
|
|
1000
1028
|
console.warn("Keytar storage failed, falling back to file:", error);
|
|
@@ -1017,9 +1045,10 @@ var ApiKeyStorage = class {
|
|
|
1017
1045
|
let keyString = null;
|
|
1018
1046
|
try {
|
|
1019
1047
|
if (this.isNode()) {
|
|
1020
|
-
|
|
1048
|
+
const keytar = await this.getKeytar();
|
|
1049
|
+
if (keytar) {
|
|
1021
1050
|
try {
|
|
1022
|
-
keyString = await
|
|
1051
|
+
keyString = await keytar.getPassword("lanonasis-mcp", this.storageKey);
|
|
1023
1052
|
} catch (error) {
|
|
1024
1053
|
console.warn("Keytar retrieval failed, trying file:", error);
|
|
1025
1054
|
}
|
|
@@ -1077,9 +1106,10 @@ var ApiKeyStorage = class {
|
|
|
1077
1106
|
*/
|
|
1078
1107
|
async clear() {
|
|
1079
1108
|
if (this.isNode()) {
|
|
1080
|
-
|
|
1109
|
+
const keytar = await this.getKeytar();
|
|
1110
|
+
if (keytar) {
|
|
1081
1111
|
try {
|
|
1082
|
-
await
|
|
1112
|
+
await keytar.deletePassword("lanonasis-mcp", this.storageKey);
|
|
1083
1113
|
} catch (error) {
|
|
1084
1114
|
console.warn("Keytar deletion failed:", error);
|
|
1085
1115
|
}
|
|
@@ -1381,26 +1411,19 @@ var ApiKeyStorage = class {
|
|
|
1381
1411
|
throw new Error("No base64 decoder available");
|
|
1382
1412
|
}
|
|
1383
1413
|
/**
|
|
1384
|
-
* Normalize
|
|
1385
|
-
*
|
|
1414
|
+
* Normalize stored credentials without transforming their value.
|
|
1415
|
+
*
|
|
1416
|
+
* These secrets are stored in encrypted local storage/keychains and must remain
|
|
1417
|
+
* usable for outbound authentication headers (for example X-API-Key or Bearer).
|
|
1418
|
+
* Hashing here would make the original credential unrecoverable and break
|
|
1419
|
+
* clients that need to send the raw key/token back to a remote service.
|
|
1386
1420
|
*/
|
|
1387
1421
|
async normalizeApiKey(apiKey) {
|
|
1388
1422
|
const value = apiKey?.trim();
|
|
1389
1423
|
if (!value) {
|
|
1390
1424
|
throw new Error("API key must be a non-empty string");
|
|
1391
1425
|
}
|
|
1392
|
-
|
|
1393
|
-
return value.toLowerCase();
|
|
1394
|
-
}
|
|
1395
|
-
if (typeof globalThis !== "undefined" && globalThis.crypto?.subtle) {
|
|
1396
|
-
const encoder = new TextEncoder();
|
|
1397
|
-
const data = encoder.encode(value);
|
|
1398
|
-
const hashBuffer = await globalThis.crypto.subtle.digest("SHA-256", data);
|
|
1399
|
-
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
1400
|
-
return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1401
|
-
}
|
|
1402
|
-
const nodeCrypto = await import("crypto");
|
|
1403
|
-
return nodeCrypto.createHash("sha256").update(value).digest("hex");
|
|
1426
|
+
return value;
|
|
1404
1427
|
}
|
|
1405
1428
|
};
|
|
1406
1429
|
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { B as BaseOAuthFlow, O as OAuthConfig,
|
|
2
|
-
export {
|
|
1
|
+
import { B as BaseOAuthFlow, O as OAuthConfig, i as TokenResponse, T as TokenStorageAdapter } from './api-key-storage-web-DUyiN9mC.cjs';
|
|
2
|
+
export { k as ApiKeyData, l as ApiKeyStorage, A as ApiKeyStorageWeb, a as AuthError, b as AuthGatewayClient, c as AuthGatewayClientConfig, d as AuthTokenType, e as AuthValidationResult, D as DesktopOAuthFlow, f as DeviceCodeResponse, G as GrantType, P as PKCEChallenge, g as TokenExchangeOptions, h as TokenExchangeResponse, m as TokenStorage, j as TokenStorageWeb } from './api-key-storage-web-DUyiN9mC.cjs';
|
|
3
3
|
|
|
4
4
|
declare class TerminalOAuthFlow extends BaseOAuthFlow {
|
|
5
5
|
private pollInterval;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { B as BaseOAuthFlow, O as OAuthConfig,
|
|
2
|
-
export {
|
|
1
|
+
import { B as BaseOAuthFlow, O as OAuthConfig, i as TokenResponse, T as TokenStorageAdapter } from './api-key-storage-web-DUyiN9mC.js';
|
|
2
|
+
export { k as ApiKeyData, l as ApiKeyStorage, A as ApiKeyStorageWeb, a as AuthError, b as AuthGatewayClient, c as AuthGatewayClientConfig, d as AuthTokenType, e as AuthValidationResult, D as DesktopOAuthFlow, f as DeviceCodeResponse, G as GrantType, P as PKCEChallenge, g as TokenExchangeOptions, h as TokenExchangeResponse, m as TokenStorage, j as TokenStorageWeb } from './api-key-storage-web-DUyiN9mC.js';
|
|
3
3
|
|
|
4
4
|
declare class TerminalOAuthFlow extends BaseOAuthFlow {
|
|
5
5
|
private pollInterval;
|
package/dist/index.mjs
CHANGED
|
@@ -622,13 +622,25 @@ var TokenStorage = class {
|
|
|
622
622
|
constructor() {
|
|
623
623
|
this.storageKey = "lanonasis_mcp_tokens";
|
|
624
624
|
this.webEncryptionKeyStorage = "lanonasis_web_token_enc_key";
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
625
|
+
this.keytar = null;
|
|
626
|
+
this.keytarLoadAttempted = false;
|
|
627
|
+
}
|
|
628
|
+
async getKeytar() {
|
|
629
|
+
if (!this.isNode()) {
|
|
630
|
+
return null;
|
|
631
631
|
}
|
|
632
|
+
if (this.keytarLoadAttempted) {
|
|
633
|
+
return this.keytar;
|
|
634
|
+
}
|
|
635
|
+
this.keytarLoadAttempted = true;
|
|
636
|
+
try {
|
|
637
|
+
const keytarModule = await import("keytar");
|
|
638
|
+
this.keytar = keytarModule.default ?? keytarModule;
|
|
639
|
+
} catch {
|
|
640
|
+
this.keytar = null;
|
|
641
|
+
console.warn("Keytar not available - falling back to file storage");
|
|
642
|
+
}
|
|
643
|
+
return this.keytar;
|
|
632
644
|
}
|
|
633
645
|
async store(tokens) {
|
|
634
646
|
const tokensWithTimestamp = {
|
|
@@ -637,8 +649,9 @@ var TokenStorage = class {
|
|
|
637
649
|
};
|
|
638
650
|
const tokenString = JSON.stringify(tokensWithTimestamp);
|
|
639
651
|
if (this.isNode()) {
|
|
640
|
-
|
|
641
|
-
|
|
652
|
+
const keytar = await this.getKeytar();
|
|
653
|
+
if (keytar) {
|
|
654
|
+
await keytar.setPassword("lanonasis-mcp", "tokens", tokenString);
|
|
642
655
|
} else {
|
|
643
656
|
await this.storeToFile(tokenString);
|
|
644
657
|
}
|
|
@@ -655,8 +668,9 @@ var TokenStorage = class {
|
|
|
655
668
|
let tokenString = null;
|
|
656
669
|
try {
|
|
657
670
|
if (this.isNode()) {
|
|
658
|
-
|
|
659
|
-
|
|
671
|
+
const keytar = await this.getKeytar();
|
|
672
|
+
if (keytar) {
|
|
673
|
+
tokenString = await keytar.getPassword("lanonasis-mcp", "tokens");
|
|
660
674
|
}
|
|
661
675
|
if (!tokenString) {
|
|
662
676
|
tokenString = await this.retrieveFromFile();
|
|
@@ -680,8 +694,9 @@ var TokenStorage = class {
|
|
|
680
694
|
}
|
|
681
695
|
async clear() {
|
|
682
696
|
if (this.isNode()) {
|
|
683
|
-
|
|
684
|
-
|
|
697
|
+
const keytar = await this.getKeytar();
|
|
698
|
+
if (keytar) {
|
|
699
|
+
await keytar.deletePassword("lanonasis-mcp", "tokens");
|
|
685
700
|
}
|
|
686
701
|
await this.deleteFile();
|
|
687
702
|
} else if (this.isElectron()) {
|
|
@@ -926,14 +941,26 @@ var ApiKeyStorage = class {
|
|
|
926
941
|
this.storageKey = "lanonasis_api_key";
|
|
927
942
|
this.legacyConfigKey = "lanonasis_legacy_api_key";
|
|
928
943
|
this.webEncryptionKeyStorage = "lanonasis_web_enc_key";
|
|
944
|
+
this.keytar = null;
|
|
945
|
+
this.keytarLoadAttempted = false;
|
|
929
946
|
this.migrationCompleted = false;
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
947
|
+
}
|
|
948
|
+
async getKeytar() {
|
|
949
|
+
if (!this.isNode()) {
|
|
950
|
+
return null;
|
|
951
|
+
}
|
|
952
|
+
if (this.keytarLoadAttempted) {
|
|
953
|
+
return this.keytar;
|
|
954
|
+
}
|
|
955
|
+
this.keytarLoadAttempted = true;
|
|
956
|
+
try {
|
|
957
|
+
const keytarModule = await import("keytar");
|
|
958
|
+
this.keytar = keytarModule.default ?? keytarModule;
|
|
959
|
+
} catch {
|
|
960
|
+
this.keytar = null;
|
|
961
|
+
console.warn("Keytar not available - falling back to encrypted file storage");
|
|
936
962
|
}
|
|
963
|
+
return this.keytar;
|
|
937
964
|
}
|
|
938
965
|
/**
|
|
939
966
|
* Initialize and migrate from legacy storage if needed
|
|
@@ -953,9 +980,10 @@ var ApiKeyStorage = class {
|
|
|
953
980
|
};
|
|
954
981
|
const keyString = JSON.stringify(dataWithTimestamp);
|
|
955
982
|
if (this.isNode()) {
|
|
956
|
-
|
|
983
|
+
const keytar = await this.getKeytar();
|
|
984
|
+
if (keytar) {
|
|
957
985
|
try {
|
|
958
|
-
await
|
|
986
|
+
await keytar.setPassword("lanonasis-mcp", this.storageKey, keyString);
|
|
959
987
|
return;
|
|
960
988
|
} catch (error) {
|
|
961
989
|
console.warn("Keytar storage failed, falling back to file:", error);
|
|
@@ -978,9 +1006,10 @@ var ApiKeyStorage = class {
|
|
|
978
1006
|
let keyString = null;
|
|
979
1007
|
try {
|
|
980
1008
|
if (this.isNode()) {
|
|
981
|
-
|
|
1009
|
+
const keytar = await this.getKeytar();
|
|
1010
|
+
if (keytar) {
|
|
982
1011
|
try {
|
|
983
|
-
keyString = await
|
|
1012
|
+
keyString = await keytar.getPassword("lanonasis-mcp", this.storageKey);
|
|
984
1013
|
} catch (error) {
|
|
985
1014
|
console.warn("Keytar retrieval failed, trying file:", error);
|
|
986
1015
|
}
|
|
@@ -1038,9 +1067,10 @@ var ApiKeyStorage = class {
|
|
|
1038
1067
|
*/
|
|
1039
1068
|
async clear() {
|
|
1040
1069
|
if (this.isNode()) {
|
|
1041
|
-
|
|
1070
|
+
const keytar = await this.getKeytar();
|
|
1071
|
+
if (keytar) {
|
|
1042
1072
|
try {
|
|
1043
|
-
await
|
|
1073
|
+
await keytar.deletePassword("lanonasis-mcp", this.storageKey);
|
|
1044
1074
|
} catch (error) {
|
|
1045
1075
|
console.warn("Keytar deletion failed:", error);
|
|
1046
1076
|
}
|
|
@@ -1342,26 +1372,19 @@ var ApiKeyStorage = class {
|
|
|
1342
1372
|
throw new Error("No base64 decoder available");
|
|
1343
1373
|
}
|
|
1344
1374
|
/**
|
|
1345
|
-
* Normalize
|
|
1346
|
-
*
|
|
1375
|
+
* Normalize stored credentials without transforming their value.
|
|
1376
|
+
*
|
|
1377
|
+
* These secrets are stored in encrypted local storage/keychains and must remain
|
|
1378
|
+
* usable for outbound authentication headers (for example X-API-Key or Bearer).
|
|
1379
|
+
* Hashing here would make the original credential unrecoverable and break
|
|
1380
|
+
* clients that need to send the raw key/token back to a remote service.
|
|
1347
1381
|
*/
|
|
1348
1382
|
async normalizeApiKey(apiKey) {
|
|
1349
1383
|
const value = apiKey?.trim();
|
|
1350
1384
|
if (!value) {
|
|
1351
1385
|
throw new Error("API key must be a non-empty string");
|
|
1352
1386
|
}
|
|
1353
|
-
|
|
1354
|
-
return value.toLowerCase();
|
|
1355
|
-
}
|
|
1356
|
-
if (typeof globalThis !== "undefined" && globalThis.crypto?.subtle) {
|
|
1357
|
-
const encoder = new TextEncoder();
|
|
1358
|
-
const data = encoder.encode(value);
|
|
1359
|
-
const hashBuffer = await globalThis.crypto.subtle.digest("SHA-256", data);
|
|
1360
|
-
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
1361
|
-
return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1362
|
-
}
|
|
1363
|
-
const nodeCrypto = await import("crypto");
|
|
1364
|
-
return nodeCrypto.createHash("sha256").update(value).digest("hex");
|
|
1387
|
+
return value;
|
|
1365
1388
|
}
|
|
1366
1389
|
};
|
|
1367
1390
|
|
package/dist/react/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as SSOConfig, U as UseSSOReturn, a as SupabaseSession, b as SSOSyncConfig, c as UseSSOSyncReturn, d as SSOUser } from '../constants-
|
|
2
|
-
export { C as COOKIE_NAMES, D as DEFAULT_AUTH_GATEWAY,
|
|
1
|
+
import { S as SSOConfig, U as UseSSOReturn, a as SupabaseSession, b as SSOSyncConfig, c as UseSSOSyncReturn, d as SSOUser } from '../constants-BZPTHasL.cjs';
|
|
2
|
+
export { C as COOKIE_NAMES, D as DEFAULT_AUTH_GATEWAY, e as DEFAULT_COOKIE_DOMAIN, f as DEFAULT_POLL_INTERVAL, g as DEFAULT_PROJECT_SCOPE, h as SSOState } from '../constants-BZPTHasL.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* React hook for SSO authentication state
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as SSOConfig, U as UseSSOReturn, a as SupabaseSession, b as SSOSyncConfig, c as UseSSOSyncReturn, d as SSOUser } from '../constants-
|
|
2
|
-
export { C as COOKIE_NAMES, D as DEFAULT_AUTH_GATEWAY,
|
|
1
|
+
import { S as SSOConfig, U as UseSSOReturn, a as SupabaseSession, b as SSOSyncConfig, c as UseSSOSyncReturn, d as SSOUser } from '../constants-BZPTHasL.js';
|
|
2
|
+
export { C as COOKIE_NAMES, D as DEFAULT_AUTH_GATEWAY, e as DEFAULT_COOKIE_DOMAIN, f as DEFAULT_POLL_INTERVAL, g as DEFAULT_PROJECT_SCOPE, h as SSOState } from '../constants-BZPTHasL.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* React hook for SSO authentication state
|
package/dist/server/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { d as SSOUser } from '../constants-
|
|
2
|
-
export { C as COOKIE_NAMES, D as DEFAULT_AUTH_GATEWAY,
|
|
1
|
+
import { d as SSOUser } from '../constants-BZPTHasL.cjs';
|
|
2
|
+
export { C as COOKIE_NAMES, D as DEFAULT_AUTH_GATEWAY, e as DEFAULT_COOKIE_DOMAIN, g as DEFAULT_PROJECT_SCOPE } from '../constants-BZPTHasL.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Server-side types for SSO authentication
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { d as SSOUser } from '../constants-
|
|
2
|
-
export { C as COOKIE_NAMES, D as DEFAULT_AUTH_GATEWAY,
|
|
1
|
+
import { d as SSOUser } from '../constants-BZPTHasL.js';
|
|
2
|
+
export { C as COOKIE_NAMES, D as DEFAULT_AUTH_GATEWAY, e as DEFAULT_COOKIE_DOMAIN, g as DEFAULT_PROJECT_SCOPE } from '../constants-BZPTHasL.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Server-side types for SSO authentication
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lanonasis/oauth-client",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "OAuth and API Key authentication client for Lan Onasis MCP integration",
|
|
6
6
|
"license": "MIT",
|
|
@@ -43,6 +43,27 @@
|
|
|
43
43
|
"types": "./dist/server/index.d.ts",
|
|
44
44
|
"import": "./dist/server/index.mjs",
|
|
45
45
|
"require": "./dist/server/index.cjs"
|
|
46
|
+
},
|
|
47
|
+
"./cookies": {
|
|
48
|
+
"types": "./dist/cookies/constants.d.ts",
|
|
49
|
+
"import": "./dist/cookies/constants.mjs",
|
|
50
|
+
"require": "./dist/cookies/constants.cjs"
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"typesVersions": {
|
|
54
|
+
"*": {
|
|
55
|
+
"browser": [
|
|
56
|
+
"./dist/browser.d.ts"
|
|
57
|
+
],
|
|
58
|
+
"react": [
|
|
59
|
+
"./dist/react/index.d.ts"
|
|
60
|
+
],
|
|
61
|
+
"server": [
|
|
62
|
+
"./dist/server/index.d.ts"
|
|
63
|
+
],
|
|
64
|
+
"cookies": [
|
|
65
|
+
"./dist/cookies/constants.d.ts"
|
|
66
|
+
]
|
|
46
67
|
}
|
|
47
68
|
},
|
|
48
69
|
"scripts": {
|
|
@@ -63,26 +84,31 @@
|
|
|
63
84
|
"desktop"
|
|
64
85
|
],
|
|
65
86
|
"dependencies": {
|
|
66
|
-
"cross-fetch": "^4.
|
|
67
|
-
"eventsource": "^
|
|
87
|
+
"cross-fetch": "^4.1.0",
|
|
88
|
+
"eventsource": "^4.1.0",
|
|
68
89
|
"keytar": "^7.9.0",
|
|
69
|
-
"open": "^
|
|
90
|
+
"open": "^11.0.0"
|
|
70
91
|
},
|
|
71
92
|
"devDependencies": {
|
|
72
|
-
"@eslint/js": "^
|
|
73
|
-
"@types/node": "^
|
|
74
|
-
"@types/react": "^19.
|
|
75
|
-
"@vitest/coverage-v8": "^
|
|
76
|
-
"eslint": "^
|
|
77
|
-
"globals": "^
|
|
78
|
-
"tsup": "^8.5.
|
|
79
|
-
"typescript": "^5.
|
|
80
|
-
"typescript-eslint": "^8.
|
|
81
|
-
"vitest": "^
|
|
93
|
+
"@eslint/js": "^10.0.1",
|
|
94
|
+
"@types/node": "^25.5.0",
|
|
95
|
+
"@types/react": "^19.2.14",
|
|
96
|
+
"@vitest/coverage-v8": "^4.1.2",
|
|
97
|
+
"eslint": "^10.1.0",
|
|
98
|
+
"globals": "^17.4.0",
|
|
99
|
+
"tsup": "^8.5.1",
|
|
100
|
+
"typescript": "^5.9.3",
|
|
101
|
+
"typescript-eslint": "^8.57.2",
|
|
102
|
+
"vitest": "^4.1.2"
|
|
103
|
+
},
|
|
104
|
+
"overrides": {
|
|
105
|
+
"flatted": "^3.4.0",
|
|
106
|
+
"picomatch": "^4.0.4",
|
|
107
|
+
"rollup": "^4.59.0"
|
|
82
108
|
},
|
|
83
109
|
"peerDependencies": {
|
|
84
|
-
"@supabase/supabase-js": "^2.
|
|
85
|
-
"react": "
|
|
110
|
+
"@supabase/supabase-js": "^2.100.1",
|
|
111
|
+
"react": "latest"
|
|
86
112
|
},
|
|
87
113
|
"peerDependenciesMeta": {
|
|
88
114
|
"react": {
|