najm-auth 1.1.25 → 1.1.27

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/index.d.ts CHANGED
@@ -684,7 +684,11 @@ declare class TokenRepository {
684
684
  token: string;
685
685
  tokenFamily: string;
686
686
  expiresAt: string;
687
+ previousHash?: string | null;
688
+ previousValidUntil?: string | null;
689
+ previousUsedAt?: string | null;
687
690
  }): Promise<any>;
691
+ markPreviousUsed(userId: string): Promise<any>;
688
692
  getRefreshTokenWithFamily(userId: string): Promise<any>;
689
693
  revokeToken(userId: string): Promise<any>;
690
694
  revokeByFamily(tokenFamily: string): Promise<any>;
@@ -718,22 +722,25 @@ declare class TokenService {
718
722
  */
719
723
  verifyAccessToken(token: string): Promise<JwtPayload>;
720
724
  verifyRefreshToken(token: string): string;
725
+ private static readonly PREVIOUS_GRACE_SECONDS;
721
726
  /**
722
727
  * Validate a refresh token as an active session:
723
728
  * 1. Verify JWT signature and type claim
724
- * 2. Compare hash against stored token in DB
725
- * 3. Reject revoked, rotated, or expired tokens
726
- *
727
- * Use this instead of bare verifyRefreshToken() when authenticating
728
- * cookie-based sessions (SSR, /auth/me, middleware).
729
+ * 2. Compare hash against current stored token
730
+ * 3. If mismatch, check previous hash within short grace window
731
+ * 4. Reject anything older or outside the grace window
729
732
  */
730
- validateRefreshSession(refreshToken: string): Promise<string>;
733
+ validateRefreshSession(refreshToken: string): Promise<{
734
+ userId: string;
735
+ rotatedTokens?: {
736
+ refreshToken: string;
737
+ tokenFamily: string;
738
+ };
739
+ }>;
731
740
  /**
732
741
  * Read the refresh cookie and return the userId it belongs to.
733
- * Lightweight check: verifies JWT signature and ensures the user
734
- * has an active session in the DB. Does NOT compare token hashes,
735
- * so it is safe to call concurrently with token rotation.
736
- * Throws if the cookie is missing, invalid, or the session was revoked.
742
+ * Validates against current/previous token state with bounded recovery.
743
+ * Throws if the cookie is missing, invalid, or outside the grace window.
737
744
  */
738
745
  resolveUserFromCookie(): Promise<string>;
739
746
  getUser(auth: string): Promise<any>;
package/dist/index.js CHANGED
@@ -67,6 +67,9 @@ var tokensTable = pgTable("tokens", {
67
67
  userId: text("user_id").references(() => usersTable.id, { onDelete: "cascade" }).unique().notNull(),
68
68
  token: text("token").notNull(),
69
69
  tokenFamily: text("token_family"),
70
+ previousHash: text("previous_hash"),
71
+ previousValidUntil: timestamp("previous_valid_until", { mode: "string" }),
72
+ previousUsedAt: timestamp("previous_used_at", { mode: "string" }),
70
73
  type: tokenTypeEnum("type").default("refresh"),
71
74
  status: tokenStatusEnum("status").default("active"),
72
75
  expiresAt: timestamp("expires_at", { mode: "string" }).notNull()
@@ -129,6 +132,9 @@ var tokensTable2 = sqliteTable("tokens", {
129
132
  userId: text2("user_id").references(() => usersTable2.id, { onDelete: "cascade" }).unique().notNull(),
130
133
  token: text2("token").notNull(),
131
134
  tokenFamily: text2("token_family"),
135
+ previousHash: text2("previous_hash"),
136
+ previousValidUntil: text2("previous_valid_until"),
137
+ previousUsedAt: text2("previous_used_at"),
132
138
  type: text2("type").$type().default("refresh"),
133
139
  status: text2("status").$type().default("active"),
134
140
  expiresAt: text2("expires_at").notNull()
@@ -191,6 +197,9 @@ var tokensTable3 = mysqlTable("tokens", {
191
197
  userId: varchar("user_id", { length: 21 }).references(() => usersTable3.id, { onDelete: "cascade" }).unique().notNull(),
192
198
  token: varchar("token", { length: 500 }).notNull(),
193
199
  tokenFamily: varchar("token_family", { length: 16 }),
200
+ previousHash: varchar("previous_hash", { length: 500 }),
201
+ previousValidUntil: timestamp2("previous_valid_until", { mode: "string" }),
202
+ previousUsedAt: timestamp2("previous_used_at", { mode: "string" }),
194
203
  type: mysqlEnum("type", [...TOKEN_TYPE]).default("refresh"),
195
204
  status: mysqlEnum("status", [...TOKEN_STATUS]).default("active"),
196
205
  expiresAt: timestamp2("expires_at", { mode: "string" }).notNull()
@@ -1311,10 +1320,16 @@ var TokenRepository = class TokenRepository2 {
1311
1320
  set: {
1312
1321
  token: tokenData.token,
1313
1322
  tokenFamily: tokenData.tokenFamily,
1314
- expiresAt: tokenData.expiresAt
1323
+ expiresAt: tokenData.expiresAt,
1324
+ previousHash: tokenData.previousHash ?? null,
1325
+ previousValidUntil: tokenData.previousValidUntil ?? null,
1326
+ previousUsedAt: tokenData.previousUsedAt ?? null
1315
1327
  }
1316
1328
  }).returning();
1317
1329
  }
1330
+ async markPreviousUsed(userId) {
1331
+ return await this.db.update(this.tokens).set({ previousUsedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(eq4(this.tokens.userId, userId)).returning();
1332
+ }
1318
1333
  async getRefreshTokenWithFamily(userId) {
1319
1334
  const [token] = await this.db.select().from(this.tokens).where(eq4(this.tokens.userId, userId));
1320
1335
  return token ?? null;
@@ -1373,6 +1388,7 @@ var __decorate10 = function(decorators, target, key, desc) {
1373
1388
  var __metadata10 = function(k, v) {
1374
1389
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1375
1390
  };
1391
+ var TokenService_1;
1376
1392
  var _a6;
1377
1393
  var _b4;
1378
1394
  var _c2;
@@ -1380,6 +1396,9 @@ var TokenService = class TokenService2 {
1380
1396
  static {
1381
1397
  __name(this, "TokenService");
1382
1398
  }
1399
+ static {
1400
+ TokenService_1 = this;
1401
+ }
1383
1402
  tokenRepository;
1384
1403
  cookieManager;
1385
1404
  cache;
@@ -1444,14 +1463,13 @@ var TokenService = class TokenService2 {
1444
1463
  Err5(this.t("errors.tokenVerificationFailed"));
1445
1464
  }
1446
1465
  }
1466
+ static PREVIOUS_GRACE_SECONDS = 120;
1447
1467
  /**
1448
1468
  * Validate a refresh token as an active session:
1449
1469
  * 1. Verify JWT signature and type claim
1450
- * 2. Compare hash against stored token in DB
1451
- * 3. Reject revoked, rotated, or expired tokens
1452
- *
1453
- * Use this instead of bare verifyRefreshToken() when authenticating
1454
- * cookie-based sessions (SSR, /auth/me, middleware).
1470
+ * 2. Compare hash against current stored token
1471
+ * 3. If mismatch, check previous hash within short grace window
1472
+ * 4. Reject anything older or outside the grace window
1455
1473
  */
1456
1474
  async validateRefreshSession(refreshToken) {
1457
1475
  const userId = this.verifyRefreshToken(refreshToken);
@@ -1459,18 +1477,25 @@ var TokenService = class TokenService2 {
1459
1477
  if (!stored) {
1460
1478
  Err5(this.t("errors.refreshTokenInvalid"));
1461
1479
  }
1462
- const isValid = this.hashToken(refreshToken) === stored.token;
1463
- if (!isValid) {
1464
- Err5(this.t("errors.refreshTokenInvalid"));
1480
+ const presentedHash = this.hashToken(refreshToken);
1481
+ if (presentedHash === stored.token) {
1482
+ return { userId };
1465
1483
  }
1466
- return userId;
1484
+ const canRecover = stored.previousHash && presentedHash === stored.previousHash && stored.previousValidUntil && new Date(stored.previousValidUntil).getTime() > Date.now() && !stored.previousUsedAt;
1485
+ if (canRecover) {
1486
+ await this.tokenRepository.markPreviousUsed(userId);
1487
+ const tokens = await this.generateTokens(userId, stored.tokenFamily ?? void 0);
1488
+ return {
1489
+ userId,
1490
+ rotatedTokens: { refreshToken: tokens.refreshToken, tokenFamily: stored.tokenFamily }
1491
+ };
1492
+ }
1493
+ Err5(this.t("errors.refreshTokenInvalid"));
1467
1494
  }
1468
1495
  /**
1469
1496
  * Read the refresh cookie and return the userId it belongs to.
1470
- * Lightweight check: verifies JWT signature and ensures the user
1471
- * has an active session in the DB. Does NOT compare token hashes,
1472
- * so it is safe to call concurrently with token rotation.
1473
- * Throws if the cookie is missing, invalid, or the session was revoked.
1497
+ * Validates against current/previous token state with bounded recovery.
1498
+ * Throws if the cookie is missing, invalid, or outside the grace window.
1474
1499
  */
1475
1500
  async resolveUserFromCookie() {
1476
1501
  const refreshToken = this.cookieManager.getRefreshToken();
@@ -1482,7 +1507,15 @@ var TokenService = class TokenService2 {
1482
1507
  if (!stored) {
1483
1508
  Err5(this.t("errors.refreshTokenInvalid"));
1484
1509
  }
1485
- return userId;
1510
+ const presentedHash = this.hashToken(refreshToken);
1511
+ if (presentedHash === stored.token) {
1512
+ return userId;
1513
+ }
1514
+ const canRecover = stored.previousHash && presentedHash === stored.previousHash && stored.previousValidUntil && new Date(stored.previousValidUntil).getTime() > Date.now() && !stored.previousUsedAt;
1515
+ if (canRecover) {
1516
+ return userId;
1517
+ }
1518
+ Err5(this.t("errors.refreshTokenInvalid"));
1486
1519
  }
1487
1520
  // ============ USER RETRIEVAL (MAIN METHOD) ============
1488
1521
  async getUser(auth2) {
@@ -1586,11 +1619,17 @@ var TokenService = class TokenService2 {
1586
1619
  async storeRefreshToken(userId, refreshToken, tokenFamily) {
1587
1620
  const expireInSecond = timestring2(this.config.jwt.refreshExpiresIn, "s");
1588
1621
  const hashedToken = this.hashToken(refreshToken);
1622
+ const existing = await this.tokenRepository.getRefreshTokenWithFamily(userId);
1623
+ const previousHash = existing?.token ?? null;
1624
+ const previousValidUntil = previousHash ? new Date(Date.now() + TokenService_1.PREVIOUS_GRACE_SECONDS * 1e3).toISOString() : null;
1589
1625
  await this.tokenRepository.storeRefreshToken({
1590
1626
  userId,
1591
1627
  token: hashedToken,
1592
1628
  tokenFamily,
1593
- expiresAt: new Date(Date.now() + expireInSecond * 1e3).toISOString()
1629
+ expiresAt: new Date(Date.now() + expireInSecond * 1e3).toISOString(),
1630
+ previousHash,
1631
+ previousValidUntil,
1632
+ previousUsedAt: null
1594
1633
  });
1595
1634
  }
1596
1635
  /**
@@ -1607,11 +1646,16 @@ var TokenService = class TokenService2 {
1607
1646
  if (!stored) {
1608
1647
  Err5(this.t("errors.refreshTokenInvalid"));
1609
1648
  }
1610
- const isValid = this.hashToken(refreshToken) === stored.token;
1611
- if (!isValid) {
1612
- Err5(this.t("errors.refreshTokenInvalid"));
1649
+ const presentedHash = this.hashToken(refreshToken);
1650
+ if (presentedHash === stored.token) {
1651
+ return this.generateTokens(userId, stored.tokenFamily ?? void 0);
1652
+ }
1653
+ const canRecover = stored.previousHash && presentedHash === stored.previousHash && stored.previousValidUntil && new Date(stored.previousValidUntil).getTime() > Date.now() && !stored.previousUsedAt;
1654
+ if (canRecover) {
1655
+ await this.tokenRepository.markPreviousUsed(userId);
1656
+ return this.generateTokens(userId, stored.tokenFamily ?? void 0);
1613
1657
  }
1614
- return this.generateTokens(userId, stored.tokenFamily ?? void 0);
1658
+ Err5(this.t("errors.refreshTokenInvalid"));
1615
1659
  }
1616
1660
  async revokeToken(userId) {
1617
1661
  return this.tokenRepository.revokeToken(userId);
@@ -1693,7 +1737,7 @@ __decorate10([
1693
1737
  I18n3("auth"),
1694
1738
  __metadata10("design:type", Object)
1695
1739
  ], TokenService.prototype, "t", void 0);
1696
- TokenService = __decorate10([
1740
+ TokenService = TokenService_1 = __decorate10([
1697
1741
  Injectable6(),
1698
1742
  __metadata10("design:paramtypes", [typeof (_a6 = typeof TokenRepository !== "undefined" && TokenRepository) === "function" ? _a6 : Object, typeof (_b4 = typeof CookieManager !== "undefined" && CookieManager) === "function" ? _b4 : Object, typeof (_c2 = typeof CacheService !== "undefined" && CacheService) === "function" ? _c2 : Object])
1699
1743
  ], TokenService);
@@ -2246,11 +2290,14 @@ var AuthResolver = class AuthResolver2 {
2246
2290
  if (!refreshToken)
2247
2291
  return false;
2248
2292
  const tokenService = await this.container.resolve(TokenService);
2249
- const userId = await tokenService.validateRefreshSession(refreshToken);
2250
- if (!userId)
2293
+ const result = await tokenService.validateRefreshSession(refreshToken);
2294
+ if (!result.userId)
2251
2295
  return false;
2296
+ if (result.rotatedTokens) {
2297
+ cookieManager.setRefreshToken(result.rotatedTokens.refreshToken);
2298
+ }
2252
2299
  const userService = await this.container.resolve(UserService);
2253
- const user = await userService.getById(userId);
2300
+ const user = await userService.getById(result.userId);
2254
2301
  if (!user)
2255
2302
  return false;
2256
2303
  return {
@@ -519,6 +519,57 @@ declare const tokensTable: drizzle_orm_mysql_core.MySqlTableWithColumns<{
519
519
  identity: undefined;
520
520
  generated: undefined;
521
521
  }, {}, {}>;
522
+ previousHash: drizzle_orm_mysql_core.MySqlColumn<{
523
+ name: "previous_hash";
524
+ tableName: "tokens";
525
+ dataType: "string";
526
+ columnType: "MySqlVarChar";
527
+ data: string;
528
+ driverParam: string | number;
529
+ notNull: false;
530
+ hasDefault: false;
531
+ isPrimaryKey: false;
532
+ isAutoincrement: false;
533
+ hasRuntimeDefault: false;
534
+ enumValues: [string, ...string[]];
535
+ baseColumn: never;
536
+ identity: undefined;
537
+ generated: undefined;
538
+ }, {}, {}>;
539
+ previousValidUntil: drizzle_orm_mysql_core.MySqlColumn<{
540
+ name: "previous_valid_until";
541
+ tableName: "tokens";
542
+ dataType: "string";
543
+ columnType: "MySqlTimestampString";
544
+ data: string;
545
+ driverParam: string | number;
546
+ notNull: false;
547
+ hasDefault: false;
548
+ isPrimaryKey: false;
549
+ isAutoincrement: false;
550
+ hasRuntimeDefault: false;
551
+ enumValues: undefined;
552
+ baseColumn: never;
553
+ identity: undefined;
554
+ generated: undefined;
555
+ }, {}, {}>;
556
+ previousUsedAt: drizzle_orm_mysql_core.MySqlColumn<{
557
+ name: "previous_used_at";
558
+ tableName: "tokens";
559
+ dataType: "string";
560
+ columnType: "MySqlTimestampString";
561
+ data: string;
562
+ driverParam: string | number;
563
+ notNull: false;
564
+ hasDefault: false;
565
+ isPrimaryKey: false;
566
+ isAutoincrement: false;
567
+ hasRuntimeDefault: false;
568
+ enumValues: undefined;
569
+ baseColumn: never;
570
+ identity: undefined;
571
+ generated: undefined;
572
+ }, {}, {}>;
522
573
  type: drizzle_orm_mysql_core.MySqlColumn<{
523
574
  name: "type";
524
575
  tableName: "tokens";
@@ -969,6 +1020,57 @@ declare const authSchema: {
969
1020
  identity: undefined;
970
1021
  generated: undefined;
971
1022
  }, {}, {}>;
1023
+ previousHash: drizzle_orm_mysql_core.MySqlColumn<{
1024
+ name: "previous_hash";
1025
+ tableName: "tokens";
1026
+ dataType: "string";
1027
+ columnType: "MySqlVarChar";
1028
+ data: string;
1029
+ driverParam: string | number;
1030
+ notNull: false;
1031
+ hasDefault: false;
1032
+ isPrimaryKey: false;
1033
+ isAutoincrement: false;
1034
+ hasRuntimeDefault: false;
1035
+ enumValues: [string, ...string[]];
1036
+ baseColumn: never;
1037
+ identity: undefined;
1038
+ generated: undefined;
1039
+ }, {}, {}>;
1040
+ previousValidUntil: drizzle_orm_mysql_core.MySqlColumn<{
1041
+ name: "previous_valid_until";
1042
+ tableName: "tokens";
1043
+ dataType: "string";
1044
+ columnType: "MySqlTimestampString";
1045
+ data: string;
1046
+ driverParam: string | number;
1047
+ notNull: false;
1048
+ hasDefault: false;
1049
+ isPrimaryKey: false;
1050
+ isAutoincrement: false;
1051
+ hasRuntimeDefault: false;
1052
+ enumValues: undefined;
1053
+ baseColumn: never;
1054
+ identity: undefined;
1055
+ generated: undefined;
1056
+ }, {}, {}>;
1057
+ previousUsedAt: drizzle_orm_mysql_core.MySqlColumn<{
1058
+ name: "previous_used_at";
1059
+ tableName: "tokens";
1060
+ dataType: "string";
1061
+ columnType: "MySqlTimestampString";
1062
+ data: string;
1063
+ driverParam: string | number;
1064
+ notNull: false;
1065
+ hasDefault: false;
1066
+ isPrimaryKey: false;
1067
+ isAutoincrement: false;
1068
+ hasRuntimeDefault: false;
1069
+ enumValues: undefined;
1070
+ baseColumn: never;
1071
+ identity: undefined;
1072
+ generated: undefined;
1073
+ }, {}, {}>;
972
1074
  type: drizzle_orm_mysql_core.MySqlColumn<{
973
1075
  name: "type";
974
1076
  tableName: "tokens";
@@ -49,6 +49,9 @@ var tokensTable = mysqlTable("tokens", {
49
49
  userId: varchar("user_id", { length: 21 }).references(() => usersTable.id, { onDelete: "cascade" }).unique().notNull(),
50
50
  token: varchar("token", { length: 500 }).notNull(),
51
51
  tokenFamily: varchar("token_family", { length: 16 }),
52
+ previousHash: varchar("previous_hash", { length: 500 }),
53
+ previousValidUntil: timestamp("previous_valid_until", { mode: "string" }),
54
+ previousUsedAt: timestamp("previous_used_at", { mode: "string" }),
52
55
  type: mysqlEnum("type", [...TOKEN_TYPE]).default("refresh"),
53
56
  status: mysqlEnum("status", [...TOKEN_STATUS]).default("active"),
54
57
  expiresAt: timestamp("expires_at", { mode: "string" }).notNull()
@@ -522,6 +522,57 @@ declare const tokensTable: drizzle_orm_pg_core.PgTableWithColumns<{
522
522
  identity: undefined;
523
523
  generated: undefined;
524
524
  }, {}, {}>;
525
+ previousHash: drizzle_orm_pg_core.PgColumn<{
526
+ name: "previous_hash";
527
+ tableName: "tokens";
528
+ dataType: "string";
529
+ columnType: "PgText";
530
+ data: string;
531
+ driverParam: string;
532
+ notNull: false;
533
+ hasDefault: false;
534
+ isPrimaryKey: false;
535
+ isAutoincrement: false;
536
+ hasRuntimeDefault: false;
537
+ enumValues: [string, ...string[]];
538
+ baseColumn: never;
539
+ identity: undefined;
540
+ generated: undefined;
541
+ }, {}, {}>;
542
+ previousValidUntil: drizzle_orm_pg_core.PgColumn<{
543
+ name: "previous_valid_until";
544
+ tableName: "tokens";
545
+ dataType: "string";
546
+ columnType: "PgTimestampString";
547
+ data: string;
548
+ driverParam: string;
549
+ notNull: false;
550
+ hasDefault: false;
551
+ isPrimaryKey: false;
552
+ isAutoincrement: false;
553
+ hasRuntimeDefault: false;
554
+ enumValues: undefined;
555
+ baseColumn: never;
556
+ identity: undefined;
557
+ generated: undefined;
558
+ }, {}, {}>;
559
+ previousUsedAt: drizzle_orm_pg_core.PgColumn<{
560
+ name: "previous_used_at";
561
+ tableName: "tokens";
562
+ dataType: "string";
563
+ columnType: "PgTimestampString";
564
+ data: string;
565
+ driverParam: string;
566
+ notNull: false;
567
+ hasDefault: false;
568
+ isPrimaryKey: false;
569
+ isAutoincrement: false;
570
+ hasRuntimeDefault: false;
571
+ enumValues: undefined;
572
+ baseColumn: never;
573
+ identity: undefined;
574
+ generated: undefined;
575
+ }, {}, {}>;
525
576
  type: drizzle_orm_pg_core.PgColumn<{
526
577
  name: "type";
527
578
  tableName: "tokens";
@@ -972,6 +1023,57 @@ declare const authSchema: {
972
1023
  identity: undefined;
973
1024
  generated: undefined;
974
1025
  }, {}, {}>;
1026
+ previousHash: drizzle_orm_pg_core.PgColumn<{
1027
+ name: "previous_hash";
1028
+ tableName: "tokens";
1029
+ dataType: "string";
1030
+ columnType: "PgText";
1031
+ data: string;
1032
+ driverParam: string;
1033
+ notNull: false;
1034
+ hasDefault: false;
1035
+ isPrimaryKey: false;
1036
+ isAutoincrement: false;
1037
+ hasRuntimeDefault: false;
1038
+ enumValues: [string, ...string[]];
1039
+ baseColumn: never;
1040
+ identity: undefined;
1041
+ generated: undefined;
1042
+ }, {}, {}>;
1043
+ previousValidUntil: drizzle_orm_pg_core.PgColumn<{
1044
+ name: "previous_valid_until";
1045
+ tableName: "tokens";
1046
+ dataType: "string";
1047
+ columnType: "PgTimestampString";
1048
+ data: string;
1049
+ driverParam: string;
1050
+ notNull: false;
1051
+ hasDefault: false;
1052
+ isPrimaryKey: false;
1053
+ isAutoincrement: false;
1054
+ hasRuntimeDefault: false;
1055
+ enumValues: undefined;
1056
+ baseColumn: never;
1057
+ identity: undefined;
1058
+ generated: undefined;
1059
+ }, {}, {}>;
1060
+ previousUsedAt: drizzle_orm_pg_core.PgColumn<{
1061
+ name: "previous_used_at";
1062
+ tableName: "tokens";
1063
+ dataType: "string";
1064
+ columnType: "PgTimestampString";
1065
+ data: string;
1066
+ driverParam: string;
1067
+ notNull: false;
1068
+ hasDefault: false;
1069
+ isPrimaryKey: false;
1070
+ isAutoincrement: false;
1071
+ hasRuntimeDefault: false;
1072
+ enumValues: undefined;
1073
+ baseColumn: never;
1074
+ identity: undefined;
1075
+ generated: undefined;
1076
+ }, {}, {}>;
975
1077
  type: drizzle_orm_pg_core.PgColumn<{
976
1078
  name: "type";
977
1079
  tableName: "tokens";
package/dist/schema/pg.js CHANGED
@@ -52,6 +52,9 @@ var tokensTable = pgTable("tokens", {
52
52
  userId: text("user_id").references(() => usersTable.id, { onDelete: "cascade" }).unique().notNull(),
53
53
  token: text("token").notNull(),
54
54
  tokenFamily: text("token_family"),
55
+ previousHash: text("previous_hash"),
56
+ previousValidUntil: timestamp("previous_valid_until", { mode: "string" }),
57
+ previousUsedAt: timestamp("previous_used_at", { mode: "string" }),
55
58
  type: tokenTypeEnum("type").default("refresh"),
56
59
  status: tokenStatusEnum("status").default("active"),
57
60
  expiresAt: timestamp("expires_at", { mode: "string" }).notNull()
@@ -572,6 +572,63 @@ declare const tokensTable: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
572
572
  }, {}, {
573
573
  length: number;
574
574
  }>;
575
+ previousHash: drizzle_orm_sqlite_core.SQLiteColumn<{
576
+ name: "previous_hash";
577
+ tableName: "tokens";
578
+ dataType: "string";
579
+ columnType: "SQLiteText";
580
+ data: string;
581
+ driverParam: string;
582
+ notNull: false;
583
+ hasDefault: false;
584
+ isPrimaryKey: false;
585
+ isAutoincrement: false;
586
+ hasRuntimeDefault: false;
587
+ enumValues: [string, ...string[]];
588
+ baseColumn: never;
589
+ identity: undefined;
590
+ generated: undefined;
591
+ }, {}, {
592
+ length: number;
593
+ }>;
594
+ previousValidUntil: drizzle_orm_sqlite_core.SQLiteColumn<{
595
+ name: "previous_valid_until";
596
+ tableName: "tokens";
597
+ dataType: "string";
598
+ columnType: "SQLiteText";
599
+ data: string;
600
+ driverParam: string;
601
+ notNull: false;
602
+ hasDefault: false;
603
+ isPrimaryKey: false;
604
+ isAutoincrement: false;
605
+ hasRuntimeDefault: false;
606
+ enumValues: [string, ...string[]];
607
+ baseColumn: never;
608
+ identity: undefined;
609
+ generated: undefined;
610
+ }, {}, {
611
+ length: number;
612
+ }>;
613
+ previousUsedAt: drizzle_orm_sqlite_core.SQLiteColumn<{
614
+ name: "previous_used_at";
615
+ tableName: "tokens";
616
+ dataType: "string";
617
+ columnType: "SQLiteText";
618
+ data: string;
619
+ driverParam: string;
620
+ notNull: false;
621
+ hasDefault: false;
622
+ isPrimaryKey: false;
623
+ isAutoincrement: false;
624
+ hasRuntimeDefault: false;
625
+ enumValues: [string, ...string[]];
626
+ baseColumn: never;
627
+ identity: undefined;
628
+ generated: undefined;
629
+ }, {}, {
630
+ length: number;
631
+ }>;
575
632
  type: drizzle_orm_sqlite_core.SQLiteColumn<{
576
633
  name: "type";
577
634
  tableName: "tokens";
@@ -1109,6 +1166,63 @@ declare const authSchema: {
1109
1166
  }, {}, {
1110
1167
  length: number;
1111
1168
  }>;
1169
+ previousHash: drizzle_orm_sqlite_core.SQLiteColumn<{
1170
+ name: "previous_hash";
1171
+ tableName: "tokens";
1172
+ dataType: "string";
1173
+ columnType: "SQLiteText";
1174
+ data: string;
1175
+ driverParam: string;
1176
+ notNull: false;
1177
+ hasDefault: false;
1178
+ isPrimaryKey: false;
1179
+ isAutoincrement: false;
1180
+ hasRuntimeDefault: false;
1181
+ enumValues: [string, ...string[]];
1182
+ baseColumn: never;
1183
+ identity: undefined;
1184
+ generated: undefined;
1185
+ }, {}, {
1186
+ length: number;
1187
+ }>;
1188
+ previousValidUntil: drizzle_orm_sqlite_core.SQLiteColumn<{
1189
+ name: "previous_valid_until";
1190
+ tableName: "tokens";
1191
+ dataType: "string";
1192
+ columnType: "SQLiteText";
1193
+ data: string;
1194
+ driverParam: string;
1195
+ notNull: false;
1196
+ hasDefault: false;
1197
+ isPrimaryKey: false;
1198
+ isAutoincrement: false;
1199
+ hasRuntimeDefault: false;
1200
+ enumValues: [string, ...string[]];
1201
+ baseColumn: never;
1202
+ identity: undefined;
1203
+ generated: undefined;
1204
+ }, {}, {
1205
+ length: number;
1206
+ }>;
1207
+ previousUsedAt: drizzle_orm_sqlite_core.SQLiteColumn<{
1208
+ name: "previous_used_at";
1209
+ tableName: "tokens";
1210
+ dataType: "string";
1211
+ columnType: "SQLiteText";
1212
+ data: string;
1213
+ driverParam: string;
1214
+ notNull: false;
1215
+ hasDefault: false;
1216
+ isPrimaryKey: false;
1217
+ isAutoincrement: false;
1218
+ hasRuntimeDefault: false;
1219
+ enumValues: [string, ...string[]];
1220
+ baseColumn: never;
1221
+ identity: undefined;
1222
+ generated: undefined;
1223
+ }, {}, {
1224
+ length: number;
1225
+ }>;
1112
1226
  type: drizzle_orm_sqlite_core.SQLiteColumn<{
1113
1227
  name: "type";
1114
1228
  tableName: "tokens";
@@ -42,6 +42,9 @@ var tokensTable = sqliteTable("tokens", {
42
42
  userId: text("user_id").references(() => usersTable.id, { onDelete: "cascade" }).unique().notNull(),
43
43
  token: text("token").notNull(),
44
44
  tokenFamily: text("token_family"),
45
+ previousHash: text("previous_hash"),
46
+ previousValidUntil: text("previous_valid_until"),
47
+ previousUsedAt: text("previous_used_at"),
45
48
  type: text("type").$type().default("refresh"),
46
49
  status: text("status").$type().default("active"),
47
50
  expiresAt: text("expires_at").notNull()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "najm-auth",
3
- "version": "1.1.25",
3
+ "version": "1.1.27",
4
4
  "description": "Authentication and authorization library for najm framework",
5
5
  "type": "module",
6
6
  "files": [