@xcelsior/auth 1.0.0 → 1.1.1

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.
@@ -1,22 +1,22 @@
1
1
 
2
- > @xcelsior/auth@0.1.1 build /Users/tuannguyen/Work/excelsior-packages/packages/services/auth
3
- > tsup
2
+ > @xcelsior/auth@1.0.0 build /Users/tuannguyen/Work/xcelsior-packages/packages/services/auth
3
+ > tsup && tsc --noEmit
4
4
 
5
5
  CLI Building entry: src/index.ts
6
6
  CLI Using tsconfig: tsconfig.json
7
- CLI tsup v8.5.0
8
- CLI Using tsup config: /Users/tuannguyen/Work/excelsior-packages/packages/services/auth/tsup.config.ts
7
+ CLI tsup v8.5.1
8
+ CLI Using tsup config: /Users/tuannguyen/Work/xcelsior-packages/packages/services/auth/tsup.config.ts
9
9
  CLI Target: es2020
10
10
  CLI Cleaning output folder
11
11
  CJS Build start
12
12
  ESM Build start
13
- CJS dist/index.js 16.47 KB
14
- CJS dist/index.js.map 30.61 KB
15
- CJS ⚡️ Build success in 330ms
16
- ESM dist/index.mjs 14.28 KB
17
- ESM dist/index.mjs.map 30.43 KB
18
- ESM ⚡️ Build success in 332ms
13
+ CJS dist/index.js 19.89 KB
14
+ CJS dist/index.js.map 37.50 KB
15
+ CJS ⚡️ Build success in 150ms
16
+ ESM dist/index.mjs 17.56 KB
17
+ ESM dist/index.mjs.map 37.19 KB
18
+ ESM ⚡️ Build success in 152ms
19
19
  DTS Build start
20
- DTS ⚡️ Build success in 4927ms
21
- DTS dist/index.d.ts 3.71 KB
22
- DTS dist/index.d.mts 3.71 KB
20
+ DTS ⚡️ Build success in 2697ms
21
+ DTS dist/index.d.ts 8.86 KB
22
+ DTS dist/index.d.mts 8.86 KB
@@ -1,5 +1,5 @@
1
1
 
2
- > @xcelsior/auth@0.1.1 lint /Users/tuannguyen/Work/excelsior-packages/packages/services/auth
2
+ > @xcelsior/auth@1.0.0 lint /Users/tuannguyen/Work/xcelsior-packages/packages/services/auth
3
3
  > biome check .
4
4
 
5
5
  Checked 17 files in 15ms. No fixes applied.
@@ -1,5 +1,5 @@
1
1
 
2
- > @xcelsior/auth@0.1.1 test /Users/tuannguyen/Work/excelsior-packages/packages/services/auth
2
+ > @xcelsior/auth@1.0.0 test /Users/tuannguyen/Work/xcelsior-packages/packages/services/auth
3
3
  > jest --passWithNoTests
4
4
 
5
5
  Determining test suites to run...No tests found, exiting with code 0
package/dist/index.d.mts CHANGED
@@ -1,22 +1,47 @@
1
1
  import { z } from 'zod';
2
2
 
3
- interface StorageConfig {
4
- type: 'dynamodb' | 'mongodb' | 'postgres';
5
- options: DynamoDBConfig | MongoDBConfig | PostgresConfig;
3
+ /** Filters for finding users */
4
+ interface UserFilter {
5
+ /** Exact email match (uses index - performant) */
6
+ email?: string;
7
+ /** Partial email match - contains (uses scan - less performant) */
8
+ emailContains?: string;
9
+ /** User must have ALL of these roles */
10
+ roles?: string[];
11
+ /** User must have at least ONE of these roles */
12
+ hasAnyRole?: string[];
13
+ /** Filter by email verification status */
14
+ isEmailVerified?: boolean;
6
15
  }
7
- interface DynamoDBConfig {
8
- tableName: string;
9
- region: string;
16
+ /** Options for paginated user queries */
17
+ interface FindUsersOptions {
18
+ /** Maximum number of users to return (default: 50) */
19
+ limit?: number;
20
+ /** Pagination cursor from previous response */
21
+ cursor?: string;
10
22
  }
11
- interface MongoDBConfig {
12
- uri: string;
13
- dbName: string;
14
- collectionName: string;
23
+ /** Result of paginated user queries */
24
+ interface FindUsersResult {
25
+ users: User[];
26
+ /** Cursor for next page, undefined if no more results */
27
+ nextCursor?: string;
15
28
  }
16
- interface PostgresConfig {
17
- connectionString: string;
18
- schema?: string;
19
- tableName: string;
29
+ interface IStorageProvider {
30
+ createUser(user: CreateUserInput): Promise<User>;
31
+ getUserById(id: UserId): Promise<User | null>;
32
+ getUserByEmail(email: string): Promise<User | null>;
33
+ getUserByResetPasswordToken(resetPasswordToken: string): Promise<User | null>;
34
+ getUserByVerifyEmailToken(verifyEmailToken: string): Promise<User | null>;
35
+ updateUser(id: UserId, updates: Partial<User> & Record<string, unknown>): Promise<void>;
36
+ deleteUser(id: UserId): Promise<void>;
37
+ findUsers(filter: UserFilter, options?: FindUsersOptions): Promise<FindUsersResult>;
38
+ createSession(session: CreateSessionInput): Promise<Session>;
39
+ getSessionById(id: SessionId): Promise<Session | null>;
40
+ getSessionsByUserId(userId: UserId): Promise<Session[]>;
41
+ updateSession(id: SessionId, updates: Partial<Session>): Promise<void>;
42
+ deleteSession(id: SessionId): Promise<void>;
43
+ deleteAllUserSessions(userId: UserId): Promise<void>;
44
+ deleteExpiredSessions(): Promise<void>;
20
45
  }
21
46
 
22
47
  interface EmailTemplates {
@@ -33,7 +58,7 @@ interface SMTPConfig {
33
58
  host: string;
34
59
  port: number;
35
60
  secure: boolean;
36
- auth: {
61
+ auth?: {
37
62
  user: string;
38
63
  pass: string;
39
64
  };
@@ -53,13 +78,16 @@ interface EmailConfig {
53
78
  templates?: EmailTemplates;
54
79
  }
55
80
 
56
- declare const UserRoleSchema: z.ZodEnum<["ADMIN", "USER", "GUEST"]>;
57
- type UserRole = z.infer<typeof UserRoleSchema>;
81
+ /** ID can be either auto-incremented number or UUID string */
82
+ type UserId = string | number;
83
+ type SessionId = string | number;
58
84
  declare const UserSchema: z.ZodObject<{
59
- id: z.ZodString;
85
+ id: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
60
86
  email: z.ZodString;
87
+ firstName: z.ZodOptional<z.ZodString>;
88
+ lastName: z.ZodOptional<z.ZodString>;
61
89
  passwordHash: z.ZodString;
62
- roles: z.ZodArray<z.ZodEnum<["ADMIN", "USER", "GUEST"]>, "many">;
90
+ roles: z.ZodArray<z.ZodString, "many">;
63
91
  isEmailVerified: z.ZodBoolean;
64
92
  verificationToken: z.ZodOptional<z.ZodString>;
65
93
  resetPasswordToken: z.ZodOptional<z.ZodString>;
@@ -67,73 +95,276 @@ declare const UserSchema: z.ZodObject<{
67
95
  createdAt: z.ZodNumber;
68
96
  updatedAt: z.ZodNumber;
69
97
  }, "strip", z.ZodTypeAny, {
70
- id: string;
98
+ id: string | number;
71
99
  email: string;
72
100
  passwordHash: string;
73
- roles: ("ADMIN" | "USER" | "GUEST")[];
101
+ roles: string[];
74
102
  isEmailVerified: boolean;
75
103
  createdAt: number;
76
104
  updatedAt: number;
105
+ firstName?: string | undefined;
106
+ lastName?: string | undefined;
77
107
  verificationToken?: string | undefined;
78
108
  resetPasswordToken?: string | undefined;
79
109
  resetPasswordExpires?: number | undefined;
80
110
  }, {
81
- id: string;
111
+ id: string | number;
82
112
  email: string;
83
113
  passwordHash: string;
84
- roles: ("ADMIN" | "USER" | "GUEST")[];
114
+ roles: string[];
85
115
  isEmailVerified: boolean;
86
116
  createdAt: number;
87
117
  updatedAt: number;
118
+ firstName?: string | undefined;
119
+ lastName?: string | undefined;
88
120
  verificationToken?: string | undefined;
89
121
  resetPasswordToken?: string | undefined;
90
122
  resetPasswordExpires?: number | undefined;
91
123
  }>;
124
+ declare const CreateUserSchema: z.ZodObject<Omit<{
125
+ id: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
126
+ email: z.ZodString;
127
+ firstName: z.ZodOptional<z.ZodString>;
128
+ lastName: z.ZodOptional<z.ZodString>;
129
+ passwordHash: z.ZodString;
130
+ roles: z.ZodArray<z.ZodString, "many">;
131
+ isEmailVerified: z.ZodBoolean;
132
+ verificationToken: z.ZodOptional<z.ZodString>;
133
+ resetPasswordToken: z.ZodOptional<z.ZodString>;
134
+ resetPasswordExpires: z.ZodOptional<z.ZodNumber>;
135
+ createdAt: z.ZodNumber;
136
+ updatedAt: z.ZodNumber;
137
+ }, "id" | "createdAt" | "updatedAt"> & {
138
+ createdAt: z.ZodOptional<z.ZodNumber>;
139
+ updatedAt: z.ZodOptional<z.ZodNumber>;
140
+ id: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
141
+ }, "strip", z.ZodTypeAny, {
142
+ email: string;
143
+ passwordHash: string;
144
+ roles: string[];
145
+ isEmailVerified: boolean;
146
+ id?: string | number | undefined;
147
+ firstName?: string | undefined;
148
+ lastName?: string | undefined;
149
+ verificationToken?: string | undefined;
150
+ resetPasswordToken?: string | undefined;
151
+ resetPasswordExpires?: number | undefined;
152
+ createdAt?: number | undefined;
153
+ updatedAt?: number | undefined;
154
+ }, {
155
+ email: string;
156
+ passwordHash: string;
157
+ roles: string[];
158
+ isEmailVerified: boolean;
159
+ id?: string | number | undefined;
160
+ firstName?: string | undefined;
161
+ lastName?: string | undefined;
162
+ verificationToken?: string | undefined;
163
+ resetPasswordToken?: string | undefined;
164
+ resetPasswordExpires?: number | undefined;
165
+ createdAt?: number | undefined;
166
+ updatedAt?: number | undefined;
167
+ }>;
92
168
  type User = z.infer<typeof UserSchema>;
169
+ type CreateUserInput = z.infer<typeof CreateUserSchema>;
170
+ declare const SessionSchema: z.ZodObject<{
171
+ id: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
172
+ userId: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
173
+ refreshTokenHash: z.ZodString;
174
+ userAgent: z.ZodOptional<z.ZodString>;
175
+ ipAddress: z.ZodOptional<z.ZodString>;
176
+ deviceName: z.ZodOptional<z.ZodString>;
177
+ createdAt: z.ZodNumber;
178
+ lastUsedAt: z.ZodNumber;
179
+ expiresAt: z.ZodNumber;
180
+ }, "strip", z.ZodTypeAny, {
181
+ id: string | number;
182
+ createdAt: number;
183
+ userId: string | number;
184
+ refreshTokenHash: string;
185
+ lastUsedAt: number;
186
+ expiresAt: number;
187
+ userAgent?: string | undefined;
188
+ ipAddress?: string | undefined;
189
+ deviceName?: string | undefined;
190
+ }, {
191
+ id: string | number;
192
+ createdAt: number;
193
+ userId: string | number;
194
+ refreshTokenHash: string;
195
+ lastUsedAt: number;
196
+ expiresAt: number;
197
+ userAgent?: string | undefined;
198
+ ipAddress?: string | undefined;
199
+ deviceName?: string | undefined;
200
+ }>;
201
+ declare const CreateSessionSchema: z.ZodObject<Omit<{
202
+ id: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
203
+ userId: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
204
+ refreshTokenHash: z.ZodString;
205
+ userAgent: z.ZodOptional<z.ZodString>;
206
+ ipAddress: z.ZodOptional<z.ZodString>;
207
+ deviceName: z.ZodOptional<z.ZodString>;
208
+ createdAt: z.ZodNumber;
209
+ lastUsedAt: z.ZodNumber;
210
+ expiresAt: z.ZodNumber;
211
+ }, "id" | "createdAt" | "lastUsedAt"> & {
212
+ createdAt: z.ZodOptional<z.ZodNumber>;
213
+ lastUsedAt: z.ZodOptional<z.ZodNumber>;
214
+ id: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
215
+ }, "strip", z.ZodTypeAny, {
216
+ userId: string | number;
217
+ refreshTokenHash: string;
218
+ expiresAt: number;
219
+ id?: string | number | undefined;
220
+ createdAt?: number | undefined;
221
+ userAgent?: string | undefined;
222
+ ipAddress?: string | undefined;
223
+ deviceName?: string | undefined;
224
+ lastUsedAt?: number | undefined;
225
+ }, {
226
+ userId: string | number;
227
+ refreshTokenHash: string;
228
+ expiresAt: number;
229
+ id?: string | number | undefined;
230
+ createdAt?: number | undefined;
231
+ userAgent?: string | undefined;
232
+ ipAddress?: string | undefined;
233
+ deviceName?: string | undefined;
234
+ lastUsedAt?: number | undefined;
235
+ }>;
236
+ type Session = z.infer<typeof SessionSchema>;
237
+ type CreateSessionInput = z.infer<typeof CreateSessionSchema>;
238
+ /** Session info returned to clients (without sensitive data) */
239
+ interface SessionInfo {
240
+ id: SessionId;
241
+ deviceName?: string;
242
+ userAgent?: string;
243
+ ipAddress?: string;
244
+ createdAt: number;
245
+ lastUsedAt: number;
246
+ isCurrent: boolean;
247
+ }
93
248
  interface AuthConfig {
94
249
  jwt: {
95
250
  privateKey: string;
96
251
  publicKey: string;
97
252
  keyId: string;
98
253
  expiresIn: string;
254
+ refreshTokenExpiresIn?: string;
99
255
  };
100
- storage: StorageConfig;
256
+ storage: IStorageProvider;
257
+ idGeneration: 'uuid' | 'increment';
101
258
  email: EmailConfig;
102
259
  }
103
260
 
261
+ interface AuthTokens {
262
+ accessToken: string;
263
+ refreshToken: string;
264
+ }
265
+ interface LoginOptions {
266
+ userAgent?: string;
267
+ ipAddress?: string;
268
+ deviceName?: string;
269
+ }
270
+ /** Allowed fields for user updates */
271
+ interface UserUpdateInput {
272
+ email?: string;
273
+ firstName?: string;
274
+ lastName?: string;
275
+ roles?: string[];
276
+ isEmailVerified?: boolean;
277
+ [key: string]: unknown;
278
+ }
104
279
  declare class AuthService {
105
280
  private storage;
106
281
  private email;
107
282
  private config;
108
283
  constructor(config: AuthConfig);
109
- private generateToken;
284
+ private generateAccessToken;
285
+ private generateRefreshToken;
286
+ private verifyRefreshToken;
287
+ private hashToken;
288
+ /** Return current time as epoch seconds */
289
+ private now;
290
+ private getRefreshTokenExpirySecs;
110
291
  private hashPassword;
111
- signup(email: string, password: string, roles?: UserRole[]): Promise<{
292
+ private createSession;
293
+ signup(createUserInput: CreateUserInput, password: string, options?: LoginOptions): Promise<{
112
294
  user: User;
113
- token: string;
295
+ tokens: AuthTokens;
114
296
  }>;
115
- signin(email: string, password: string): Promise<{
297
+ signin(email: string, password: string, options?: LoginOptions): Promise<{
116
298
  user: User;
117
- token: string;
299
+ tokens: AuthTokens;
118
300
  }>;
301
+ refreshAccessToken(refreshToken: string): Promise<AuthTokens>;
302
+ /**
303
+ * Logout from current session only
304
+ */
305
+ logout(refreshToken: string): Promise<void>;
306
+ /**
307
+ * Revoke a specific session by ID
308
+ */
309
+ revokeSession(userId: UserId, sessionId: SessionId): Promise<void>;
310
+ /**
311
+ * Revoke all sessions for a user (logout from all devices)
312
+ */
313
+ revokeAllSessions(userId: UserId): Promise<void>;
314
+ /**
315
+ * Get all active sessions for a user
316
+ */
317
+ getSessions(userId: UserId, currentRefreshToken?: string): Promise<SessionInfo[]>;
119
318
  verifyEmail(token: string): Promise<void>;
120
319
  initiatePasswordReset(email: string): Promise<void>;
121
320
  resetPassword(token: string, newPassword: string): Promise<void>;
122
321
  verifyToken(token: string): Promise<{
123
- id: string;
322
+ id: UserId;
124
323
  email: string;
125
- roles: UserRole[];
324
+ roles: string[];
126
325
  isEmailVerified: boolean;
127
326
  }>;
128
- hasRole(userId: string, requiredRoles: UserRole[]): Promise<boolean>;
327
+ hasRole(userId: UserId, requiredRoles: string[]): Promise<boolean>;
328
+ /**
329
+ * Get a user by ID
330
+ */
331
+ getUserById(id: UserId): Promise<User | null>;
332
+ /**
333
+ * Get a user by email
334
+ */
335
+ getUserByEmail(email: string): Promise<User | null>;
336
+ /**
337
+ * Update a user's profile information.
338
+ * Supports predefined fields (email, firstName, lastName, roles, isEmailVerified)
339
+ * as well as any additional custom fields.
340
+ */
341
+ updateUser(id: UserId, updates: UserUpdateInput): Promise<User>;
342
+ /**
343
+ * Delete a user and all their sessions
344
+ */
345
+ deleteUser(id: UserId): Promise<void>;
346
+ /**
347
+ * Find users with filtering and pagination
348
+ *
349
+ * @example
350
+ * // Find all admins
351
+ * const { users } = await authService.findUsers({ hasAnyRole: ['ADMIN'] });
352
+ *
353
+ * // Find verified users with email containing '@company.com'
354
+ * const result = await authService.findUsers({
355
+ * emailContains: '@company.com',
356
+ * isEmailVerified: true
357
+ * }, { limit: 20 });
358
+ */
359
+ findUsers(filter: UserFilter, options?: FindUsersOptions): Promise<FindUsersResult>;
129
360
  }
130
361
 
131
362
  declare class AuthMiddleware {
132
363
  private authService;
133
364
  constructor(authService: AuthService);
134
365
  verifyToken(): (req: any, res: any, next: any) => Promise<void>;
135
- requireRoles(roles: UserRole[]): (req: any, res: any, next: any) => Promise<void>;
366
+ requireRoles(roles: string[]): (req: any, res: any, next: any) => Promise<void>;
136
367
  requireEmailVerified(): (req: any, res: any, next: any) => any;
137
368
  }
138
369
 
139
- export { type AuthConfig, AuthMiddleware, AuthService, type User, type UserRole, UserRoleSchema, UserSchema };
370
+ export { type AuthConfig, AuthMiddleware, AuthService, type AuthTokens, type CreateSessionInput, CreateSessionSchema, type CreateUserInput, CreateUserSchema, type FindUsersOptions, type FindUsersResult, type IStorageProvider, type LoginOptions, type Session, type SessionId, type SessionInfo, SessionSchema, type User, type UserFilter, type UserId, UserSchema, type UserUpdateInput };