@xcelsior/auth 0.1.1 → 1.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.
@@ -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 146ms
16
- ESM dist/index.mjs 14.28 KB
17
- ESM dist/index.mjs.map 30.43 KB
18
- ESM ⚡️ Build success in 146ms
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 3500ms
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.0 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
- Checked 21 files in 28ms. No fixes applied.
5
+ Checked 17 files in 15ms. No fixes applied.
@@ -1,12 +1,8 @@
1
1
 
2
- > @xcelsior/auth@0.1.0 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
6
6
  
7
-
8
- 
9
- 
10
-
11
- 
12
- 
7
+
8
+
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,274 @@ 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
+ private getRefreshTokenExpiryMs;
110
289
  private hashPassword;
111
- signup(email: string, password: string, roles?: UserRole[]): Promise<{
290
+ private createSession;
291
+ signup(createUserInput: CreateUserInput, password: string, options?: LoginOptions): Promise<{
112
292
  user: User;
113
- token: string;
293
+ tokens: AuthTokens;
114
294
  }>;
115
- signin(email: string, password: string): Promise<{
295
+ signin(email: string, password: string, options?: LoginOptions): Promise<{
116
296
  user: User;
117
- token: string;
297
+ tokens: AuthTokens;
118
298
  }>;
299
+ refreshAccessToken(refreshToken: string): Promise<AuthTokens>;
300
+ /**
301
+ * Logout from current session only
302
+ */
303
+ logout(refreshToken: string): Promise<void>;
304
+ /**
305
+ * Revoke a specific session by ID
306
+ */
307
+ revokeSession(userId: UserId, sessionId: SessionId): Promise<void>;
308
+ /**
309
+ * Revoke all sessions for a user (logout from all devices)
310
+ */
311
+ revokeAllSessions(userId: UserId): Promise<void>;
312
+ /**
313
+ * Get all active sessions for a user
314
+ */
315
+ getSessions(userId: UserId, currentRefreshToken?: string): Promise<SessionInfo[]>;
119
316
  verifyEmail(token: string): Promise<void>;
120
317
  initiatePasswordReset(email: string): Promise<void>;
121
318
  resetPassword(token: string, newPassword: string): Promise<void>;
122
319
  verifyToken(token: string): Promise<{
123
- id: string;
320
+ id: UserId;
124
321
  email: string;
125
- roles: UserRole[];
322
+ roles: string[];
126
323
  isEmailVerified: boolean;
127
324
  }>;
128
- hasRole(userId: string, requiredRoles: UserRole[]): Promise<boolean>;
325
+ hasRole(userId: UserId, requiredRoles: string[]): Promise<boolean>;
326
+ /**
327
+ * Get a user by ID
328
+ */
329
+ getUserById(id: UserId): Promise<User | null>;
330
+ /**
331
+ * Get a user by email
332
+ */
333
+ getUserByEmail(email: string): Promise<User | null>;
334
+ /**
335
+ * Update a user's profile information.
336
+ * Supports predefined fields (email, firstName, lastName, roles, isEmailVerified)
337
+ * as well as any additional custom fields.
338
+ */
339
+ updateUser(id: UserId, updates: UserUpdateInput): Promise<User>;
340
+ /**
341
+ * Delete a user and all their sessions
342
+ */
343
+ deleteUser(id: UserId): Promise<void>;
344
+ /**
345
+ * Find users with filtering and pagination
346
+ *
347
+ * @example
348
+ * // Find all admins
349
+ * const { users } = await authService.findUsers({ hasAnyRole: ['ADMIN'] });
350
+ *
351
+ * // Find verified users with email containing '@company.com'
352
+ * const result = await authService.findUsers({
353
+ * emailContains: '@company.com',
354
+ * isEmailVerified: true
355
+ * }, { limit: 20 });
356
+ */
357
+ findUsers(filter: UserFilter, options?: FindUsersOptions): Promise<FindUsersResult>;
129
358
  }
130
359
 
131
360
  declare class AuthMiddleware {
132
361
  private authService;
133
362
  constructor(authService: AuthService);
134
363
  verifyToken(): (req: any, res: any, next: any) => Promise<void>;
135
- requireRoles(roles: UserRole[]): (req: any, res: any, next: any) => Promise<void>;
364
+ requireRoles(roles: string[]): (req: any, res: any, next: any) => Promise<void>;
136
365
  requireEmailVerified(): (req: any, res: any, next: any) => any;
137
366
  }
138
367
 
139
- export { type AuthConfig, AuthMiddleware, AuthService, type User, type UserRole, UserRoleSchema, UserSchema };
368
+ 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 };