sentri 2.0.0 → 4.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/README.md +372 -548
- package/dist/cli.js +112 -13
- package/dist/index.d.ts +303 -750
- package/dist/index.js +1 -1
- package/package.json +7 -12
- package/templates/drizzle/adapter.ts +0 -154
- package/templates/drizzle/auth.ts +0 -125
- package/templates/drizzle/schema.ts +0 -47
- package/templates/prisma/adapter.ts +0 -122
- package/templates/prisma/auth.ts +0 -128
- package/templates/prisma/schema.prisma +0 -56
package/templates/prisma/auth.ts
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
// sentri — auth config template (Prisma)
|
|
2
|
-
// Generated by: npx sentri generate prisma
|
|
3
|
-
//
|
|
4
|
-
// Update validRoles to match the roles your application uses.
|
|
5
|
-
// Add JWT_SECRET to your .env file.
|
|
6
|
-
// If you already have a PrismaClient instance elsewhere, import it instead of
|
|
7
|
-
// creating a new one here.
|
|
8
|
-
|
|
9
|
-
import { PrismaClient } from '@prisma/client';
|
|
10
|
-
import { createAuth } from 'sentri';
|
|
11
|
-
import { createAdapter } from './adapter.js';
|
|
12
|
-
|
|
13
|
-
const prisma = new PrismaClient();
|
|
14
|
-
|
|
15
|
-
export const auth = createAuth({
|
|
16
|
-
secret: process.env.JWT_SECRET!,
|
|
17
|
-
validRoles: ['user', 'admin'] as const,
|
|
18
|
-
adapter: createAdapter(prisma),
|
|
19
|
-
accessExpiresIn: '5m', // short-lived; silent refresh happens automatically in protect()
|
|
20
|
-
// refreshExpiresIn: '7d',
|
|
21
|
-
// algorithm: 'HS256',
|
|
22
|
-
// saltRounds: 12,
|
|
23
|
-
// apiKey: process.env.REGISTER_API_KEY, // when set, POST /register requires X-Api-Key header
|
|
24
|
-
|
|
25
|
-
// Access token stored in a non-httpOnly cookie — browser JS can read it via
|
|
26
|
-
// document.cookie or getCurrentAccessToken(req). protect() reads from this
|
|
27
|
-
// cookie automatically when no Authorization header is present.
|
|
28
|
-
accessCookie: {
|
|
29
|
-
secure: process.env.NODE_ENV === 'production',
|
|
30
|
-
// name: 'access_token',
|
|
31
|
-
// sameSite: 'strict',
|
|
32
|
-
// path: '/',
|
|
33
|
-
},
|
|
34
|
-
|
|
35
|
-
// Refresh token stored in an httpOnly cookie — not readable by JS.
|
|
36
|
-
cookie: {
|
|
37
|
-
secure: process.env.NODE_ENV === 'production',
|
|
38
|
-
// name: 'refresh_token',
|
|
39
|
-
// httpOnly: true,
|
|
40
|
-
// sameSite: 'strict',
|
|
41
|
-
// path: '/',
|
|
42
|
-
},
|
|
43
|
-
|
|
44
|
-
// hooks: {
|
|
45
|
-
// // Fired after every successful login — good for audit logs, notifications.
|
|
46
|
-
// onLogin: async (user) => {
|
|
47
|
-
// await auditLog.record('login', user.id);
|
|
48
|
-
// },
|
|
49
|
-
// // Fired after every failed login — good for rate limiting, alerting.
|
|
50
|
-
// onFailedLogin: (identifier, error) => {
|
|
51
|
-
// rateLimiter.hit(`login:${identifier}`);
|
|
52
|
-
// },
|
|
53
|
-
// // Fired after logout (single session or all sessions).
|
|
54
|
-
// onLogout: async (userId) => {
|
|
55
|
-
// await cache.invalidate(userId);
|
|
56
|
-
// },
|
|
57
|
-
// },
|
|
58
|
-
|
|
59
|
-
// isTokenRevoked: async (sessionId) => {
|
|
60
|
-
// // Optional: immediate revocation via Redis (called on every protected request).
|
|
61
|
-
// // Keep this fast — a slow check negates the performance benefit of stateless JWTs.
|
|
62
|
-
// return await redis.sismember('revoked_sessions', sessionId);
|
|
63
|
-
// },
|
|
64
|
-
|
|
65
|
-
// router: {
|
|
66
|
-
// register: async (input) => {
|
|
67
|
-
// // custom register logic — must return RegisterResult
|
|
68
|
-
// },
|
|
69
|
-
// login: async (input) => {
|
|
70
|
-
// // custom login logic — must return AuthResult
|
|
71
|
-
// },
|
|
72
|
-
// refresh: async (refreshToken) => {
|
|
73
|
-
// // custom refresh logic — must return RefreshResult
|
|
74
|
-
// },
|
|
75
|
-
// logout: async (refreshToken) => {
|
|
76
|
-
// // custom logout logic
|
|
77
|
-
// },
|
|
78
|
-
// logoutAll: async (userId) => {
|
|
79
|
-
// // custom logout-all logic
|
|
80
|
-
// },
|
|
81
|
-
// assignRoles: async (userId, roles) => {
|
|
82
|
-
// // custom assignRoles logic — must return AssignRolesResult
|
|
83
|
-
// },
|
|
84
|
-
// },
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
// --- Express app setup ---
|
|
88
|
-
//
|
|
89
|
-
// import express from 'express';
|
|
90
|
-
// import { SentriError, createIdempotencyMiddleware, getCurrentAccessToken } from 'sentri';
|
|
91
|
-
//
|
|
92
|
-
// const app = express();
|
|
93
|
-
// app.use(express.json());
|
|
94
|
-
//
|
|
95
|
-
// // Optional: make create/update operations idempotent via X-Idempotency-Key header
|
|
96
|
-
// app.use(createIdempotencyMiddleware());
|
|
97
|
-
//
|
|
98
|
-
// // Mount the auth router (POST /auth/register, /auth/login, etc.)
|
|
99
|
-
// app.use('/auth', auth.router());
|
|
100
|
-
//
|
|
101
|
-
// // Your own routes — protect() reads token from Authorization header OR access_token cookie
|
|
102
|
-
// app.get('/protected', auth.protect(), (req, res) => {
|
|
103
|
-
// res.json(req.user);
|
|
104
|
-
// });
|
|
105
|
-
//
|
|
106
|
-
// // Read the raw access token if needed (header → cookie fallback)
|
|
107
|
-
// app.get('/debug', (req, res) => {
|
|
108
|
-
// const token = auth.getCurrentAccessToken(req); // or: getCurrentAccessToken(req, config)
|
|
109
|
-
// res.json({ hasToken: !!token });
|
|
110
|
-
// });
|
|
111
|
-
//
|
|
112
|
-
// // Domain-specific error by extending SentriError
|
|
113
|
-
// class NotFoundError extends SentriError {
|
|
114
|
-
// constructor(resource: string) {
|
|
115
|
-
// super('NOT_FOUND', `${resource} not found`, 404);
|
|
116
|
-
// }
|
|
117
|
-
// }
|
|
118
|
-
//
|
|
119
|
-
// app.get('/items/:id', auth.protect(), async (req, res) => {
|
|
120
|
-
// const item = await prisma.item.findUnique({ where: { id: req.params['id'] } });
|
|
121
|
-
// if (!item) throw new NotFoundError('Item');
|
|
122
|
-
// res.json(item);
|
|
123
|
-
// });
|
|
124
|
-
//
|
|
125
|
-
// // Mount AFTER all routes — catches SentriError from sentri AND your subclasses
|
|
126
|
-
// app.use(auth.errorHandler());
|
|
127
|
-
//
|
|
128
|
-
// app.listen(3000);
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
// sentri — Prisma schema template (Prisma v7+)
|
|
2
|
-
// Run `npx sentri init` to copy this file to your project.
|
|
3
|
-
//
|
|
4
|
-
// Field mapping: library uses `identifier` internally, but your DB column
|
|
5
|
-
// can be named anything — adjust the @map(...) values below to match
|
|
6
|
-
// your existing schema, or leave them as-is for a fresh project.
|
|
7
|
-
//
|
|
8
|
-
// Database and generator config lives in prisma.config.ts (Prisma v7+).
|
|
9
|
-
|
|
10
|
-
model User {
|
|
11
|
-
id String @id @default(cuid()) @map("id")
|
|
12
|
-
// Change @map("email") to match your column name:
|
|
13
|
-
// @map("email") — login via email
|
|
14
|
-
// @map("username") — login via username
|
|
15
|
-
// @map("phone") — login via phone number
|
|
16
|
-
identifier String @unique @map("email")
|
|
17
|
-
passwordHash String @map("password_hash")
|
|
18
|
-
createdAt DateTime @default(now()) @map("created_at")
|
|
19
|
-
updatedAt DateTime @updatedAt @map("updated_at")
|
|
20
|
-
|
|
21
|
-
userRoles UserRole[]
|
|
22
|
-
sessions Session[]
|
|
23
|
-
|
|
24
|
-
@@map("users")
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
model Role {
|
|
28
|
-
id String @id @default(cuid()) @map("id")
|
|
29
|
-
name String @unique @map("name")
|
|
30
|
-
|
|
31
|
-
userRoles UserRole[]
|
|
32
|
-
|
|
33
|
-
@@map("roles")
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
model UserRole {
|
|
37
|
-
userId String @map("user_id")
|
|
38
|
-
roleId String @map("role_id")
|
|
39
|
-
|
|
40
|
-
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
41
|
-
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
|
|
42
|
-
|
|
43
|
-
@@id([userId, roleId])
|
|
44
|
-
@@map("user_roles")
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
model Session {
|
|
48
|
-
id String @id @default(cuid()) @map("id")
|
|
49
|
-
userId String @map("user_id")
|
|
50
|
-
expiresAt DateTime @map("expires_at")
|
|
51
|
-
createdAt DateTime @default(now()) @map("created_at")
|
|
52
|
-
|
|
53
|
-
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
54
|
-
|
|
55
|
-
@@map("sessions")
|
|
56
|
-
}
|