sentri 2.0.0 → 2.1.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,19 +1,118 @@
1
1
  #!/usr/bin/env node
2
- import {existsSync,mkdirSync,copyFileSync,writeFileSync,readFileSync}from'fs';import {dirname,join}from'path';import {fileURLToPath}from'url';var x=dirname(fileURLToPath(import.meta.url)),C=["generate"],y=["prisma","drizzle"];function g(){console.log(`
2
+ import {mkdir,writeFile}from'fs/promises';import {existsSync}from'fs';import {join}from'path';var u=`import { createAuthServer } from 'sentri';
3
+
4
+ type Role = 'admin' | 'user';
5
+
6
+ export const sentriAuth = createAuthServer<Role>({
7
+ // -- Roles ------------------------------------------------------------------
8
+ validRoles: ['admin', 'user'],
9
+
10
+ // -- Database ---------------------------------------------------------------
11
+ db: { connectionString: process.env.DATABASE_URL! },
12
+
13
+ // -- Token ------------------------------------------------------------------
14
+ accessExpiresIn: process.env.JWT_ACCESS_EXPIRES_IN ?? '15m',
15
+ refreshExpiresIn: process.env.JWT_REFRESH_EXPIRES_IN ?? '7d',
16
+
17
+ // -- Security ---------------------------------------------------------------
18
+ saltRounds: parseInt(process.env.SALT_ROUNDS ?? '12', 10),
19
+ // apiKey: process.env.API_KEY, // uncomment to restrict POST /register
20
+
21
+ // -- Redis (optional) -------------------------------------------------------
22
+ // redisUrl: process.env.REDIS_URL, // uncomment to enable distributed idempotency cache
23
+
24
+ // -- Cookie (optional) ------------------------------------------------------
25
+ // cookie: { secure: true, sameSite: 'strict' }, // refresh token cookie
26
+ // accessCookie: { secure: true, sameSite: 'strict' }, // access token cookie (SPA)
27
+
28
+ // -- Hooks (optional) -------------------------------------------------------
29
+ // hooks: {
30
+ // onLogin: (user) => console.log(\`[\${new Date().toISOString()}] login: \${user.identifier}\`),
31
+ // onFailedLogin: (identifier) => console.warn(\`failed login attempt: \${identifier}\`),
32
+ // onLogout: (userId) => console.log(\`logout: \${userId}\`),
33
+ // },
34
+
35
+ // -- Token revocation (optional) --------------------------------------------
36
+ // isTokenRevoked: async (sessionId) => false,
37
+ });
38
+ `,d=`# -- Server -------------------------------------------------------------------
39
+ PORT=3000
40
+
41
+ # -- Database -----------------------------------------------------------------
42
+ DATABASE_URL=postgresql://user:password@localhost:5432/mydb
43
+
44
+ # -- Token --------------------------------------------------------------------
45
+ JWT_ACCESS_EXPIRES_IN=15m
46
+ JWT_REFRESH_EXPIRES_IN=7d
47
+
48
+ # -- Security -----------------------------------------------------------------
49
+ SALT_ROUNDS=12
50
+ # API_KEY=your-register-api-key
51
+
52
+ # -- Redis (optional) ---------------------------------------------------------
53
+ # REDIS_URL=redis://localhost:6379
54
+ `,m=`import { createAuth } from 'sentri';
55
+
56
+ type Role = 'admin' | 'user';
57
+
58
+ export const sentriAuth = createAuth<Role>({
59
+ mode: 'client',
60
+
61
+ // -- Auth server ------------------------------------------------------------
62
+ // URL of the auth server's GET /auth/keys endpoint (JWKS).
63
+ // The server must use RS256/RS384/RS512 to expose this endpoint.
64
+ keyUri: process.env.AUTH_KEY_URI!,
65
+
66
+ // -- Roles (optional) -------------------------------------------------------
67
+ // Only used for TypeScript type safety on authorize() \u2014 not validated at runtime.
68
+ validRoles: ['admin', 'user'],
69
+ });
70
+ `,v=`# -- Server -------------------------------------------------------------------
71
+ PORT=3000
72
+
73
+ # -- Auth Server --------------------------------------------------------------
74
+ # URL of the auth server's GET /auth/keys endpoint (JWKS).
75
+ AUTH_KEY_URI=http://localhost:3000/auth/keys
76
+ `;function c(){console.log(`
3
77
  sentri \u2014 auth/authorization library for Express
4
78
 
5
79
  Usage:
6
- npx sentri <command> [options]
80
+ npx sentri <command>
7
81
 
8
82
  Commands:
9
- generate <prisma|drizzle>
10
- Generate adapter, auth config, and schema templates
11
- in src/lib/sentri/ and create a barrel at src/lib/index.ts
12
- `);}function b(s,t,r,a){if(existsSync(s))if(mkdirSync(dirname(t),{recursive:true}),!existsSync(t))copyFileSync(s,t),console.log(`Created ${a}`);else {let o=readFileSync(s,"utf-8").split(`
13
- `),f=o.findIndex(l=>l.startsWith(r));if(f!==-1){let l=o.slice(f).join(`
14
- `).trimEnd(),S=readFileSync(t,"utf-8");writeFileSync(t,S.trimEnd()+`
15
-
16
- `+l+`
17
- `),console.log(`Updated ${a} (tables appended)`);}}}function R(s){(!s||!y.includes(s))&&(console.error(`Error: specify an ORM \u2014 usage: sentri generate <${y.join("|")}>`),process.exit(1));let t=join(x,"..","templates",s),r=join(process.cwd(),"src","lib","sentri"),a=join(r,"adapter.ts"),c=join(r,"auth.ts"),o=join(process.cwd(),"src","lib","index.ts");existsSync(t)||(console.error(`Error: templates for "${s}" not found. Try reinstalling sentri.`),process.exit(1)),(existsSync(a)||existsSync(c))&&(console.error("Error: files already exist in src/lib/sentri/. Remove them first if you want to regenerate."),process.exit(1)),mkdirSync(r,{recursive:true}),copyFileSync(join(t,"adapter.ts"),a),copyFileSync(join(t,"auth.ts"),c),console.log("Created src/lib/sentri/adapter.ts"),console.log("Created src/lib/sentri/auth.ts"),s==="prisma"?b(join(x,"..","templates","prisma","schema.prisma"),join(process.cwd(),"prisma","schema.prisma"),"model ","prisma/schema.prisma"):b(join(t,"schema.ts"),join(r,"schema.ts"),"export ","src/lib/sentri/schema.ts"),existsSync(o)?console.log("Skipped src/lib/index.ts (already exists)"):(mkdirSync(dirname(o),{recursive:true}),writeFileSync(o,`export { createAdapter } from './sentri/adapter.js';
18
- export { auth } from './sentri/auth.js';
19
- `),console.log("Created src/lib/index.ts")),console.log(""),console.log("Next steps:"),s==="prisma"?(console.log(' 1. Edit prisma/schema.prisma \u2014 change @map("email") to match your column name'),console.log(" 2. Set DATABASE_URL and JWT_SECRET in your .env file"),console.log(" 3. Run: npx prisma migrate dev && npx prisma generate"),console.log(" 4. Edit src/lib/sentri/auth.ts \u2014 update validRoles to match your app")):(console.log(" 1. Edit src/lib/sentri/schema.ts \u2014 change text('email') to match your column name"),console.log(" 2. Edit src/lib/sentri/auth.ts \u2014 update validRoles to match your app"),console.log(" 3. Set JWT_SECRET in your .env file")),console.log(" Mount the router in your Express app:"),console.log(" import { auth } from './lib/sentri/auth.js';"),console.log(" app.use('/auth', auth.router());"),console.log("");}var[,,i,...d]=process.argv;(!i||i==="--help"||i==="-h")&&(g(),process.exit(0));C.includes(i)||(console.error(`Unknown command: ${i}`),g(),process.exit(1));(d.includes("--help")||d.includes("-h"))&&(g(),process.exit(0));i==="generate"&&R(d[0]);
83
+ init server Generate src/lib/sentri.ts for server mode (PostgreSQL + JWT signing)
84
+ init client Generate src/lib/sentri.ts for client mode (JWT verification via JWKS)
85
+
86
+ Examples:
87
+ npx sentri init server
88
+ npx sentri init client
89
+ `);}async function o(e,t,n){if(existsSync(e)){console.log(` skip ${n} (already exists)`);return}await writeFile(e,t,"utf8"),console.log(` create ${n}`);}async function E(){let e=process.cwd(),t=join(e,"src","lib");await mkdir(t,{recursive:true}),console.log(`
90
+ Generating sentri server mode files...
91
+ `),await o(join(t,"sentri.ts"),u,"src/lib/sentri.ts"),await o(join(e,".env.example"),d,".env.example"),console.log(`
92
+ Done. Next steps:
93
+
94
+ 1. Copy .env.example to .env and fill in your values
95
+ 2. Add to your app entry point:
96
+
97
+ import { sentriAuth } from './lib/sentri.js';
98
+
99
+ await sentriAuth.migrate();
100
+ app.use('/auth', sentriAuth.router());
101
+ app.use(sentriAuth.errorHandler());
102
+
103
+ 3. Protect routes:
104
+
105
+ app.get('/me', sentriAuth.protect(), (req, res) => res.json(req.user));
106
+ `);}async function S(){let e=process.cwd(),t=join(e,"src","lib");await mkdir(t,{recursive:true}),console.log(`
107
+ Generating sentri client mode files...
108
+ `),await o(join(t,"sentri.ts"),m,"src/lib/sentri.ts"),await o(join(e,".env.example"),v,".env.example"),console.log(`
109
+ Done. Next steps:
110
+
111
+ 1. Copy .env.example to .env and set AUTH_KEY_URI to your auth server's /auth/keys endpoint
112
+ 2. Add to your app entry point:
113
+
114
+ import { sentriAuth } from './lib/sentri.js';
115
+
116
+ app.get('/protected', sentriAuth.protect(), (req, res) => res.json(req.user));
117
+ app.use(sentriAuth.errorHandler());
118
+ `);}var h=process.argv.slice(2),[s,i]=h;(!s||s==="--help"||s==="-h")&&(c(),process.exit(0));s==="init"?i==="server"?E().catch(e=>{console.error(e),process.exit(1);}):i==="client"?S().catch(e=>{console.error(e),process.exit(1);}):(console.error("Usage: npx sentri init <server|client>"),process.exit(1)):(console.error(`Unknown command: ${s}`),c(),process.exit(1));