idenplane-sdk 1.0.1

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 (2) hide show
  1. package/README.md +649 -0
  2. package/package.json +94 -0
package/README.md ADDED
@@ -0,0 +1,649 @@
1
+ <p align="center">
2
+ <img src="https://idenplane.com/logo.svg" alt="Idenplane" width="60" />
3
+ </p>
4
+
5
+ <h2 align="center">idenplane-sdk</h2>
6
+
7
+ <p align="center">
8
+ <strong>Official client SDK for <a href="https://idenplane.com">Idenplane</a></strong><br />
9
+ <sub>Zero-dependency TypeScript SDK with OAuth 2.0 PKCE, token management, React bindings, and Next.js support.</sub>
10
+ </p>
11
+
12
+ <p align="center">
13
+ <img src="https://img.shields.io/badge/version-1.0.0-blue" alt="v1.0.0" />
14
+ <img src="https://img.shields.io/badge/bundle-~5KB_gzipped-green" alt="bundle size" />
15
+ <img src="https://img.shields.io/badge/TypeScript-first-blue" alt="TypeScript" />
16
+ <img src="https://img.shields.io/badge/React-18%2B-61dafb" alt="React 18+" />
17
+ </p>
18
+
19
+ ---
20
+
21
+ ## Install
22
+
23
+ ```bash
24
+ npm install idenplane-sdk
25
+ ```
26
+
27
+ ---
28
+
29
+ ## Quick Start
30
+
31
+ ### Vanilla JavaScript / TypeScript
32
+
33
+ ```typescript
34
+ import { IdenplaneClient } from 'idenplane-sdk';
35
+
36
+ const idenplane = new IdenplaneClient({
37
+ url: 'http://localhost:3000',
38
+ realm: 'my-realm',
39
+ clientId: 'my-app',
40
+ redirectUri: 'http://localhost:5173/callback',
41
+ });
42
+
43
+ // Initialize (restores existing session if any)
44
+ await idenplane.init();
45
+
46
+ if (!idenplane.isAuthenticated()) {
47
+ // Redirects to Idenplane login page
48
+ await idenplane.login();
49
+ }
50
+ ```
51
+
52
+ On your callback page:
53
+
54
+ ```typescript
55
+ const idenplane = new IdenplaneClient({ /* same config */ });
56
+ const success = await idenplane.handleCallback();
57
+ if (success) {
58
+ const user = idenplane.getUserInfo();
59
+ console.log(`Welcome, ${user?.name}!`);
60
+ }
61
+ ```
62
+
63
+ ### React
64
+
65
+ ```tsx
66
+ import { AuthProvider, useAuth, useUser, usePermissions } from 'idenplane-sdk/react';
67
+
68
+ function App() {
69
+ return (
70
+ <AuthProvider
71
+ serverUrl="http://localhost:3000"
72
+ realm="my-realm"
73
+ clientId="my-app"
74
+ redirectUri="http://localhost:5173/callback"
75
+ onLogin={(tokens) => console.log('Logged in!')}
76
+ onLogout={() => console.log('Logged out!')}
77
+ onError={(err) => console.error('Auth error:', err)}
78
+ >
79
+ <Main />
80
+ </AuthProvider>
81
+ );
82
+ }
83
+
84
+ function Main() {
85
+ const { isAuthenticated, isLoading, login, logout, getToken } = useAuth();
86
+ const user = useUser();
87
+ const { hasRole, hasPermission, roles } = usePermissions();
88
+
89
+ if (isLoading) return <div>Loading...</div>;
90
+
91
+ if (!isAuthenticated) {
92
+ return <button onClick={() => login()}>Sign In</button>;
93
+ }
94
+
95
+ return (
96
+ <div>
97
+ <p>Welcome, {user?.name}!</p>
98
+ <p>Token: {getToken()}</p>
99
+ {hasRole('admin') && <p>You are an admin.</p>}
100
+ {hasPermission('read:reports') && <p>You can read reports.</p>}
101
+ <p>Your roles: {roles.join(', ')}</p>
102
+ <button onClick={() => logout()}>Sign Out</button>
103
+ </div>
104
+ );
105
+ }
106
+ ```
107
+
108
+ ### AuthProvider with pre-built client
109
+
110
+ ```tsx
111
+ import { IdenplaneClient } from 'idenplane-sdk';
112
+ import { AuthProvider } from 'idenplane-sdk/react';
113
+
114
+ const client = new IdenplaneClient({
115
+ url: 'http://localhost:3000',
116
+ realm: 'my-realm',
117
+ clientId: 'my-app',
118
+ redirectUri: 'http://localhost:5173/callback',
119
+ refreshStrategy: 'rotation', // 'rotation' | 'silent' | 'eager'
120
+ storage: 'sessionStorage', // 'sessionStorage' | 'localStorage' | 'memory'
121
+ });
122
+
123
+ function App() {
124
+ return (
125
+ <AuthProvider client={client}>
126
+ <Main />
127
+ </AuthProvider>
128
+ );
129
+ }
130
+ ```
131
+
132
+ ### ProtectedRoute
133
+
134
+ ```tsx
135
+ import { AuthProvider, ProtectedRoute } from 'idenplane-sdk/react';
136
+ import { useNavigate } from 'react-router-dom';
137
+
138
+ function AdminPage() {
139
+ const navigate = useNavigate();
140
+
141
+ return (
142
+ <ProtectedRoute
143
+ roles={['admin']}
144
+ fallback={<div>Loading...</div>}
145
+ onUnauthorized={() => {
146
+ navigate('/login');
147
+ return null;
148
+ }}
149
+ onForbidden={() => <div>Access denied. Admin role required.</div>}
150
+ >
151
+ <AdminDashboard />
152
+ </ProtectedRoute>
153
+ );
154
+ }
155
+ ```
156
+
157
+ ---
158
+
159
+ ## Token Refresh Strategies
160
+
161
+ Configure how the SDK refreshes tokens via the `refreshStrategy` option:
162
+
163
+ | Strategy | Description |
164
+ |----------|-------------|
165
+ | `rotation` | *(default)* Uses refresh token grant to get a new access token |
166
+ | `eager` | Like `rotation`, but refreshes proactively at 2× the `refreshBuffer` |
167
+ | `silent` | Uses a hidden iframe with `prompt=none` for silent re-auth |
168
+
169
+ ```typescript
170
+ const client = new IdenplaneClient({
171
+ url: 'http://localhost:3000',
172
+ realm: 'my-realm',
173
+ clientId: 'my-app',
174
+ redirectUri: 'http://localhost:5173/callback',
175
+ refreshStrategy: 'eager', // refresh 60 seconds before expiry (2× default 30s)
176
+ refreshBuffer: 30, // seconds before expiry to trigger refresh
177
+ autoRefresh: true, // enable automatic refresh (default: true)
178
+ });
179
+ ```
180
+
181
+ For the `silent` strategy, your app's redirect URI page must post a message back to the parent window:
182
+
183
+ ```html
184
+ <!-- /callback page for silent refresh -->
185
+ <script>
186
+ const params = new URLSearchParams(window.location.search);
187
+ window.parent.postMessage({
188
+ type: 'idenplane:silent_callback',
189
+ code: params.get('code'),
190
+ state: params.get('state'),
191
+ error: params.get('error'),
192
+ }, window.location.origin);
193
+ </script>
194
+ ```
195
+
196
+ ---
197
+
198
+ ## Event System
199
+
200
+ Subscribe to SDK events to react to authentication state changes:
201
+
202
+ ```typescript
203
+ const client = new IdenplaneClient({ ... });
204
+
205
+ // Subscribe — returns an unsubscribe function
206
+ const unsubscribe = client.on('login', (tokens) => {
207
+ console.log('User logged in, token:', tokens.access_token);
208
+ });
209
+
210
+ client.on('logout', () => {
211
+ console.log('User logged out');
212
+ });
213
+
214
+ client.on('tokenRefresh', (tokens) => {
215
+ console.log('Token refreshed silently');
216
+ });
217
+
218
+ client.on('error', (error) => {
219
+ console.error('Auth error:', error.message);
220
+ });
221
+
222
+ client.on('ready', (isAuthenticated) => {
223
+ console.log('Client initialized, authenticated:', isAuthenticated);
224
+ });
225
+
226
+ // Unsubscribe when done
227
+ unsubscribe();
228
+ // or
229
+ client.off('login', myHandler);
230
+ ```
231
+
232
+ Alternatively, pass callbacks directly in the config:
233
+
234
+ ```typescript
235
+ const client = new IdenplaneClient({
236
+ url: 'http://localhost:3000',
237
+ realm: 'my-realm',
238
+ clientId: 'my-app',
239
+ redirectUri: '/callback',
240
+ onLogin: (tokens) => saveSession(tokens),
241
+ onLogout: () => clearSession(),
242
+ onError: (err) => reportError(err),
243
+ onTokenRefresh: (tokens) => updateSession(tokens),
244
+ });
245
+ ```
246
+
247
+ ---
248
+
249
+ ## Next.js Integration
250
+
251
+ ### Server-side authentication in API routes
252
+
253
+ ```typescript
254
+ // pages/api/profile.ts (or app/api/profile/route.ts)
255
+ import type { NextApiRequest, NextApiResponse } from 'next';
256
+ import { getServerSideAuth } from 'idenplane-sdk/server';
257
+
258
+ export default async function handler(req: NextApiRequest, res: NextApiResponse) {
259
+ const { user, isAuthenticated } = await getServerSideAuth(req, {
260
+ issuerUrl: 'http://localhost:3000',
261
+ realm: 'my-realm',
262
+ });
263
+
264
+ if (!isAuthenticated) {
265
+ return res.status(401).json({ error: 'Unauthorized' });
266
+ }
267
+
268
+ res.json({
269
+ id: user!.sub,
270
+ username: user!.preferred_username,
271
+ email: user!.email,
272
+ });
273
+ }
274
+ ```
275
+
276
+ ### getServerSideProps
277
+
278
+ ```typescript
279
+ import { getServerSideAuth } from 'idenplane-sdk/server';
280
+
281
+ export const getServerSideProps = async ({ req }) => {
282
+ const { user, isAuthenticated } = await getServerSideAuth(req, {
283
+ issuerUrl: 'http://localhost:3000',
284
+ realm: 'my-realm',
285
+ });
286
+
287
+ if (!isAuthenticated) {
288
+ return { redirect: { destination: '/login', permanent: false } };
289
+ }
290
+
291
+ return {
292
+ props: {
293
+ user: { sub: user!.sub, name: user!.name, email: user!.email },
294
+ },
295
+ };
296
+ };
297
+ ```
298
+
299
+ ### Next.js Middleware
300
+
301
+ ```typescript
302
+ // middleware.ts
303
+ import { NextResponse } from 'next/server';
304
+ import type { NextRequest } from 'next/server';
305
+ import { createNextMiddleware } from 'idenplane-sdk/server';
306
+
307
+ const authMiddleware = createNextMiddleware({
308
+ issuerUrl: 'http://localhost:3000',
309
+ realm: 'my-realm',
310
+ protectedPaths: ['/dashboard', '/api/protected'],
311
+ loginPath: '/login',
312
+ forbiddenPath: '/403',
313
+ });
314
+
315
+ export async function middleware(request: NextRequest) {
316
+ const result = await authMiddleware(request as any);
317
+
318
+ if (result?.redirect) {
319
+ return NextResponse.redirect(new URL(result.redirect, request.url));
320
+ }
321
+
322
+ return NextResponse.next();
323
+ }
324
+
325
+ export const config = {
326
+ matcher: ['/((?!_next|public|favicon.ico).*)'],
327
+ };
328
+ ```
329
+
330
+ ---
331
+
332
+ ## SSR Compatibility
333
+
334
+ The SDK is fully SSR-safe. When `window` is undefined (e.g., in Node.js / Next.js):
335
+ - Storage automatically falls back to `MemoryStorage`
336
+ - `login()` and `logout()` browser redirects throw a safe error
337
+ - `init()` and token operations work without errors
338
+
339
+ ```typescript
340
+ // This works safely in both browser and SSR environments
341
+ const client = new IdenplaneClient({
342
+ url: 'http://localhost:3000',
343
+ realm: 'my-realm',
344
+ clientId: 'my-app',
345
+ redirectUri: '/callback',
346
+ storage: 'memory', // explicit for SSR, or falls back automatically
347
+ });
348
+ ```
349
+
350
+ ---
351
+
352
+ ## API Reference
353
+
354
+ ### `IdenplaneClient`
355
+
356
+ #### Constructor
357
+
358
+ ```typescript
359
+ new IdenplaneClient(config: IdenplaneConfig)
360
+ ```
361
+
362
+ | Option | Type | Default | Description |
363
+ |--------|------|---------|-------------|
364
+ | `url` | `string` | *required* | Idenplane server URL |
365
+ | `realm` | `string` | *required* | Realm name |
366
+ | `clientId` | `string` | *required* | OAuth2 client ID (PUBLIC client) |
367
+ | `redirectUri` | `string` | *required* | Callback URL after login |
368
+ | `scopes` | `string[]` | `['openid', 'profile', 'email']` | OAuth2 scopes to request |
369
+ | `storage` | `'sessionStorage' \| 'localStorage' \| 'memory'` | `'sessionStorage'` | Where to persist tokens |
370
+ | `autoRefresh` | `boolean` | `true` | Automatically refresh tokens before expiry |
371
+ | `refreshBuffer` | `number` | `30` | Seconds before expiry to trigger refresh |
372
+ | `refreshStrategy` | `'rotation' \| 'silent' \| 'eager'` | `'rotation'` | Token refresh strategy |
373
+ | `postLogoutRedirectUri` | `string` | — | URL to redirect after logout |
374
+ | `onLogin` | `(tokens: TokenResponse) => void` | — | Called on successful login |
375
+ | `onLogout` | `() => void` | — | Called on logout |
376
+ | `onError` | `(error: Error) => void` | — | Called on error |
377
+ | `onTokenRefresh` | `(tokens: TokenResponse) => void` | — | Called on token refresh |
378
+
379
+ #### Methods
380
+
381
+ | Method | Returns | Description |
382
+ |--------|---------|-------------|
383
+ | `init()` | `Promise<boolean>` | Initialize client, restore session. Returns `true` if authenticated |
384
+ | `login(options?)` | `Promise<void>` | Redirect to Idenplane login page |
385
+ | `handleCallback(url?)` | `Promise<boolean>` | Exchange authorization code for tokens |
386
+ | `logout()` | `Promise<void>` | Clear tokens and call server logout endpoint |
387
+ | `getAccessToken()` | `string \| null` | Current access token (null if expired) |
388
+ | `getTokenClaims()` | `TokenClaims \| null` | Parsed access token JWT payload |
389
+ | `getIdTokenClaims()` | `TokenClaims \| null` | Parsed ID token JWT payload |
390
+ | `isAuthenticated()` | `boolean` | Whether user has a valid, non-expired access token |
391
+ | `fetchUserInfo()` | `Promise<UserInfo \| null>` | Fetch user info from the server UserInfo endpoint |
392
+ | `getUserInfo()` | `UserInfo \| null` | Cached user info (from ID token or last fetch) |
393
+ | `hasRealmRole(role)` | `boolean` | Check if user has a realm-level role |
394
+ | `hasClientRole(clientId, role)` | `boolean` | Check if user has a client-level role |
395
+ | `hasPermission(permission)` | `boolean` | Check realm or default client role |
396
+ | `getRealmRoles()` | `string[]` | All realm roles for the current user |
397
+ | `getClientRoles(clientId)` | `string[]` | All client roles for a specific client |
398
+ | `refreshTokens()` | `Promise<TokenResponse>` | Manually trigger a token refresh |
399
+ | `on(event, handler)` | `() => void` | Subscribe to SDK events — returns unsubscribe function |
400
+ | `off(event, handler)` | `void` | Unsubscribe from SDK events |
401
+
402
+ #### Events
403
+
404
+ | Event | Payload | Fires When |
405
+ |-------|---------|------------|
406
+ | `login` | `TokenResponse` | After successful login or callback |
407
+ | `logout` | — | After logout completes |
408
+ | `tokenRefresh` | `TokenResponse` | After a silent token refresh |
409
+ | `error` | `Error` | On any authentication error |
410
+ | `ready` | `boolean` | After `init()` completes (`true` if authenticated) |
411
+
412
+ ---
413
+
414
+ ### React
415
+
416
+ Import from `idenplane-sdk/react`.
417
+
418
+ #### `<AuthProvider>`
419
+
420
+ | Prop | Type | Description |
421
+ |------|------|-------------|
422
+ | `client` | `IdenplaneClient` | Pre-built client (mutually exclusive with inline config props) |
423
+ | `serverUrl` | `string` | Idenplane server URL (alternative to `client`) |
424
+ | `realm` | `string` | Realm name (alternative to `client`) |
425
+ | `clientId` | `string` | OAuth2 client ID (alternative to `client`) |
426
+ | `redirectUri` | `string` | Redirect URI (alternative to `client`) |
427
+ | `scope` | `string[]` | OAuth2 scopes |
428
+ | `autoHandleCallback` | `boolean` | Auto-handle `/callback` redirect (default: `true`) |
429
+ | `onReady` | `(authenticated: boolean) => void` | Called when initialization is complete |
430
+ | `onLogin` | `(tokens: TokenResponse) => void` | Called on login |
431
+ | `onLogout` | `() => void` | Called on logout |
432
+ | `onError` | `(error: Error) => void` | Called on error |
433
+ | `onTokenRefresh` | `(tokens: TokenResponse) => void` | Called on token refresh |
434
+
435
+ #### `useAuth()`
436
+
437
+ ```typescript
438
+ const { isAuthenticated, isLoading, login, logout, getToken, user, client } = useAuth();
439
+ ```
440
+
441
+ | Property | Type | Description |
442
+ |----------|------|-------------|
443
+ | `isAuthenticated` | `boolean` | Whether the user is logged in |
444
+ | `isLoading` | `boolean` | `true` during initialization |
445
+ | `login` | `(options?) => Promise<void>` | Trigger login redirect |
446
+ | `logout` | `() => Promise<void>` | Trigger logout |
447
+ | `getToken` | `() => string \| null` | Get current access token |
448
+ | `user` | `UserInfo \| null` | Current user profile |
449
+ | `client` | `IdenplaneClient` | Underlying SDK client instance |
450
+
451
+ #### `useUser()`
452
+
453
+ ```typescript
454
+ const user = useUser();
455
+ // user?.sub, user?.name, user?.email, user?.preferred_username, etc.
456
+ ```
457
+
458
+ Returns the current user's profile information, or `null` if not authenticated.
459
+
460
+ #### `usePermissions()`
461
+
462
+ ```typescript
463
+ const { hasRole, hasPermission, roles } = usePermissions();
464
+
465
+ hasRole('admin'); // boolean — check realm role
466
+ hasPermission('read:reports'); // boolean — check realm or client role
467
+ roles; // string[] — all realm roles
468
+ ```
469
+
470
+ #### `<ProtectedRoute>`
471
+
472
+ | Prop | Type | Description |
473
+ |------|------|-------------|
474
+ | `roles` | `string[]` | Required realm roles (optional) |
475
+ | `fallback` | `ReactNode` | Shown while loading |
476
+ | `onUnauthorized` | `() => ReactNode \| null` | Called when not authenticated |
477
+ | `onForbidden` | `() => ReactNode \| null` | Called when lacking required roles |
478
+
479
+ ---
480
+
481
+ ### Server (`idenplane-sdk/server`)
482
+
483
+ #### `verifyToken(token, config)`
484
+
485
+ Verifies a JWT access token using the server's JWKS endpoint.
486
+
487
+ ```typescript
488
+ const payload = await verifyToken(accessToken, {
489
+ issuerUrl: 'http://localhost:3000',
490
+ realm: 'my-realm',
491
+ });
492
+ ```
493
+
494
+ #### `getServerSideAuth(req, config)`
495
+
496
+ Helper for Next.js API routes and `getServerSideProps`.
497
+
498
+ #### `createNextMiddleware(config)`
499
+
500
+ Factory for Next.js middleware with route protection.
501
+
502
+ #### `createIdenplaneMiddleware(config)`
503
+
504
+ Express middleware for token validation.
505
+
506
+ #### `createIdenplaneGuard(config)`
507
+
508
+ NestJS guard factory for token validation.
509
+
510
+ ---
511
+
512
+ ## Backend Integration
513
+
514
+ ### Express
515
+
516
+ ```typescript
517
+ import express from 'express';
518
+ import { createIdenplaneMiddleware } from 'idenplane-sdk/server';
519
+
520
+ const app = express();
521
+ const idenplane = createIdenplaneMiddleware({
522
+ issuerUrl: 'http://localhost:3000',
523
+ realm: 'my-realm',
524
+ requiredRoles: ['user'], // optional
525
+ });
526
+
527
+ app.get('/api/profile', idenplane, (req: any, res) => {
528
+ res.json(req.user); // IdenplaneTokenPayload
529
+ });
530
+ ```
531
+
532
+ ### NestJS
533
+
534
+ ```typescript
535
+ import { createIdenplaneGuard } from 'idenplane-sdk/server';
536
+
537
+ const IdenplaneGuard = createIdenplaneGuard({
538
+ issuerUrl: 'http://localhost:3000',
539
+ realm: 'my-realm',
540
+ });
541
+
542
+ @Controller('api')
543
+ export class AppController {
544
+ @Get('profile')
545
+ @UseGuards(IdenplaneGuard)
546
+ getProfile(@Req() req) {
547
+ return req.user;
548
+ }
549
+ }
550
+ ```
551
+
552
+ ---
553
+
554
+ ## Attaching Tokens to API Requests
555
+
556
+ ```typescript
557
+ // With fetch
558
+ const res = await fetch('/api/profile', {
559
+ headers: {
560
+ Authorization: `Bearer ${idenplane.getAccessToken()}`,
561
+ },
562
+ });
563
+
564
+ // With axios interceptor
565
+ api.interceptors.request.use((config) => {
566
+ const token = idenplane.getAccessToken();
567
+ if (token) config.headers.Authorization = `Bearer ${token}`;
568
+ return config;
569
+ });
570
+ ```
571
+
572
+ ---
573
+
574
+ ## Full SPA Callback Flow (React Router)
575
+
576
+ ```tsx
577
+ // main.tsx
578
+ import { BrowserRouter, Routes, Route } from 'react-router-dom';
579
+ import { AuthProvider, ProtectedRoute } from 'idenplane-sdk/react';
580
+
581
+ function App() {
582
+ return (
583
+ <AuthProvider
584
+ serverUrl="http://localhost:3000"
585
+ realm="my-realm"
586
+ clientId="my-app"
587
+ redirectUri="http://localhost:5173/callback"
588
+ >
589
+ <BrowserRouter>
590
+ <Routes>
591
+ <Route path="/" element={<Home />} />
592
+ <Route
593
+ path="/dashboard"
594
+ element={
595
+ <ProtectedRoute
596
+ onUnauthorized={() => { window.location.href = '/login'; return null; }}
597
+ >
598
+ <Dashboard />
599
+ </ProtectedRoute>
600
+ }
601
+ />
602
+ <Route path="/login" element={<Login />} />
603
+ </Routes>
604
+ </BrowserRouter>
605
+ </AuthProvider>
606
+ );
607
+ }
608
+ ```
609
+
610
+ ---
611
+
612
+ ## Error Handling
613
+
614
+ ```typescript
615
+ idenplane.on('error', (error) => {
616
+ console.error('Auth error:', error.message);
617
+
618
+ // Common errors:
619
+ // - "No refresh token available" — user needs to re-login
620
+ // - "State mismatch — possible CSRF attack"
621
+ // - "Missing PKCE verifier"
622
+ // - "token_exchange_failed" — authorization code invalid or expired
623
+ });
624
+ ```
625
+
626
+ ---
627
+
628
+ ## Idenplane Client Setup
629
+
630
+ For the SDK to work, register a **PUBLIC** client in Idenplane:
631
+
632
+ 1. Open the Idenplane Admin Console at `/console`
633
+ 2. Navigate to your realm > **Clients** > **Create**
634
+ 3. Set **Client Type** to `PUBLIC`
635
+ 4. Add your app's URL to **Redirect URIs** (e.g., `http://localhost:5173/callback`)
636
+ 5. Add your app's origin to **Web Origins** (e.g., `http://localhost:5173`)
637
+ 6. Enable the `authorization_code` and `refresh_token` grant types
638
+
639
+ ---
640
+
641
+ ## License
642
+
643
+ MIT
644
+
645
+ ---
646
+
647
+ <p align="center">
648
+ Part of <a href="https://idenplane.com">Idenplane</a> — Open-source Identity & Access Management
649
+ </p>
package/package.json ADDED
@@ -0,0 +1,94 @@
1
+ {
2
+ "name": "idenplane-sdk",
3
+ "version": "1.0.1",
4
+ "description": "Client SDK for Idenplane Identity and Access Management Server",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
19
+ },
20
+ "./react": {
21
+ "import": {
22
+ "types": "./dist/react.d.ts",
23
+ "default": "./dist/react.js"
24
+ },
25
+ "require": {
26
+ "types": "./dist/react.d.cts",
27
+ "default": "./dist/react.cjs"
28
+ }
29
+ },
30
+ "./server": {
31
+ "import": {
32
+ "types": "./dist/server.d.ts",
33
+ "default": "./dist/server.js"
34
+ },
35
+ "require": {
36
+ "types": "./dist/server.d.cts",
37
+ "default": "./dist/server.cjs"
38
+ }
39
+ }
40
+ },
41
+ "peerDependencies": {
42
+ "jose": ">=5.0.0",
43
+ "react": ">=18.0.0"
44
+ },
45
+ "peerDependenciesMeta": {
46
+ "react": {
47
+ "optional": true
48
+ },
49
+ "jose": {
50
+ "optional": true
51
+ }
52
+ },
53
+ "scripts": {
54
+ "build": "tsup",
55
+ "dev": "tsup --watch",
56
+ "typecheck": "tsc --noEmit",
57
+ "test": "vitest run",
58
+ "test:watch": "vitest"
59
+ },
60
+ "devDependencies": {
61
+ "@types/react": "^19.0.0",
62
+ "jose": "^6.1.3",
63
+ "react": "^19.0.0",
64
+ "tsup": "^8.4.0",
65
+ "typescript": "^5.7.0",
66
+ "vitest": "^4.1.0"
67
+ },
68
+ "files": [
69
+ "dist",
70
+ "README.md"
71
+ ],
72
+ "keywords": [
73
+ "idenplane",
74
+ "oauth2",
75
+ "oidc",
76
+ "openid-connect",
77
+ "authentication",
78
+ "identity",
79
+ "pkce",
80
+ "react"
81
+ ],
82
+ "license": "MIT",
83
+ "repository": {
84
+ "type": "git",
85
+ "url": "https://github.com/idenplane/idenplane.git",
86
+ "directory": "packages/idenplane-js"
87
+ },
88
+ "publishConfig": {
89
+ "access": "public"
90
+ },
91
+ "overrides": {
92
+ "esbuild": ">=0.28.1"
93
+ }
94
+ }