sentri 4.1.1 → 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.cjs ADDED
@@ -0,0 +1,514 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';var promises=require('fs/promises'),fs=require('fs'),path=require('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;
7
+
8
+ type Role = 'admin' | 'user';
9
+
10
+ export const sentriAuth = createAuthExpress<Role>({
11
+ mode: 'server',
12
+
13
+ // -- Roles ------------------------------------------------------------------
14
+ validRoles: ['admin', 'user'],
15
+
16
+ // -- Database ---------------------------------------------------------------
17
+ dialect: new PostgresDialect({
18
+ pool: new Pool({ connectionString: process.env.DATABASE_URL! })
19
+ }),
20
+
21
+ // -- Token ------------------------------------------------------------------
22
+ accessExpiresIn: process.env.JWT_ACCESS_EXPIRES_IN ?? '15m',
23
+ refreshExpiresIn: process.env.JWT_REFRESH_EXPIRES_IN ?? '7d',
24
+
25
+ // -- Security ---------------------------------------------------------------
26
+ saltRounds: parseInt(process.env.SALT_ROUNDS ?? '12', 10),
27
+ // apiKey: process.env.API_KEY, // uncomment to restrict POST /register
28
+
29
+ // -- Redis (optional) -------------------------------------------------------
30
+ // redisUrl: process.env.REDIS_URL,
31
+
32
+ // -- Cookie (optional) ------------------------------------------------------
33
+ // cookie: { secure: true, sameSite: 'strict' },
34
+ // accessCookie: { secure: true, sameSite: 'strict' },
35
+
36
+ // -- Hooks (optional) -------------------------------------------------------
37
+ // hooks: {
38
+ // onLogin: (user) => console.log(\`login: \${user.identifier}\`),
39
+ // onFailedLogin: (identifier) => console.warn(\`failed login: \${identifier}\`),
40
+ // onLogout: (userId) => console.log(\`logout: \${userId}\`),
41
+ // },
42
+
43
+ // -- Token revocation (optional) --------------------------------------------
44
+ // isTokenRevoked: async (sessionId) => false,
45
+
46
+ // -- Logger (optional) ------------------------------------------------------
47
+ // logger: console,
48
+ // loggerService: 'sentri',
49
+ });
50
+ `,fastify:`import { createAuthFastify } from 'sentri/fastify';
51
+ import { PostgresDialect } from 'kysely';
52
+ import pg from 'pg';
53
+
54
+ const { Pool } = pg;
55
+
56
+ type Role = 'admin' | 'user';
57
+
58
+ export const sentriAuth = createAuthFastify<Role>({
59
+ mode: 'server',
60
+
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';
275
+
276
+ type Role = 'admin' | 'user';
277
+
278
+ export const sentriAuth = createAuthKoa<Role>({
279
+ mode: 'client',
280
+
281
+ // -- Auth server ------------------------------------------------------------
282
+ // URL of the auth server's GET /auth/keys endpoint (JWKS).
283
+ // The server must use RS256 to expose this endpoint.
284
+ keyUri: process.env.AUTH_KEY_URI!,
285
+
286
+ // -- Roles (optional) -------------------------------------------------------
287
+ // Only used for TypeScript type safety on authorize() \u2014 not validated at runtime.
288
+ validRoles: ['admin', 'user'],
289
+
290
+ // -- Logger (optional) ------------------------------------------------------
291
+ // logger: console,
292
+ // loggerService: 'auth-service',
293
+ });
294
+ `}},A=`# -- Server -------------------------------------------------------------------
295
+ PORT=3000
296
+
297
+ # -- Database -----------------------------------------------------------------
298
+ DATABASE_URL=postgresql://user:password@localhost:5432/mydb
299
+
300
+ # -- Token --------------------------------------------------------------------
301
+ JWT_ACCESS_EXPIRES_IN=15m
302
+ JWT_REFRESH_EXPIRES_IN=7d
303
+
304
+ # -- Security -----------------------------------------------------------------
305
+ SALT_ROUNDS=12
306
+ # API_KEY=your-register-api-key
307
+
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:`
317
+ Done. Next steps:
318
+
319
+ 1. Copy .env.example to .env and fill in your values
320
+ 2. Add to your app entry point:
321
+
322
+ import express from 'express';
323
+ import { sentriAuth } from './lib/sentri.js';
324
+
325
+ const app = express();
326
+ app.use(express.json());
327
+ await sentriAuth.migrate();
328
+ app.use('/auth', sentriAuth.router());
329
+ app.use(sentriAuth.errorHandler());
330
+
331
+ 3. Protect routes:
332
+
333
+ app.get('/me', sentriAuth.protect(), (req, res) => res.json(req.user));
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:`
420
+ Done. Next steps:
421
+
422
+ 1. Copy .env.example to .env and set AUTH_KEY_URI to your auth server's /auth/keys endpoint
423
+ 2. Add to your app entry point:
424
+
425
+ import express from 'express';
426
+ import { sentriAuth } from './lib/sentri.js';
427
+
428
+ const app = express();
429
+ app.get('/protected', sentriAuth.protect(), (req, res) => res.json(req.user));
430
+ app.use(sentriAuth.errorHandler());
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(fs.existsSync(e)){console.log(` skip ${t} (already exists)`);return}await promises.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=path.join(a,"src","lib");await promises.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(path.join(p,"sentri.ts"),u,"src/lib/sentri.ts"),await l(path.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));
package/dist/cli.d.cts ADDED
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node