sentri 4.1.0 → 5.0.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.
package/dist/cli.js CHANGED
@@ -1,14 +1,22 @@
1
1
  #!/usr/bin/env node
2
- import {mkdir,writeFile}from'fs/promises';import {existsSync}from'fs';import {join}from'path';var u=`import { createAuthServer } from 'sentri';
2
+ import {mkdir,writeFile}from'fs/promises';import {existsSync}from'fs';import {join}from'path';var y=Object.defineProperty;var s=(e,o)=>y(e,"name",{value:o,configurable:true});var g={server:{express:`import { createAuthExpress } from 'sentri/express';
3
+ import { PostgresDialect } from 'kysely';
4
+ import pg from 'pg';
5
+
6
+ const { Pool } = pg;
3
7
 
4
8
  type Role = 'admin' | 'user';
5
9
 
6
- export const sentriAuth = createAuthServer<Role>({
10
+ export const sentriAuth = createAuthExpress<Role>({
11
+ mode: 'server',
12
+
7
13
  // -- Roles ------------------------------------------------------------------
8
14
  validRoles: ['admin', 'user'],
9
15
 
10
16
  // -- Database ---------------------------------------------------------------
11
- db: { connectionString: process.env.DATABASE_URL! },
17
+ dialect: new PostgresDialect({
18
+ pool: new Pool({ connectionString: process.env.DATABASE_URL! })
19
+ }),
12
20
 
13
21
  // -- Token ------------------------------------------------------------------
14
22
  accessExpiresIn: process.env.JWT_ACCESS_EXPIRES_IN ?? '15m',
@@ -19,16 +27,16 @@ export const sentriAuth = createAuthServer<Role>({
19
27
  // apiKey: process.env.API_KEY, // uncomment to restrict POST /register
20
28
 
21
29
  // -- Redis (optional) -------------------------------------------------------
22
- // redisUrl: process.env.REDIS_URL, // uncomment to enable distributed idempotency cache
30
+ // redisUrl: process.env.REDIS_URL,
23
31
 
24
32
  // -- Cookie (optional) ------------------------------------------------------
25
- // cookie: { secure: true, sameSite: 'strict' }, // refresh token cookie
26
- // accessCookie: { secure: true, sameSite: 'strict' }, // access token cookie (SPA)
33
+ // cookie: { secure: true, sameSite: 'strict' },
34
+ // accessCookie: { secure: true, sameSite: 'strict' },
27
35
 
28
36
  // -- Hooks (optional) -------------------------------------------------------
29
37
  // hooks: {
30
- // onLogin: (user) => console.log(\`[\${new Date().toISOString()}] login: \${user.identifier}\`),
31
- // onFailedLogin: (identifier) => console.warn(\`failed login attempt: \${identifier}\`),
38
+ // onLogin: (user) => console.log(\`login: \${user.identifier}\`),
39
+ // onFailedLogin: (identifier) => console.warn(\`failed login: \${identifier}\`),
32
40
  // onLogout: (userId) => console.log(\`logout: \${userId}\`),
33
41
  // },
34
42
 
@@ -36,37 +44,243 @@ export const sentriAuth = createAuthServer<Role>({
36
44
  // isTokenRevoked: async (sessionId) => false,
37
45
 
38
46
  // -- Logger (optional) ------------------------------------------------------
39
- // Accepts any logger compatible with pino, winston, or console.
40
- // When omitted, sentri produces no log output.
41
47
  // logger: console,
42
- // loggerService: 'sentri', // default: 'sentri'
48
+ // loggerService: 'sentri',
43
49
  });
44
- `,d=`# -- Server -------------------------------------------------------------------
45
- PORT=3000
50
+ `,fastify:`import { createAuthFastify } from 'sentri/fastify';
51
+ import { PostgresDialect } from 'kysely';
52
+ import pg from 'pg';
46
53
 
47
- # -- Database -----------------------------------------------------------------
48
- DATABASE_URL=postgresql://user:password@localhost:5432/mydb
54
+ const { Pool } = pg;
49
55
 
50
- # -- Token --------------------------------------------------------------------
51
- JWT_ACCESS_EXPIRES_IN=15m
52
- JWT_REFRESH_EXPIRES_IN=7d
56
+ type Role = 'admin' | 'user';
53
57
 
54
- # -- Security -----------------------------------------------------------------
55
- SALT_ROUNDS=12
56
- # API_KEY=your-register-api-key
58
+ export const sentriAuth = createAuthFastify<Role>({
59
+ mode: 'server',
57
60
 
58
- # -- Redis (optional) ---------------------------------------------------------
59
- # REDIS_URL=redis://localhost:6379
60
- `,m=`import { createAuth } from 'sentri';
61
+ // -- Roles ------------------------------------------------------------------
62
+ validRoles: ['admin', 'user'],
63
+
64
+ // -- Database ---------------------------------------------------------------
65
+ dialect: new PostgresDialect({
66
+ pool: new Pool({ connectionString: process.env.DATABASE_URL! })
67
+ }),
68
+
69
+ // -- Token ------------------------------------------------------------------
70
+ accessExpiresIn: process.env.JWT_ACCESS_EXPIRES_IN ?? '15m',
71
+ refreshExpiresIn: process.env.JWT_REFRESH_EXPIRES_IN ?? '7d',
72
+
73
+ // -- Security ---------------------------------------------------------------
74
+ saltRounds: parseInt(process.env.SALT_ROUNDS ?? '12', 10),
75
+ // apiKey: process.env.API_KEY,
76
+
77
+ // -- Redis (optional) -------------------------------------------------------
78
+ // redisUrl: process.env.REDIS_URL,
79
+
80
+ // -- Cookie (optional) ------------------------------------------------------
81
+ // cookie: { secure: true, sameSite: 'strict' },
82
+ // accessCookie: { secure: true, sameSite: 'strict' },
83
+
84
+ // -- Hooks (optional) -------------------------------------------------------
85
+ // hooks: {
86
+ // onLogin: (user) => console.log(\`login: \${user.identifier}\`),
87
+ // onFailedLogin: (identifier) => console.warn(\`failed login: \${identifier}\`),
88
+ // onLogout: (userId) => console.log(\`logout: \${userId}\`),
89
+ // },
90
+
91
+ // -- Token revocation (optional) --------------------------------------------
92
+ // isTokenRevoked: async (sessionId) => false,
93
+
94
+ // -- Logger (optional) ------------------------------------------------------
95
+ // logger: console,
96
+ // loggerService: 'sentri',
97
+ });
98
+ `,hono:`import { createAuthHono } from 'sentri/hono';
99
+ import { PostgresDialect } from 'kysely';
100
+ import pg from 'pg';
101
+
102
+ const { Pool } = pg;
103
+
104
+ type Role = 'admin' | 'user';
105
+
106
+ export const sentriAuth = createAuthHono<Role>({
107
+ mode: 'server',
108
+
109
+ // -- Roles ------------------------------------------------------------------
110
+ validRoles: ['admin', 'user'],
111
+
112
+ // -- Database ---------------------------------------------------------------
113
+ dialect: new PostgresDialect({
114
+ pool: new Pool({ connectionString: process.env.DATABASE_URL! })
115
+ }),
116
+
117
+ // -- Token ------------------------------------------------------------------
118
+ accessExpiresIn: process.env.JWT_ACCESS_EXPIRES_IN ?? '15m',
119
+ refreshExpiresIn: process.env.JWT_REFRESH_EXPIRES_IN ?? '7d',
120
+
121
+ // -- Security ---------------------------------------------------------------
122
+ saltRounds: parseInt(process.env.SALT_ROUNDS ?? '12', 10),
123
+ // apiKey: process.env.API_KEY,
124
+
125
+ // -- Redis (optional) -------------------------------------------------------
126
+ // redisUrl: process.env.REDIS_URL,
127
+
128
+ // -- Cookie (optional) ------------------------------------------------------
129
+ // cookie: { secure: true, sameSite: 'strict' },
130
+ // accessCookie: { secure: true, sameSite: 'strict' },
131
+
132
+ // -- Hooks (optional) -------------------------------------------------------
133
+ // hooks: {
134
+ // onLogin: (user) => console.log(\`login: \${user.identifier}\`),
135
+ // onFailedLogin: (identifier) => console.warn(\`failed login: \${identifier}\`),
136
+ // onLogout: (userId) => console.log(\`logout: \${userId}\`),
137
+ // },
138
+
139
+ // -- Token revocation (optional) --------------------------------------------
140
+ // isTokenRevoked: async (sessionId) => false,
141
+
142
+ // -- Logger (optional) ------------------------------------------------------
143
+ // logger: console,
144
+ // loggerService: 'sentri',
145
+ });
146
+ `,elysia:`import { createAuthElysia } from 'sentri/elysia';
147
+ import { PostgresDialect } from 'kysely';
148
+ import pg from 'pg';
149
+
150
+ const { Pool } = pg;
151
+
152
+ type Role = 'admin' | 'user';
153
+
154
+ export const sentriAuth = createAuthElysia<Role>({
155
+ mode: 'server',
156
+
157
+ // -- Roles ------------------------------------------------------------------
158
+ validRoles: ['admin', 'user'],
159
+
160
+ // -- Database ---------------------------------------------------------------
161
+ dialect: new PostgresDialect({
162
+ pool: new Pool({ connectionString: process.env.DATABASE_URL! })
163
+ }),
164
+
165
+ // -- Token ------------------------------------------------------------------
166
+ accessExpiresIn: process.env.JWT_ACCESS_EXPIRES_IN ?? '15m',
167
+ refreshExpiresIn: process.env.JWT_REFRESH_EXPIRES_IN ?? '7d',
168
+
169
+ // -- Security ---------------------------------------------------------------
170
+ saltRounds: parseInt(process.env.SALT_ROUNDS ?? '12', 10),
171
+ });
172
+ `,koa:`import { createAuthKoa } from 'sentri/koa';
173
+ import { PostgresDialect } from 'kysely';
174
+ import pg from 'pg';
175
+
176
+ const { Pool } = pg;
177
+
178
+ type Role = 'admin' | 'user';
179
+
180
+ export const sentriAuth = createAuthKoa<Role>({
181
+ mode: 'server',
182
+
183
+ // -- Roles ------------------------------------------------------------------
184
+ validRoles: ['admin', 'user'],
185
+
186
+ // -- Database ---------------------------------------------------------------
187
+ dialect: new PostgresDialect({
188
+ pool: new Pool({ connectionString: process.env.DATABASE_URL! })
189
+ }),
190
+
191
+ // -- Token ------------------------------------------------------------------
192
+ accessExpiresIn: process.env.JWT_ACCESS_EXPIRES_IN ?? '15m',
193
+ refreshExpiresIn: process.env.JWT_REFRESH_EXPIRES_IN ?? '7d',
194
+
195
+ // -- Security ---------------------------------------------------------------
196
+ saltRounds: parseInt(process.env.SALT_ROUNDS ?? '12', 10),
197
+ });
198
+ `},client:{express:`import { createAuthExpress } from 'sentri/express';
199
+
200
+ type Role = 'admin' | 'user';
201
+
202
+ export const sentriAuth = createAuthExpress<Role>({
203
+ mode: 'client',
204
+
205
+ // -- Auth server ------------------------------------------------------------
206
+ // URL of the auth server's GET /auth/keys endpoint (JWKS).
207
+ // The server must use RS256 to expose this endpoint.
208
+ keyUri: process.env.AUTH_KEY_URI!,
209
+
210
+ // -- Roles (optional) -------------------------------------------------------
211
+ // Only used for TypeScript type safety on authorize() \u2014 not validated at runtime.
212
+ validRoles: ['admin', 'user'],
213
+
214
+ // -- Logger (optional) ------------------------------------------------------
215
+ // logger: console,
216
+ // loggerService: 'auth-service',
217
+ });
218
+ `,fastify:`import { createAuthFastify } from 'sentri/fastify';
219
+
220
+ type Role = 'admin' | 'user';
221
+
222
+ export const sentriAuth = createAuthFastify<Role>({
223
+ mode: 'client',
224
+
225
+ // -- Auth server ------------------------------------------------------------
226
+ // URL of the auth server's GET /auth/keys endpoint (JWKS).
227
+ keyUri: process.env.AUTH_KEY_URI!,
228
+
229
+ // -- Roles (optional) -------------------------------------------------------
230
+ validRoles: ['admin', 'user'],
231
+
232
+ // -- Logger (optional) ------------------------------------------------------
233
+ // logger: console,
234
+ // loggerService: 'auth-service',
235
+ });
236
+ `,hono:`import { createAuthHono } from 'sentri/hono';
237
+
238
+ type Role = 'admin' | 'user';
239
+
240
+ export const sentriAuth = createAuthHono<Role>({
241
+ mode: 'client',
242
+
243
+ // -- Auth server ------------------------------------------------------------
244
+ // URL of the auth server's GET /auth/keys endpoint (JWKS).
245
+ keyUri: process.env.AUTH_KEY_URI!,
246
+
247
+ // -- Roles (optional) -------------------------------------------------------
248
+ validRoles: ['admin', 'user'],
249
+
250
+ // -- Logger (optional) ------------------------------------------------------
251
+ // logger: console,
252
+ // loggerService: 'auth-service',
253
+ });
254
+ `,elysia:`import { createAuthElysia } from 'sentri/elysia';
255
+
256
+ type Role = 'admin' | 'user';
257
+
258
+ export const sentriAuth = createAuthElysia<Role>({
259
+ mode: 'client',
260
+
261
+ // -- Auth server ------------------------------------------------------------
262
+ // URL of the auth server's GET /auth/keys endpoint (JWKS).
263
+ // The server must use RS256 to expose this endpoint.
264
+ keyUri: process.env.AUTH_KEY_URI!,
265
+
266
+ // -- Roles (optional) -------------------------------------------------------
267
+ // Only used for TypeScript type safety on authorize() \u2014 not validated at runtime.
268
+ validRoles: ['admin', 'user'],
269
+
270
+ // -- Logger (optional) ------------------------------------------------------
271
+ // logger: console,
272
+ // loggerService: 'auth-service',
273
+ });
274
+ `,koa:`import { createAuthKoa } from 'sentri/koa';
61
275
 
62
276
  type Role = 'admin' | 'user';
63
277
 
64
- export const sentriAuth = createAuth<Role>({
278
+ export const sentriAuth = createAuthKoa<Role>({
65
279
  mode: 'client',
66
280
 
67
281
  // -- Auth server ------------------------------------------------------------
68
282
  // URL of the auth server's GET /auth/keys endpoint (JWKS).
69
- // The server must use RS256/RS384/RS512 to expose this endpoint.
283
+ // The server must use RS256 to expose this endpoint.
70
284
  keyUri: process.env.AUTH_KEY_URI!,
71
285
 
72
286
  // -- Roles (optional) -------------------------------------------------------
@@ -74,40 +288,42 @@ export const sentriAuth = createAuth<Role>({
74
288
  validRoles: ['admin', 'user'],
75
289
 
76
290
  // -- Logger (optional) ------------------------------------------------------
77
- // Accepts any logger compatible with pino, winston, or console.
78
- // When omitted, sentri produces no log output.
79
291
  // logger: console,
80
- // loggerService: 'auth-service', // default: 'sentri'
292
+ // loggerService: 'auth-service',
81
293
  });
82
- `,g=`# -- Server -------------------------------------------------------------------
294
+ `}},A=`# -- Server -------------------------------------------------------------------
83
295
  PORT=3000
84
296
 
85
- # -- Auth Server --------------------------------------------------------------
86
- # URL of the auth server's GET /auth/keys endpoint (JWKS).
87
- AUTH_KEY_URI=http://localhost:3000/auth/keys
88
- `;function a(){console.log(`
89
- sentri \u2014 auth/authorization library for Express
297
+ # -- Database -----------------------------------------------------------------
298
+ DATABASE_URL=postgresql://user:password@localhost:5432/mydb
90
299
 
91
- Usage:
92
- npx sentri <command>
300
+ # -- Token --------------------------------------------------------------------
301
+ JWT_ACCESS_EXPIRES_IN=15m
302
+ JWT_REFRESH_EXPIRES_IN=7d
93
303
 
94
- Commands:
95
- init server Generate src/lib/sentri.ts for server mode (PostgreSQL + JWT signing)
96
- init client Generate src/lib/sentri.ts for client mode (JWT verification via JWKS)
304
+ # -- Security -----------------------------------------------------------------
305
+ SALT_ROUNDS=12
306
+ # API_KEY=your-register-api-key
97
307
 
98
- Examples:
99
- npx sentri init server
100
- npx sentri init client
101
- `);}async function s(e,o,n){if(existsSync(e)){console.log(` skip ${n} (already exists)`);return}await writeFile(e,o,"utf8"),console.log(` create ${n}`);}async function v(){let e=process.cwd(),o=join(e,"src","lib");await mkdir(o,{recursive:true}),console.log(`
102
- Generating sentri server mode files...
103
- `),await s(join(o,"sentri.ts"),u,"src/lib/sentri.ts"),await s(join(e,".env.example"),d,".env.example"),console.log(`
308
+ # -- Redis (optional) ---------------------------------------------------------
309
+ # REDIS_URL=redis://localhost:6379
310
+ `,R=`# -- Server -------------------------------------------------------------------
311
+ PORT=3000
312
+
313
+ # -- Auth Server --------------------------------------------------------------
314
+ # URL of the auth server's GET /auth/keys endpoint (JWKS).
315
+ AUTH_KEY_URI=http://localhost:3000/auth/keys
316
+ `,E={server:{express:`
104
317
  Done. Next steps:
105
318
 
106
319
  1. Copy .env.example to .env and fill in your values
107
320
  2. Add to your app entry point:
108
321
 
322
+ import express from 'express';
109
323
  import { sentriAuth } from './lib/sentri.js';
110
324
 
325
+ const app = express();
326
+ app.use(express.json());
111
327
  await sentriAuth.migrate();
112
328
  app.use('/auth', sentriAuth.router());
113
329
  app.use(sentriAuth.errorHandler());
@@ -115,16 +331,184 @@ Done. Next steps:
115
331
  3. Protect routes:
116
332
 
117
333
  app.get('/me', sentriAuth.protect(), (req, res) => res.json(req.user));
118
- `);}async function h(){let e=process.cwd(),o=join(e,"src","lib");await mkdir(o,{recursive:true}),console.log(`
119
- Generating sentri client mode files...
120
- `),await s(join(o,"sentri.ts"),m,"src/lib/sentri.ts"),await s(join(e,".env.example"),g,".env.example"),console.log(`
334
+ `,fastify:`
335
+ Done. Next steps:
336
+
337
+ 1. Copy .env.example to .env and fill in your values
338
+ 2. Install peer deps: npm install fastify @fastify/cookie
339
+ 3. Add to your app entry point:
340
+
341
+ import Fastify from 'fastify';
342
+ import cookie from '@fastify/cookie';
343
+ import { sentriAuth } from './lib/sentri.js';
344
+
345
+ const app = Fastify();
346
+ await app.register(cookie);
347
+ await sentriAuth.migrate();
348
+ await app.register(sentriAuth.plugin(), { prefix: '/auth' });
349
+ app.setErrorHandler(sentriAuth.errorHandler());
350
+
351
+ 4. Protect routes:
352
+
353
+ app.get('/me', { preHandler: sentriAuth.protect() }, async (req) => req.user);
354
+ `,hono:`
355
+ Done. Next steps:
356
+
357
+ 1. Copy .env.example to .env and fill in your values
358
+ 2. Install peer deps: npm install hono
359
+ 3. Add to your app entry point:
360
+
361
+ import { Hono } from 'hono';
362
+ import { sentriAuth } from './lib/sentri.js';
363
+ import type { SentriHonoEnv } from 'sentri/hono';
364
+
365
+ const app = new Hono<SentriHonoEnv>();
366
+ await sentriAuth.migrate();
367
+ app.route('/auth', sentriAuth.router());
368
+ app.onError(sentriAuth.errorHandler());
369
+
370
+ 4. Protect routes:
371
+
372
+ app.get('/me', sentriAuth.protect(), (c) => c.json(c.get('user')));
373
+ `,elysia:`
374
+ Done. Next steps:
375
+
376
+ 1. Copy .env.example to .env and fill in your values
377
+ 2. Install peer deps: npm install elysia
378
+ 3. Add to your app entry point:
379
+
380
+ import { Elysia } from 'elysia';
381
+ import { sentriAuth } from './lib/sentri.js';
382
+
383
+ const app = new Elysia()
384
+ .onError(sentriAuth.errorHandler())
385
+ .group('/auth', app => app.use(sentriAuth.router()))
386
+ .use(sentriAuth.protect())
387
+ .get('/me', ({ user }) => user);
388
+
389
+ 4. Protect routes:
390
+
391
+ app.use(sentriAuth.protect())
392
+ .get('/me', ({ user }) => user);
393
+ `,koa:`
394
+ Done. Next steps:
395
+
396
+ 1. Copy .env.example to .env and fill in your values
397
+ 2. Install peer deps: npm install koa @koa/router koa-bodyparser
398
+ 3. Add to your app entry point:
399
+
400
+ import Koa from 'koa';
401
+ import Router from '@koa/router';
402
+ import bodyParser from 'koa-bodyparser';
403
+ import { sentriAuth } from './lib/sentri.js';
404
+
405
+ const app = new Koa();
406
+ app.use(bodyParser());
407
+ app.use(sentriAuth.errorHandler());
408
+ await sentriAuth.migrate();
409
+
410
+ const rootRouter = new Router();
411
+ rootRouter.use('/auth', sentriAuth.router().routes());
412
+ app.use(rootRouter.routes());
413
+
414
+ 4. Protect routes:
415
+
416
+ rootRouter.get('/me', sentriAuth.protect(), (ctx) => {
417
+ ctx.body = ctx.state.user;
418
+ });
419
+ `},client:{express:`
121
420
  Done. Next steps:
122
421
 
123
422
  1. Copy .env.example to .env and set AUTH_KEY_URI to your auth server's /auth/keys endpoint
124
423
  2. Add to your app entry point:
125
424
 
425
+ import express from 'express';
126
426
  import { sentriAuth } from './lib/sentri.js';
127
427
 
428
+ const app = express();
128
429
  app.get('/protected', sentriAuth.protect(), (req, res) => res.json(req.user));
129
430
  app.use(sentriAuth.errorHandler());
130
- `);}var E=process.argv.slice(2),[r,i]=E;(!r||r==="--help"||r==="-h")&&(a(),process.exit(0));r==="init"?i==="server"?v().catch(e=>{console.error(e),process.exit(1);}):i==="client"?h().catch(e=>{console.error(e),process.exit(1);}):(console.error("Usage: npx sentri init <server|client>"),process.exit(1)):(console.error(`Unknown command: ${r}`),a(),process.exit(1));
431
+ `,fastify:`
432
+ Done. Next steps:
433
+
434
+ 1. Copy .env.example to .env and set AUTH_KEY_URI to your auth server's /auth/keys endpoint
435
+ 2. Install peer deps: npm install fastify
436
+ 3. Add to your app entry point:
437
+
438
+ import Fastify from 'fastify';
439
+ import { sentriAuth } from './lib/sentri.js';
440
+
441
+ const app = Fastify();
442
+ app.get('/protected', { preHandler: sentriAuth.protect() }, async (req) => req.user);
443
+ app.setErrorHandler(sentriAuth.errorHandler());
444
+ `,hono:`
445
+ Done. Next steps:
446
+
447
+ 1. Copy .env.example to .env and set AUTH_KEY_URI to your auth server's /auth/keys endpoint
448
+ 2. Install peer deps: npm install hono
449
+ 3. Add to your app entry point:
450
+
451
+ import { Hono } from 'hono';
452
+ import { sentriAuth } from './lib/sentri.js';
453
+ import type { SentriHonoEnv } from 'sentri/hono';
454
+
455
+ const app = new Hono<SentriHonoEnv>();
456
+ app.get('/protected', sentriAuth.protect(), (c) => c.json(c.get('user')));
457
+ app.onError(sentriAuth.errorHandler());
458
+ `,elysia:`
459
+ Done. Next steps:
460
+
461
+ 1. Copy .env.example to .env and set AUTH_KEY_URI to your auth server's /auth/keys endpoint
462
+ 2. Install peer deps: npm install elysia
463
+ 3. Add to your app entry point:
464
+
465
+ import { Elysia } from 'elysia';
466
+ import { sentriAuth } from './lib/sentri.js';
467
+
468
+ const app = new Elysia()
469
+ .onError(sentriAuth.errorHandler())
470
+ .use(sentriAuth.protect())
471
+ .get('/protected', ({ user }) => user);
472
+ `,koa:`
473
+ Done. Next steps:
474
+
475
+ 1. Copy .env.example to .env and set AUTH_KEY_URI to your auth server's /auth/keys endpoint
476
+ 2. Install peer deps: npm install koa @koa/router
477
+ 3. Add to your app entry point:
478
+
479
+ import Koa from 'koa';
480
+ import Router from '@koa/router';
481
+ import { sentriAuth } from './lib/sentri.js';
482
+
483
+ const app = new Koa();
484
+ app.use(sentriAuth.errorHandler());
485
+
486
+ const rootRouter = new Router();
487
+ rootRouter.get('/protected', sentriAuth.protect(), (ctx) => {
488
+ ctx.body = ctx.state.user;
489
+ });
490
+ app.use(rootRouter.routes());
491
+ `}};function c(){console.log(`
492
+ sentri \u2014 auth/authorization library for Express, Fastify, Hono, Elysia, and Koa
493
+
494
+ Usage:
495
+ npx sentri <command>
496
+
497
+ Commands:
498
+ init [mode] [adapter] Generate src/lib/sentri.ts
499
+
500
+ mode: server (default) | client
501
+ adapter: express (default) | fastify | hono | elysia | koa
502
+
503
+ Examples:
504
+ npx sentri init \u2192 server mode, express adapter
505
+ npx sentri init server \u2192 server mode, express adapter
506
+ npx sentri init server hono \u2192 server mode, hono adapter
507
+ npx sentri init server elysia \u2192 server mode, elysia adapter
508
+ npx sentri init server koa \u2192 server mode, koa adapter
509
+ npx sentri init client \u2192 client mode, express adapter
510
+ npx sentri init client fastify \u2192 client mode, fastify adapter
511
+ npx sentri init client hono \u2192 client mode, hono adapter
512
+ `);}s(c,"help");async function l(e,o,t){if(existsSync(e)){console.log(` skip ${t} (already exists)`);return}await writeFile(e,o,"utf8"),console.log(` create ${t}`);}s(l,"writeIfNotExists");async function S(e,o){let t=["server","client"],i=["express","fastify","hono","elysia","koa"];t.includes(e)||(console.error(`Unknown mode: "${e}". Valid modes: ${t.join(", ")}`),process.exit(1)),i.includes(o)||(console.error(`Unknown adapter: "${o}". Valid adapters: ${i.join(", ")}`),process.exit(1));let a=process.cwd(),p=join(a,"src","lib");await mkdir(p,{recursive:true});let u=g[e][o],d=e==="server"?A:R,m=E[e][o];console.log(`
513
+ Generating sentri ${e} mode files (${o})...
514
+ `),await l(join(p,"sentri.ts"),u,"src/lib/sentri.ts"),await l(join(a,".env.example"),d,".env.example"),console.log(m);}s(S,"init");var x=process.argv.slice(2),[r,k,_]=x;(!r||r==="--help"||r==="-h")&&(c(),process.exit(0));r==="init"?S(k??"server",_??"express").catch(t=>{console.error(t),process.exit(1);}):(console.error(`Unknown command: ${r}`),c(),process.exit(1));
@@ -0,0 +1 @@
1
+ 'use strict';var t=Object.defineProperty;var N=(I,E)=>t(I,"name",{value:E,configurable:true});var O=Object.assign(Object.create(null),{UNAUTHORIZED:401,TOKEN_EXPIRED:401,TOKEN_INVALID:401,INVALID_CREDENTIALS:401,FORBIDDEN:403,USER_NOT_FOUND:404,IDENTIFIER_NOT_FOUND:404,USER_ALREADY_EXISTS:409,IDENTIFIER_ALREADY_EXISTS:409,INVALID_ROLE:400,VALIDATION_ERROR:400,CONFIGURATION_ERROR:500,TOKEN_REUSE:401}),R=class extends Error{static{N(this,"SentriError");}code;statusCode;constructor(E,T,_){super(T),this.name="SentriError",this.code=E,this.statusCode=_??O[E]??500;}};exports.SENTRI_ERROR_STATUS=O;exports.SentriError=R;