najm-auth 1.1.26 → 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,14 +722,13 @@ 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
733
  validateRefreshSession(refreshToken: string): Promise<{
731
734
  userId: string;
@@ -736,10 +739,8 @@ declare class TokenService {
736
739
  }>;
737
740
  /**
738
741
  * Read the refresh cookie and return the userId it belongs to.
739
- * Lightweight check: verifies JWT signature and ensures the user
740
- * has an active session in the DB. Does NOT compare token hashes,
741
- * so it is safe to call concurrently with token rotation.
742
- * 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.
743
744
  */
744
745
  resolveUserFromCookie(): Promise<string>;
745
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,22 +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) {
1480
+ const presentedHash = this.hashToken(refreshToken);
1481
+ if (presentedHash === stored.token) {
1482
+ return { userId };
1483
+ }
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);
1464
1487
  const tokens = await this.generateTokens(userId, stored.tokenFamily ?? void 0);
1465
1488
  return {
1466
1489
  userId,
1467
1490
  rotatedTokens: { refreshToken: tokens.refreshToken, tokenFamily: stored.tokenFamily }
1468
1491
  };
1469
1492
  }
1470
- return { userId };
1493
+ Err5(this.t("errors.refreshTokenInvalid"));
1471
1494
  }
1472
1495
  /**
1473
1496
  * Read the refresh cookie and return the userId it belongs to.
1474
- * Lightweight check: verifies JWT signature and ensures the user
1475
- * has an active session in the DB. Does NOT compare token hashes,
1476
- * so it is safe to call concurrently with token rotation.
1477
- * 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.
1478
1499
  */
1479
1500
  async resolveUserFromCookie() {
1480
1501
  const refreshToken = this.cookieManager.getRefreshToken();
@@ -1486,7 +1507,15 @@ var TokenService = class TokenService2 {
1486
1507
  if (!stored) {
1487
1508
  Err5(this.t("errors.refreshTokenInvalid"));
1488
1509
  }
1489
- 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"));
1490
1519
  }
1491
1520
  // ============ USER RETRIEVAL (MAIN METHOD) ============
1492
1521
  async getUser(auth2) {
@@ -1590,11 +1619,17 @@ var TokenService = class TokenService2 {
1590
1619
  async storeRefreshToken(userId, refreshToken, tokenFamily) {
1591
1620
  const expireInSecond = timestring2(this.config.jwt.refreshExpiresIn, "s");
1592
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;
1593
1625
  await this.tokenRepository.storeRefreshToken({
1594
1626
  userId,
1595
1627
  token: hashedToken,
1596
1628
  tokenFamily,
1597
- expiresAt: new Date(Date.now() + expireInSecond * 1e3).toISOString()
1629
+ expiresAt: new Date(Date.now() + expireInSecond * 1e3).toISOString(),
1630
+ previousHash,
1631
+ previousValidUntil,
1632
+ previousUsedAt: null
1598
1633
  });
1599
1634
  }
1600
1635
  /**
@@ -1611,7 +1646,16 @@ var TokenService = class TokenService2 {
1611
1646
  if (!stored) {
1612
1647
  Err5(this.t("errors.refreshTokenInvalid"));
1613
1648
  }
1614
- return this.generateTokens(userId, stored.tokenFamily ?? void 0);
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);
1657
+ }
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);
@@ -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.26",
3
+ "version": "1.1.27",
4
4
  "description": "Authentication and authorization library for najm framework",
5
5
  "type": "module",
6
6
  "files": [