sentri 1.1.2 → 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.
Files changed (64) hide show
  1. package/README.md +268 -448
  2. package/dist/cli.d.ts +0 -2
  3. package/dist/cli.js +113 -107
  4. package/dist/index.d.ts +545 -11
  5. package/dist/index.js +1 -5
  6. package/package.json +9 -7
  7. package/dist/cli.d.ts.map +0 -1
  8. package/dist/cli.js.map +0 -1
  9. package/dist/client.d.ts +0 -160
  10. package/dist/client.d.ts.map +0 -1
  11. package/dist/client.js +0 -45
  12. package/dist/client.js.map +0 -1
  13. package/dist/errors/AuthError.d.ts +0 -99
  14. package/dist/errors/AuthError.d.ts.map +0 -1
  15. package/dist/errors/AuthError.js +0 -97
  16. package/dist/errors/AuthError.js.map +0 -1
  17. package/dist/index.d.ts.map +0 -1
  18. package/dist/index.js.map +0 -1
  19. package/dist/libs/config.d.ts +0 -62
  20. package/dist/libs/config.d.ts.map +0 -1
  21. package/dist/libs/config.js +0 -97
  22. package/dist/libs/config.js.map +0 -1
  23. package/dist/libs/hash.d.ts +0 -17
  24. package/dist/libs/hash.d.ts.map +0 -1
  25. package/dist/libs/hash.js +0 -22
  26. package/dist/libs/hash.js.map +0 -1
  27. package/dist/libs/token.d.ts +0 -46
  28. package/dist/libs/token.d.ts.map +0 -1
  29. package/dist/libs/token.js +0 -118
  30. package/dist/libs/token.js.map +0 -1
  31. package/dist/middleware/authorize.d.ts +0 -18
  32. package/dist/middleware/authorize.d.ts.map +0 -1
  33. package/dist/middleware/authorize.js +0 -30
  34. package/dist/middleware/authorize.js.map +0 -1
  35. package/dist/middleware/errorHandler.d.ts +0 -71
  36. package/dist/middleware/errorHandler.d.ts.map +0 -1
  37. package/dist/middleware/errorHandler.js +0 -74
  38. package/dist/middleware/errorHandler.js.map +0 -1
  39. package/dist/middleware/permit.d.ts +0 -62
  40. package/dist/middleware/permit.d.ts.map +0 -1
  41. package/dist/middleware/permit.js +0 -61
  42. package/dist/middleware/permit.js.map +0 -1
  43. package/dist/middleware/protect.d.ts +0 -31
  44. package/dist/middleware/protect.d.ts.map +0 -1
  45. package/dist/middleware/protect.js +0 -54
  46. package/dist/middleware/protect.js.map +0 -1
  47. package/dist/middleware/router.d.ts +0 -34
  48. package/dist/middleware/router.d.ts.map +0 -1
  49. package/dist/middleware/router.js +0 -264
  50. package/dist/middleware/router.js.map +0 -1
  51. package/dist/services/auth.d.ts +0 -85
  52. package/dist/services/auth.d.ts.map +0 -1
  53. package/dist/services/auth.js +0 -173
  54. package/dist/services/auth.js.map +0 -1
  55. package/dist/types/auth.d.ts +0 -450
  56. package/dist/types/auth.d.ts.map +0 -1
  57. package/dist/types/auth.js +0 -21
  58. package/dist/types/auth.js.map +0 -1
  59. package/templates/drizzle/adapter.ts +0 -154
  60. package/templates/drizzle/auth.ts +0 -82
  61. package/templates/drizzle/schema.ts +0 -47
  62. package/templates/prisma/adapter.ts +0 -122
  63. package/templates/prisma/auth.ts +0 -85
  64. package/templates/prisma/schema.prisma +0 -56
@@ -1,82 +0,0 @@
1
- // sentri — auth config template (Drizzle)
2
- // Generated by: npx sentri generate drizzle
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 db instance defined elsewhere, import it instead.
7
-
8
- import { createAuth } from 'sentri';
9
- import { db } from '../db.js'; // adjust path to your db instance
10
- import { createAdapter } from './adapter.js';
11
-
12
- export const auth = createAuth({
13
- secret: process.env.JWT_SECRET!,
14
- validRoles: ['user', 'admin'] as const,
15
- adapter: createAdapter(db),
16
- // accessExpiresIn: '15m',
17
- // refreshExpiresIn: '7d',
18
- // algorithm: 'HS256',
19
- // saltRounds: 12,
20
- // apiKey: process.env.REGISTER_API_KEY, // when set, POST /register requires X-Api-Key header
21
- cookie: {
22
- secure: process.env.NODE_ENV === 'production',
23
- // name: 'refresh_token',
24
- // httpOnly: true,
25
- // sameSite: 'strict',
26
- // path: '/',
27
- },
28
- // router: {
29
- // register: async (input) => {
30
- // // custom register logic — must return SignupResult
31
- // },
32
- // login: async (input) => {
33
- // // custom login logic — must return AuthResult
34
- // },
35
- // refresh: async (refreshToken) => {
36
- // // custom refresh logic — must return RefreshResult
37
- // },
38
- // logout: async (refreshToken) => {
39
- // // custom logout logic
40
- // },
41
- // logoutAll: async (userId) => {
42
- // // custom logout-all logic
43
- // },
44
- // assignRoles: async (userId, roles) => {
45
- // // custom assignRoles logic — must return AssignRolesResult
46
- // },
47
- // },
48
- });
49
-
50
- // --- Express app setup ---
51
- //
52
- // import express from 'express';
53
- // import { SentriError } from 'sentri';
54
- //
55
- // const app = express();
56
- // app.use(express.json());
57
- //
58
- // // Mount the auth router (POST /auth/register, /auth/login, etc.)
59
- // app.use('/auth', auth.router());
60
- //
61
- // // Your own routes — throw SentriError (or any subclass) and errorHandler catches them
62
- // app.get('/protected', auth.protect(), (req, res) => {
63
- // res.json(req.user);
64
- // });
65
- //
66
- // // Domain-specific error by extending SentriError
67
- // class NotFoundError extends SentriError {
68
- // constructor(resource: string) {
69
- // super('NOT_FOUND', `${resource} not found`, 404);
70
- // }
71
- // }
72
- //
73
- // app.get('/items/:id', auth.protect(), async (req, res) => {
74
- // const item = await db.query.items.findFirst({ where: (t, { eq }) => eq(t.id, req.params['id']) });
75
- // if (!item) throw new NotFoundError('Item');
76
- // res.json(item);
77
- // });
78
- //
79
- // // Mount AFTER all routes — catches SentriError from sentri AND your subclasses
80
- // app.use(auth.errorHandler());
81
- //
82
- // app.listen(3000);
@@ -1,47 +0,0 @@
1
- // sentri — Drizzle schema template (PostgreSQL / node-postgres)
2
- // Generated by: npx sentri generate drizzle
3
- //
4
- // Field mapping: library uses `identifier` internally, but your DB column
5
- // can be named anything — adjust the first argument of text() on the
6
- // identifier column to match your existing schema, or leave it as-is.
7
- //
8
- // text('email') — login via email
9
- // text('username') — login via username
10
- // text('phone') — login via phone number
11
-
12
- import { pgTable, primaryKey, text, timestamp } from 'drizzle-orm/pg-core';
13
-
14
- export const users = pgTable('users', {
15
- id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()),
16
- identifier: text('email').notNull().unique(),
17
- passwordHash: text('password_hash').notNull(),
18
- createdAt: timestamp('created_at').notNull().defaultNow(),
19
- updatedAt: timestamp('updated_at').notNull().$onUpdateFn(() => new Date()),
20
- });
21
-
22
- export const roles = pgTable('roles', {
23
- id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()),
24
- name: text('name').notNull().unique(),
25
- });
26
-
27
- export const userRoles = pgTable(
28
- 'user_roles',
29
- {
30
- userId: text('user_id')
31
- .notNull()
32
- .references(() => users.id, { onDelete: 'cascade' }),
33
- roleId: text('role_id')
34
- .notNull()
35
- .references(() => roles.id, { onDelete: 'cascade' }),
36
- },
37
- (table) => [primaryKey({ columns: [table.userId, table.roleId] })],
38
- );
39
-
40
- export const sessions = pgTable('sessions', {
41
- id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()),
42
- userId: text('user_id')
43
- .notNull()
44
- .references(() => users.id, { onDelete: 'cascade' }),
45
- expiresAt: timestamp('expires_at').notNull(),
46
- createdAt: timestamp('created_at').notNull().defaultNow(),
47
- });
@@ -1,122 +0,0 @@
1
- // sentri — Prisma adapter template
2
- // Generated by: npx sentri generate prisma
3
- //
4
- // Adjust the Prisma model/field names below if your schema differs from the
5
- // template produced by `npx sentri init`.
6
-
7
- import type { PrismaClient } from '@prisma/client';
8
- import { AuthError, type AuthAdapter } from 'sentri';
9
-
10
- export function createAdapter(prisma: PrismaClient): AuthAdapter {
11
- if (!prisma) {
12
- throw new AuthError(
13
- 'CONFIGURATION_ERROR',
14
- 'createAdapter requires a PrismaClient instance. Did you forget to pass it?\n' +
15
- 'Example: createAdapter(prisma)',
16
- );
17
- }
18
- return {
19
- user: {
20
- async findByIdentifier(identifier) {
21
- const user = await prisma.user.findUnique({
22
- where: { identifier },
23
- include: { userRoles: { include: { role: true } } },
24
- });
25
- if (!user) return null;
26
- return {
27
- id: user.id,
28
- identifier: user.identifier,
29
- passwordHash: user.passwordHash,
30
- roles: user.userRoles.map((userRole) => userRole.role.name),
31
- };
32
- },
33
-
34
- async findById(id) {
35
- const user = await prisma.user.findUnique({
36
- where: { id },
37
- include: { userRoles: { include: { role: true } } },
38
- });
39
- if (!user) return null;
40
- return {
41
- id: user.id,
42
- identifier: user.identifier,
43
- passwordHash: user.passwordHash,
44
- roles: user.userRoles.map((userRole) => userRole.role.name),
45
- };
46
- },
47
-
48
- async create({ identifier, passwordHash, roles }) {
49
- const user = await prisma.user.create({
50
- data: {
51
- identifier,
52
- passwordHash,
53
- userRoles: {
54
- create: await Promise.all(
55
- roles.map(async (name) => {
56
- const role = await prisma.role.upsert({
57
- where: { name },
58
- update: {},
59
- create: { name },
60
- });
61
- return { roleId: role.id };
62
- }),
63
- ),
64
- },
65
- },
66
- });
67
- return { id: user.id };
68
- },
69
-
70
- async updateRoles(userId, roles) {
71
- await prisma.userRole.deleteMany({ where: { userId } });
72
- await Promise.all(
73
- roles.map(async (name) => {
74
- const role = await prisma.role.upsert({
75
- where: { name },
76
- update: {},
77
- create: { name },
78
- });
79
- await prisma.userRole.create({ data: { userId, roleId: role.id } });
80
- }),
81
- );
82
- },
83
- },
84
-
85
- session: {
86
- async create({ userId, expiresAt }) {
87
- const session = await prisma.session.create({ data: { userId, expiresAt } });
88
- return { id: session.id };
89
- },
90
-
91
- async findById(sessionId) {
92
- const session = await prisma.session.findUnique({
93
- where: { id: sessionId },
94
- include: {
95
- user: { include: { userRoles: { include: { role: true } } } },
96
- },
97
- });
98
- if (!session) return null;
99
- return {
100
- id: session.id,
101
- userId: session.userId,
102
- expiresAt: session.expiresAt,
103
- createdAt: session.createdAt,
104
- user: {
105
- id: session.user.id,
106
- identifier: session.user.identifier,
107
- passwordHash: session.user.passwordHash,
108
- roles: session.user.userRoles.map((userRole) => userRole.role.name),
109
- },
110
- };
111
- },
112
-
113
- async delete(sessionId) {
114
- await prisma.session.delete({ where: { id: sessionId } }).catch(() => {});
115
- },
116
-
117
- async deleteAllForUser(userId) {
118
- await prisma.session.deleteMany({ where: { userId } });
119
- },
120
- },
121
- };
122
- }
@@ -1,85 +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: '15m',
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
- cookie: {
25
- secure: process.env.NODE_ENV === 'production',
26
- // name: 'refresh_token',
27
- // httpOnly: true,
28
- // sameSite: 'strict',
29
- // path: '/',
30
- },
31
- // router: {
32
- // register: async (input) => {
33
- // // custom register logic — must return SignupResult
34
- // },
35
- // login: async (input) => {
36
- // // custom login logic — must return AuthResult
37
- // },
38
- // refresh: async (refreshToken) => {
39
- // // custom refresh logic — must return RefreshResult
40
- // },
41
- // logout: async (refreshToken) => {
42
- // // custom logout logic
43
- // },
44
- // logoutAll: async (userId) => {
45
- // // custom logout-all logic
46
- // },
47
- // assignRoles: async (userId, roles) => {
48
- // // custom assignRoles logic — must return AssignRolesResult
49
- // },
50
- // },
51
- });
52
-
53
- // --- Express app setup ---
54
- //
55
- // import express from 'express';
56
- // import { SentriError } from 'sentri';
57
- //
58
- // const app = express();
59
- // app.use(express.json());
60
- //
61
- // // Mount the auth router (POST /auth/register, /auth/login, etc.)
62
- // app.use('/auth', auth.router());
63
- //
64
- // // Your own routes — throw SentriError (or any subclass) and errorHandler catches them
65
- // app.get('/protected', auth.protect(), (req, res) => {
66
- // res.json(req.user);
67
- // });
68
- //
69
- // // Domain-specific error by extending SentriError
70
- // class NotFoundError extends SentriError {
71
- // constructor(resource: string) {
72
- // super('NOT_FOUND', `${resource} not found`, 404);
73
- // }
74
- // }
75
- //
76
- // app.get('/items/:id', auth.protect(), async (req, res) => {
77
- // const item = await prisma.item.findUnique({ where: { id: req.params['id'] } });
78
- // if (!item) throw new NotFoundError('Item');
79
- // res.json(item);
80
- // });
81
- //
82
- // // Mount AFTER all routes — catches SentriError from sentri AND your subclasses
83
- // app.use(auth.errorHandler());
84
- //
85
- // 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
- }