@weifuwujs/auth 0.9.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 (50) hide show
  1. package/README.md +172 -0
  2. package/dist/auth.d.ts +4 -0
  3. package/dist/auth.d.ts.map +1 -0
  4. package/dist/auth.js +625 -0
  5. package/dist/auth.js.map +1 -0
  6. package/dist/cli.d.ts +3 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +159 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/index.d.ts +6 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +4 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/password.d.ts +21 -0
  15. package/dist/password.d.ts.map +1 -0
  16. package/dist/password.js +75 -0
  17. package/dist/password.js.map +1 -0
  18. package/dist/postgres.d.ts +22 -0
  19. package/dist/postgres.d.ts.map +1 -0
  20. package/dist/postgres.js +240 -0
  21. package/dist/postgres.js.map +1 -0
  22. package/dist/sqlite.d.ts +3 -0
  23. package/dist/sqlite.d.ts.map +1 -0
  24. package/dist/sqlite.js +2 -0
  25. package/dist/sqlite.js.map +1 -0
  26. package/dist/stores/memory.d.ts +4 -0
  27. package/dist/stores/memory.d.ts.map +1 -0
  28. package/dist/stores/memory.js +150 -0
  29. package/dist/stores/memory.js.map +1 -0
  30. package/dist/stores/sqlite.d.ts +13 -0
  31. package/dist/stores/sqlite.d.ts.map +1 -0
  32. package/dist/stores/sqlite.js +215 -0
  33. package/dist/stores/sqlite.js.map +1 -0
  34. package/dist/testing.d.ts +13 -0
  35. package/dist/testing.d.ts.map +1 -0
  36. package/dist/testing.js +123 -0
  37. package/dist/testing.js.map +1 -0
  38. package/dist/types.d.ts +190 -0
  39. package/dist/types.d.ts.map +1 -0
  40. package/dist/types.js +2 -0
  41. package/dist/types.js.map +1 -0
  42. package/package.json +53 -0
  43. package/templates/react-router-auth/app/auth.ts +13 -0
  44. package/templates/react-router-auth/app/context.ts +6 -0
  45. package/templates/react-router-auth/app/routes/account.tsx +47 -0
  46. package/templates/react-router-auth/app/routes/login.tsx +59 -0
  47. package/templates/react-router-auth/app/routes/register.tsx +47 -0
  48. package/templates/react-router-auth/app/routes/reset-password.tsx +54 -0
  49. package/templates/react-router-auth/app/routes.ts +9 -0
  50. package/templates/react-router-auth/app/server.ts +31 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,159 @@
1
+ #!/usr/bin/env node
2
+ import { randomBytes } from 'node:crypto';
3
+ import { resolve } from 'node:path';
4
+ function parseArgs(argv) {
5
+ const command = argv[0] ?? 'help';
6
+ let root = process.cwd();
7
+ let store;
8
+ let password;
9
+ const rest = [];
10
+ for (let index = 1; index < argv.length; index++) {
11
+ const arg = argv[index];
12
+ if (arg === '--root' || arg.startsWith('--root=')) {
13
+ const value = arg.includes('=') ? arg.slice(arg.indexOf('=') + 1) : argv[++index];
14
+ if (!value)
15
+ throw new Error('--root 需要提供一个值');
16
+ root = resolve(value);
17
+ }
18
+ else if (arg === '--store' || arg.startsWith('--store=')) {
19
+ const value = arg.includes('=') ? arg.slice(arg.indexOf('=') + 1) : argv[++index];
20
+ if (!value)
21
+ throw new Error('--store 需要提供一个值');
22
+ store = value;
23
+ }
24
+ else if (arg === '--password' || arg.startsWith('--password=')) {
25
+ const value = arg.includes('=') ? arg.slice(arg.indexOf('=') + 1) : argv[++index];
26
+ if (!value)
27
+ throw new Error('--password 需要提供一个值');
28
+ password = value;
29
+ }
30
+ else {
31
+ rest.push(arg);
32
+ }
33
+ }
34
+ return { command, root, store, password, rest };
35
+ }
36
+ /** `weifuwu-auth migrate [--store sqlite:<path>|postgres://…]`(CLI 不加载用户代码) */
37
+ function openStore(options) {
38
+ const spec = options.store ?? 'sqlite:data/auth.db';
39
+ if (spec.startsWith('sqlite:')) {
40
+ const path = resolve(options.root, spec.slice('sqlite:'.length));
41
+ return import("./stores/sqlite.js").then(({ sqliteAuthStore }) => {
42
+ const authStore = sqliteAuthStore(path);
43
+ return { store: authStore, close: async () => authStore.close() };
44
+ });
45
+ }
46
+ if (spec.startsWith('postgres://') || spec.startsWith('postgresql://')) {
47
+ return import("./postgres.js").then(({ postgresAuthStore }) => {
48
+ const authStore = postgresAuthStore(spec);
49
+ return { store: authStore, close: () => authStore.close() };
50
+ });
51
+ }
52
+ return Promise.reject(new Error(`无法识别的 --store:${spec}(支持 sqlite:<path> 与 postgres://…)`));
53
+ }
54
+ async function authMigrate(options) {
55
+ const { store, close } = await openStore(options);
56
+ try {
57
+ await store.migrate?.();
58
+ console.log(`auth 迁移完成:${options.store ?? 'sqlite:data/auth.db'}`);
59
+ }
60
+ finally {
61
+ await close();
62
+ }
63
+ }
64
+ /** `user:list` / `user:disable <email>` / `user:reset-password <email> [--password <plain>]` */
65
+ async function userCommand(options) {
66
+ const { store, close } = await openStore(options);
67
+ try {
68
+ const email = options.rest[0] ?? '';
69
+ switch (options.command) {
70
+ case 'user:list': {
71
+ if (!store.listUsers) {
72
+ throw new Error('当前 store 未实现 listUsers()');
73
+ }
74
+ const users = await store.listUsers();
75
+ if (users.length === 0) {
76
+ console.log('(无用户)');
77
+ return;
78
+ }
79
+ for (const user of users) {
80
+ console.log([
81
+ user.id,
82
+ user.email,
83
+ user.role,
84
+ user.disabledAt
85
+ ? `disabled(${user.disabledAt.toISOString()})`
86
+ : 'active',
87
+ user.createdAt.toISOString(),
88
+ ].join('\t'));
89
+ }
90
+ return;
91
+ }
92
+ case 'user:disable': {
93
+ const { normalizeEmail } = await import("./password.js");
94
+ const normalized = normalizeEmail(email);
95
+ if (!normalized)
96
+ throw new Error('user:disable 需要 <email>');
97
+ const user = await store.findUserByEmail(normalized);
98
+ if (!user)
99
+ throw new Error(`用户不存在:${normalized}`);
100
+ await store.setUserDisabled(user.id, new Date());
101
+ console.log(`已禁用:${normalized}`);
102
+ return;
103
+ }
104
+ case 'user:reset-password': {
105
+ const { normalizeEmail, scryptHasher } = await import("./password.js");
106
+ const normalized = normalizeEmail(email);
107
+ if (!normalized)
108
+ throw new Error('user:reset-password 需要 <email>');
109
+ const user = await store.findUserByEmail(normalized);
110
+ if (!user)
111
+ throw new Error(`用户不存在:${normalized}`);
112
+ const password = options.password ?? randomBytes(24).toString('base64url');
113
+ await store.updateUserPassword(user.id, await scryptHasher.hash(password));
114
+ console.log(`已重置密码:${normalized}`);
115
+ if (!options.password)
116
+ console.log(`新密码(仅显示一次):${password}`);
117
+ return;
118
+ }
119
+ }
120
+ }
121
+ finally {
122
+ await close();
123
+ }
124
+ }
125
+ function printHelp() {
126
+ console.log(`用法:weifuwu-auth <命令> [选项]
127
+
128
+ 命令:
129
+ migrate 迁移 auth 数据表(sqlite/postgres)
130
+ user:list 列出用户
131
+ user:disable <email> 禁用用户
132
+ user:reset-password <email> 重置密码(省略明文则随机生成并打印一次)
133
+
134
+ 选项:
135
+ --root <dir> 项目根目录,默认当前目录
136
+ --store <url> 数据源,默认 sqlite:data/auth.db(支持 sqlite:<path> 与 postgres://…)
137
+ --password <plain> user:reset-password 的明文新密码(省略则随机生成)
138
+ `);
139
+ }
140
+ const options = parseArgs(process.argv.slice(2));
141
+ try {
142
+ switch (options.command) {
143
+ case 'migrate':
144
+ await authMigrate(options);
145
+ break;
146
+ case 'user:list':
147
+ case 'user:disable':
148
+ case 'user:reset-password':
149
+ await userCommand(options);
150
+ break;
151
+ default:
152
+ printHelp();
153
+ }
154
+ }
155
+ catch (error) {
156
+ console.error(error instanceof Error ? error.message : error);
157
+ process.exit(1);
158
+ }
159
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAWnC,SAAS,SAAS,CAAC,IAAc;IAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,MAAM,CAAA;IACjC,IAAI,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAA;IACxB,IAAI,KAAyB,CAAA;IAC7B,IAAI,QAA4B,CAAA;IAChC,MAAM,IAAI,GAAa,EAAE,CAAA;IAEzB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;QACjD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAE,CAAA;QACxB,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAClD,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAA;YACjF,IAAI,CAAC,KAAK;gBAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAA;YAC7C,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAA;QACvB,CAAC;aAAM,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3D,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAA;YACjF,IAAI,CAAC,KAAK;gBAAE,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAA;YAC9C,KAAK,GAAG,KAAK,CAAA;QACf,CAAC;aAAM,IAAI,GAAG,KAAK,YAAY,IAAI,GAAG,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;YACjE,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAA;YACjF,IAAI,CAAC,KAAK;gBAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAA;YACjD,QAAQ,GAAG,KAAK,CAAA;QAClB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAChB,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAA;AACjD,CAAC;AAED,+EAA+E;AAC/E,SAAS,SAAS,CAChB,OAAmB;IAEnB,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,IAAI,qBAAqB,CAAA;IACnD,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAA;QAChE,OAAO,MAAM,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,eAAe,EAAE,EAAE,EAAE;YAC/D,MAAM,SAAS,GAAG,eAAe,CAAC,IAAI,CAAC,CAAA;YACvC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE,CAAA;QACnE,CAAC,CAAC,CAAA;IACJ,CAAC;IACD,IAAI,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QACvE,OAAO,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,iBAAiB,EAAE,EAAE,EAAE;YAC5D,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAA;YACzC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE,CAAA;QAC7D,CAAC,CAAC,CAAA;IACJ,CAAC;IACD,OAAO,OAAO,CAAC,MAAM,CACnB,IAAI,KAAK,CAAC,iBAAiB,IAAI,mCAAmC,CAAC,CACpE,CAAA;AACH,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,OAAmB;IAC5C,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,CAAA;IACjD,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,OAAO,EAAE,EAAE,CAAA;QACvB,OAAO,CAAC,GAAG,CAAC,aAAa,OAAO,CAAC,KAAK,IAAI,qBAAqB,EAAE,CAAC,CAAA;IACpE,CAAC;YAAS,CAAC;QACT,MAAM,KAAK,EAAE,CAAA;IACf,CAAC;AACH,CAAC;AAED,gGAAgG;AAChG,KAAK,UAAU,WAAW,CAAC,OAAmB;IAC5C,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,CAAA;IACjD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;QACnC,QAAQ,OAAO,CAAC,OAAO,EAAE,CAAC;YACxB,KAAK,WAAW,CAAC,CAAC,CAAC;gBACjB,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;oBACrB,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA;gBAC7C,CAAC;gBACD,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,SAAS,EAAE,CAAA;gBACrC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACvB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;oBACpB,OAAM;gBACR,CAAC;gBACD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBACzB,OAAO,CAAC,GAAG,CACT;wBACE,IAAI,CAAC,EAAE;wBACP,IAAI,CAAC,KAAK;wBACV,IAAI,CAAC,IAAI;wBACT,IAAI,CAAC,UAAU;4BACb,CAAC,CAAC,YAAY,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,GAAG;4BAC9C,CAAC,CAAC,QAAQ;wBACZ,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE;qBAC7B,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAA;gBACH,CAAC;gBACD,OAAM;YACR,CAAC;YACD,KAAK,cAAc,CAAC,CAAC,CAAC;gBACpB,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAA;gBACxD,MAAM,UAAU,GAAG,cAAc,CAAC,KAAK,CAAC,CAAA;gBACxC,IAAI,CAAC,UAAU;oBAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAA;gBAC3D,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,eAAe,CAAC,UAAU,CAAC,CAAA;gBACpD,IAAI,CAAC,IAAI;oBAAE,MAAM,IAAI,KAAK,CAAC,SAAS,UAAU,EAAE,CAAC,CAAA;gBACjD,MAAM,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,CAAA;gBAChD,OAAO,CAAC,GAAG,CAAC,OAAO,UAAU,EAAE,CAAC,CAAA;gBAChC,OAAM;YACR,CAAC;YACD,KAAK,qBAAqB,CAAC,CAAC,CAAC;gBAC3B,MAAM,EAAE,cAAc,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAA;gBACtE,MAAM,UAAU,GAAG,cAAc,CAAC,KAAK,CAAC,CAAA;gBACxC,IAAI,CAAC,UAAU;oBAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAA;gBAClE,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,eAAe,CAAC,UAAU,CAAC,CAAA;gBACpD,IAAI,CAAC,IAAI;oBAAE,MAAM,IAAI,KAAK,CAAC,SAAS,UAAU,EAAE,CAAC,CAAA;gBACjD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;gBAC1E,MAAM,KAAK,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAA;gBAC1E,OAAO,CAAC,GAAG,CAAC,SAAS,UAAU,EAAE,CAAC,CAAA;gBAClC,IAAI,CAAC,OAAO,CAAC,QAAQ;oBAAE,OAAO,CAAC,GAAG,CAAC,cAAc,QAAQ,EAAE,CAAC,CAAA;gBAC5D,OAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;YAAS,CAAC;QACT,MAAM,KAAK,EAAE,CAAA;IACf,CAAC;AACH,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;CAYb,CAAC,CAAA;AACF,CAAC;AAED,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;AAEhD,IAAI,CAAC;IACH,QAAQ,OAAO,CAAC,OAAO,EAAE,CAAC;QACxB,KAAK,SAAS;YACZ,MAAM,WAAW,CAAC,OAAO,CAAC,CAAA;YAC1B,MAAK;QACP,KAAK,WAAW,CAAC;QACjB,KAAK,cAAc,CAAC;QACpB,KAAK,qBAAqB;YACxB,MAAM,WAAW,CAAC,OAAO,CAAC,CAAA;YAC1B,MAAK;QACP;YACE,SAAS,EAAE,CAAA;IACf,CAAC;AACH,CAAC;AAAC,OAAO,KAAK,EAAE,CAAC;IACf,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;IAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { createAuth } from './auth.ts';
2
+ export { memoryAuthStore } from './stores/memory.ts';
3
+ export { scryptHasher, scryptHash, scryptVerify, normalizeEmail, isValidEmail, validatePassword, SCRYPT_DEFAULTS, } from './password.ts';
4
+ export type { ScryptParams } from './password.ts';
5
+ export type { Auth, AuthCheck, AuthContext, AuthErrorCode, AuthHooks, AuthOptions, AuthResult, AuthRole, AuthSession, AuthStore, AuthUser, PasswordHasher, PublicUser, RateLimitOptions, RateLimitStore, ResetTokenStore, SessionOptions, SessionStore, UserStore, } from './types.ts';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,EACL,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,eAAe,GAChB,MAAM,eAAe,CAAA;AACtB,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACjD,YAAY,EACV,IAAI,EACJ,SAAS,EACT,WAAW,EACX,aAAa,EACb,SAAS,EACT,WAAW,EACX,UAAU,EACV,QAAQ,EACR,WAAW,EACX,SAAS,EACT,QAAQ,EACR,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,cAAc,EACd,YAAY,EACZ,SAAS,GACV,MAAM,YAAY,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { createAuth } from "./auth.js";
2
+ export { memoryAuthStore } from "./stores/memory.js";
3
+ export { scryptHasher, scryptHash, scryptVerify, normalizeEmail, isValidEmail, validatePassword, SCRYPT_DEFAULTS, } from "./password.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,EACL,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,eAAe,GAChB,MAAM,eAAe,CAAA"}
@@ -0,0 +1,21 @@
1
+ import type { PasswordHasher } from './types.ts';
2
+ export interface ScryptParams {
3
+ N: number;
4
+ r: number;
5
+ p: number;
6
+ keylen: number;
7
+ }
8
+ export declare const SCRYPT_DEFAULTS: ScryptParams;
9
+ /**
10
+ * 哈希格式:`scrypt$N$r$p$salt$hash`(base64url)。
11
+ * 参数随哈希入库,调参不需要迁移旧数据。
12
+ */
13
+ export declare function scryptHash(plain: string, params?: ScryptParams): Promise<string>;
14
+ export declare function scryptVerify(plain: string, stored: string): Promise<boolean>;
15
+ /** 默认 hasher:scrypt + 参数变化时惰性重算 */
16
+ export declare const scryptHasher: PasswordHasher;
17
+ /** 校验密码策略:返回错误码或 null */
18
+ export declare function validatePassword(password: string, minLength?: number): 'weak_password' | null;
19
+ export declare function normalizeEmail(email: string): string;
20
+ export declare function isValidEmail(email: string): boolean;
21
+ //# sourceMappingURL=password.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"password.d.ts","sourceRoot":"","sources":["../src/password.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAgBhD,MAAM,WAAW,YAAY;IAC3B,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,MAAM,EAAE,MAAM,CAAA;CACf;AAED,eAAO,MAAM,eAAe,EAAE,YAAmD,CAAA;AAEjF;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,YAA8B,GACrC,OAAO,CAAC,MAAM,CAAC,CAejB;AAED,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAalF;AAED,mCAAmC;AACnC,eAAO,MAAM,YAAY,EAAE,cAY1B,CAAA;AAED,yBAAyB;AACzB,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,SAAS,SAAI,GACZ,eAAe,GAAG,IAAI,CAIxB;AAID,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEnD"}
@@ -0,0 +1,75 @@
1
+ import { randomBytes, scrypt as scryptCallback, timingSafeEqual } from 'node:crypto';
2
+ function deriveKey(plain, salt, keylen, options) {
3
+ return new Promise((resolve, reject) => {
4
+ scryptCallback(plain, salt, keylen, options, (error, derived) => {
5
+ if (error)
6
+ reject(error);
7
+ else
8
+ resolve(derived);
9
+ });
10
+ });
11
+ }
12
+ export const SCRYPT_DEFAULTS = { N: 16384, r: 8, p: 1, keylen: 64 };
13
+ /**
14
+ * 哈希格式:`scrypt$N$r$p$salt$hash`(base64url)。
15
+ * 参数随哈希入库,调参不需要迁移旧数据。
16
+ */
17
+ export async function scryptHash(plain, params = SCRYPT_DEFAULTS) {
18
+ const salt = randomBytes(16);
19
+ const derived = await deriveKey(plain, salt, params.keylen, {
20
+ N: params.N,
21
+ r: params.r,
22
+ p: params.p,
23
+ });
24
+ return [
25
+ 'scrypt',
26
+ params.N,
27
+ params.r,
28
+ params.p,
29
+ salt.toString('base64url'),
30
+ derived.toString('base64url'),
31
+ ].join('$');
32
+ }
33
+ export async function scryptVerify(plain, stored) {
34
+ const parts = stored.split('$');
35
+ if (parts.length !== 6 || parts[0] !== 'scrypt')
36
+ return false;
37
+ const N = Number(parts[1]);
38
+ const r = Number(parts[2]);
39
+ const p = Number(parts[3]);
40
+ if (!Number.isInteger(N) || !Number.isInteger(r) || !Number.isInteger(p)) {
41
+ return false;
42
+ }
43
+ const salt = Buffer.from(parts[4], 'base64url');
44
+ const expected = Buffer.from(parts[5], 'base64url');
45
+ const derived = await deriveKey(plain, salt, expected.length, { N, r, p });
46
+ return derived.length === expected.length && timingSafeEqual(derived, expected);
47
+ }
48
+ /** 默认 hasher:scrypt + 参数变化时惰性重算 */
49
+ export const scryptHasher = {
50
+ hash: (plain) => scryptHash(plain),
51
+ verify: (plain, stored) => scryptVerify(plain, stored),
52
+ needsRehash: (stored) => {
53
+ const params = stored.split('$');
54
+ return (params[0] !== 'scrypt' ||
55
+ Number(params[1]) !== SCRYPT_DEFAULTS.N ||
56
+ Number(params[2]) !== SCRYPT_DEFAULTS.r ||
57
+ Number(params[3]) !== SCRYPT_DEFAULTS.p);
58
+ },
59
+ };
60
+ /** 校验密码策略:返回错误码或 null */
61
+ export function validatePassword(password, minLength = 8) {
62
+ if (typeof password !== 'string')
63
+ return 'weak_password';
64
+ if (password.length < minLength || password.length > 200)
65
+ return 'weak_password';
66
+ return null;
67
+ }
68
+ const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
69
+ export function normalizeEmail(email) {
70
+ return typeof email === 'string' ? email.trim().toLowerCase() : '';
71
+ }
72
+ export function isValidEmail(email) {
73
+ return email.length <= 254 && EMAIL_RE.test(email);
74
+ }
75
+ //# sourceMappingURL=password.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"password.js","sourceRoot":"","sources":["../src/password.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,IAAI,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAGpF,SAAS,SAAS,CAChB,KAAa,EACb,IAAY,EACZ,MAAc,EACd,OAA4C;IAE5C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,cAAc,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAC9D,IAAI,KAAK;gBAAE,MAAM,CAAC,KAAK,CAAC,CAAA;;gBACnB,OAAO,CAAC,OAAiB,CAAC,CAAA;QACjC,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC;AASD,MAAM,CAAC,MAAM,eAAe,GAAiB,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAA;AAEjF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,KAAa,EACb,SAAuB,eAAe;IAEtC,MAAM,IAAI,GAAG,WAAW,CAAC,EAAE,CAAC,CAAA;IAC5B,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE;QAC1D,CAAC,EAAE,MAAM,CAAC,CAAC;QACX,CAAC,EAAE,MAAM,CAAC,CAAC;QACX,CAAC,EAAE,MAAM,CAAC,CAAC;KACZ,CAAC,CAAA;IACF,OAAO;QACL,QAAQ;QACR,MAAM,CAAC,CAAC;QACR,MAAM,CAAC,CAAC;QACR,MAAM,CAAC,CAAC;QACR,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC;QAC1B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;KAC9B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACb,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,KAAa,EAAE,MAAc;IAC9D,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAC7D,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;IAC1B,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;IAC1B,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;IAC1B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;QACzE,OAAO,KAAK,CAAA;IACd,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,WAAW,CAAC,CAAA;IAChD,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,WAAW,CAAC,CAAA;IACpD,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;IAC1E,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,IAAI,eAAe,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;AACjF,CAAC;AAED,mCAAmC;AACnC,MAAM,CAAC,MAAM,YAAY,GAAmB;IAC1C,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC;IAClC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC;IACtD,WAAW,EAAE,CAAC,MAAM,EAAE,EAAE;QACtB,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAChC,OAAO,CACL,MAAM,CAAC,CAAC,CAAC,KAAK,QAAQ;YACtB,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,eAAe,CAAC,CAAC;YACvC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,eAAe,CAAC,CAAC;YACvC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,eAAe,CAAC,CAAC,CACxC,CAAA;IACH,CAAC;CACF,CAAA;AAED,yBAAyB;AACzB,MAAM,UAAU,gBAAgB,CAC9B,QAAgB,EAChB,SAAS,GAAG,CAAC;IAEb,IAAI,OAAO,QAAQ,KAAK,QAAQ;QAAE,OAAO,eAAe,CAAA;IACxD,IAAI,QAAQ,CAAC,MAAM,GAAG,SAAS,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG;QAAE,OAAO,eAAe,CAAA;IAChF,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,QAAQ,GAAG,4BAA4B,CAAA;AAE7C,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;AACpE,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,OAAO,KAAK,CAAC,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;AACpD,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type postgresJs from 'postgres';
2
+ import type { AuthStore } from './types.ts';
3
+ export interface PostgresAuthStore extends AuthStore {
4
+ migrate(): Promise<void>;
5
+ close(): Promise<void>;
6
+ }
7
+ /** postgres.js 的 options(其泛型无默认值,同 `./postgres`) */
8
+ type PostgresOptions = NonNullable<Parameters<typeof postgresJs>[1]>;
9
+ /**
10
+ * postgres 实现(复用 `postgres.js`,与 `./postgres` 的 `ctx.sql` 同一客户端)。
11
+ *
12
+ * ```ts
13
+ * postgresAuthStore('postgres://…') // 连接串
14
+ * postgresAuthStore(process.env.DATABASE_URL)
15
+ * postgresAuthStore(ctx.sql) // 注入已有客户端(不负责 close)
16
+ * ```
17
+ *
18
+ * 表结构与 sqlite 对齐;`migrate()` 幂等(`auth_migrations` 版本记录)。
19
+ */
20
+ export declare function postgresAuthStore(urlOrSql?: string | postgresJs.Sql, options?: PostgresOptions): PostgresAuthStore;
21
+ export {};
22
+ //# sourceMappingURL=postgres.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../src/postgres.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,UAAU,MAAM,UAAU,CAAA;AACtC,OAAO,KAAK,EAAe,SAAS,EAAY,MAAM,YAAY,CAAA;AAoFlE,MAAM,WAAW,iBAAkB,SAAQ,SAAS;IAClD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AAED,oDAAoD;AACpD,KAAK,eAAe,GAAG,WAAW,CAAC,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAEpE;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC,GAAG,EAClC,OAAO,CAAC,EAAE,eAAe,GACxB,iBAAiB,CAyLnB"}
@@ -0,0 +1,240 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ const SCHEMA = [
3
+ `
4
+ CREATE TABLE IF NOT EXISTS users (
5
+ id TEXT PRIMARY KEY,
6
+ email TEXT NOT NULL UNIQUE,
7
+ password_hash TEXT NOT NULL,
8
+ role TEXT NOT NULL DEFAULT 'user',
9
+ disabled_at TEXT,
10
+ created_at TEXT NOT NULL,
11
+ updated_at TEXT NOT NULL
12
+ )`,
13
+ `
14
+ CREATE TABLE IF NOT EXISTS sessions (
15
+ id TEXT PRIMARY KEY,
16
+ user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
17
+ token_hash TEXT NOT NULL UNIQUE,
18
+ created_at TEXT NOT NULL,
19
+ expires_at TEXT NOT NULL,
20
+ last_seen_at TEXT NOT NULL
21
+ )`,
22
+ 'CREATE INDEX IF NOT EXISTS sessions_user_id_idx ON sessions(user_id)',
23
+ `
24
+ CREATE TABLE IF NOT EXISTS password_resets (
25
+ token_hash TEXT PRIMARY KEY,
26
+ user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
27
+ expires_at TEXT NOT NULL,
28
+ used_at TEXT
29
+ )`,
30
+ ];
31
+ function uniqueViolation(error, code) {
32
+ if (error.code === '23505') {
33
+ throw Object.assign(new Error(code), { code });
34
+ }
35
+ throw error;
36
+ }
37
+ function toUser(row) {
38
+ return {
39
+ id: row.id,
40
+ email: row.email,
41
+ passwordHash: row.password_hash,
42
+ role: row.role === 'admin' ? 'admin' : 'user',
43
+ disabledAt: row.disabled_at ? new Date(row.disabled_at) : null,
44
+ createdAt: new Date(row.created_at),
45
+ updatedAt: new Date(row.updated_at),
46
+ };
47
+ }
48
+ function toSession(row) {
49
+ return {
50
+ id: row.id,
51
+ userId: row.user_id,
52
+ tokenHash: row.token_hash,
53
+ createdAt: new Date(row.created_at),
54
+ expiresAt: new Date(row.expires_at),
55
+ lastSeenAt: new Date(row.last_seen_at),
56
+ };
57
+ }
58
+ /**
59
+ * postgres 实现(复用 `postgres.js`,与 `./postgres` 的 `ctx.sql` 同一客户端)。
60
+ *
61
+ * ```ts
62
+ * postgresAuthStore('postgres://…') // 连接串
63
+ * postgresAuthStore(process.env.DATABASE_URL)
64
+ * postgresAuthStore(ctx.sql) // 注入已有客户端(不负责 close)
65
+ * ```
66
+ *
67
+ * 表结构与 sqlite 对齐;`migrate()` 幂等(`auth_migrations` 版本记录)。
68
+ */
69
+ export function postgresAuthStore(urlOrSql, options) {
70
+ const injected = typeof urlOrSql === 'function' ? urlOrSql : null;
71
+ let client = injected
72
+ ? Promise.resolve(injected)
73
+ : null;
74
+ const sql = () => {
75
+ client ??= (async () => {
76
+ const { default: createPostgres } = (await import('postgres'));
77
+ if (typeof urlOrSql === 'string')
78
+ return createPostgres(urlOrSql, options);
79
+ const url = process.env.DATABASE_URL;
80
+ if (url)
81
+ return createPostgres(url, options);
82
+ return createPostgres(options);
83
+ })();
84
+ return client;
85
+ };
86
+ const applyMigrations = async (db) => {
87
+ await db `
88
+ CREATE TABLE IF NOT EXISTS auth_migrations (
89
+ version INTEGER PRIMARY KEY,
90
+ applied_at TEXT NOT NULL
91
+ )`;
92
+ const applied = await db `SELECT version FROM auth_migrations WHERE version = 1`;
93
+ if (applied.length > 0)
94
+ return;
95
+ await db.begin(async (tx) => {
96
+ for (const statement of SCHEMA)
97
+ await tx.unsafe(statement);
98
+ await tx `INSERT INTO auth_migrations (version, applied_at) VALUES (1, ${new Date().toISOString()})`;
99
+ });
100
+ };
101
+ return {
102
+ async migrate() {
103
+ await applyMigrations(await sql());
104
+ },
105
+ async close() {
106
+ if (!client || injected)
107
+ return;
108
+ const db = await client;
109
+ client = null;
110
+ await db.end({ timeout: 5 });
111
+ },
112
+ async createUser({ email, passwordHash, role = 'user' }) {
113
+ const db = await sql();
114
+ const timestamp = new Date().toISOString();
115
+ const id = randomUUID();
116
+ try {
117
+ await db `
118
+ INSERT INTO users (id, email, password_hash, role, disabled_at, created_at, updated_at)
119
+ VALUES (${id}, ${email}, ${passwordHash}, ${role}, NULL, ${timestamp}, ${timestamp})`;
120
+ }
121
+ catch (error) {
122
+ uniqueViolation(error, 'email_taken');
123
+ }
124
+ return {
125
+ id,
126
+ email,
127
+ passwordHash,
128
+ role,
129
+ disabledAt: null,
130
+ createdAt: new Date(timestamp),
131
+ updatedAt: new Date(timestamp),
132
+ };
133
+ },
134
+ async findUserByEmail(email) {
135
+ const db = await sql();
136
+ const rows = (await db `SELECT * FROM users WHERE email = ${email} LIMIT 1`);
137
+ return rows[0] ? toUser(rows[0]) : null;
138
+ },
139
+ async findUserById(id) {
140
+ const db = await sql();
141
+ const rows = (await db `SELECT * FROM users WHERE id = ${id} LIMIT 1`);
142
+ return rows[0] ? toUser(rows[0]) : null;
143
+ },
144
+ async listUsers() {
145
+ const db = await sql();
146
+ const rows = (await db `SELECT * FROM users ORDER BY created_at`);
147
+ return rows.map(toUser);
148
+ },
149
+ async updateUserEmail(id, email) {
150
+ const db = await sql();
151
+ try {
152
+ await db `UPDATE users SET email = ${email}, updated_at = ${new Date().toISOString()} WHERE id = ${id}`;
153
+ }
154
+ catch (error) {
155
+ uniqueViolation(error, 'email_taken');
156
+ }
157
+ },
158
+ async updateUserPassword(id, passwordHash) {
159
+ const db = await sql();
160
+ await db `UPDATE users SET password_hash = ${passwordHash}, updated_at = ${new Date().toISOString()} WHERE id = ${id}`;
161
+ },
162
+ async setUserRole(id, role) {
163
+ const db = await sql();
164
+ await db `UPDATE users SET role = ${role}, updated_at = ${new Date().toISOString()} WHERE id = ${id}`;
165
+ },
166
+ async setUserDisabled(id, disabledAt) {
167
+ const db = await sql();
168
+ await db `UPDATE users SET disabled_at = ${disabledAt ? disabledAt.toISOString() : null}, updated_at = ${new Date().toISOString()} WHERE id = ${id}`;
169
+ },
170
+ async createSession({ userId, tokenHash, expiresAt }) {
171
+ const db = await sql();
172
+ const timestamp = new Date().toISOString();
173
+ const session = {
174
+ id: randomUUID(),
175
+ userId,
176
+ tokenHash,
177
+ createdAt: new Date(timestamp),
178
+ expiresAt,
179
+ lastSeenAt: new Date(timestamp),
180
+ };
181
+ await db `
182
+ INSERT INTO sessions (id, user_id, token_hash, created_at, expires_at, last_seen_at)
183
+ VALUES (${session.id}, ${userId}, ${tokenHash}, ${timestamp}, ${expiresAt.toISOString()}, ${timestamp})`;
184
+ return session;
185
+ },
186
+ async findSessionByTokenHash(tokenHash) {
187
+ const db = await sql();
188
+ const rows = (await db `SELECT * FROM sessions WHERE token_hash = ${tokenHash} LIMIT 1`);
189
+ return rows[0] ? toSession(rows[0]) : null;
190
+ },
191
+ async touchSession(id, lastSeenAt) {
192
+ const db = await sql();
193
+ await db `UPDATE sessions SET last_seen_at = ${lastSeenAt.toISOString()} WHERE id = ${id}`;
194
+ },
195
+ async deleteSession(id) {
196
+ const db = await sql();
197
+ await db `DELETE FROM sessions WHERE id = ${id}`;
198
+ },
199
+ async deleteUserSessions(userId, exceptId) {
200
+ const db = await sql();
201
+ if (exceptId) {
202
+ await db `DELETE FROM sessions WHERE user_id = ${userId} AND id <> ${exceptId}`;
203
+ }
204
+ else {
205
+ await db `DELETE FROM sessions WHERE user_id = ${userId}`;
206
+ }
207
+ },
208
+ async deleteExpiredSessions(now) {
209
+ const db = await sql();
210
+ const rows = (await db `DELETE FROM sessions WHERE expires_at <= ${now.toISOString()} RETURNING id`);
211
+ return rows.length;
212
+ },
213
+ async createResetToken({ userId, tokenHash, expiresAt }) {
214
+ const db = await sql();
215
+ try {
216
+ await db `
217
+ INSERT INTO password_resets (token_hash, user_id, expires_at, used_at)
218
+ VALUES (${tokenHash}, ${userId}, ${expiresAt.toISOString()}, NULL)`;
219
+ }
220
+ catch (error) {
221
+ uniqueViolation(error, 'invalid_token');
222
+ }
223
+ },
224
+ async consumeResetToken(tokenHash, now) {
225
+ const db = await sql();
226
+ const timestamp = now.toISOString();
227
+ const rows = (await db `
228
+ UPDATE password_resets SET used_at = ${timestamp}
229
+ WHERE token_hash = ${tokenHash} AND used_at IS NULL AND expires_at > ${timestamp}
230
+ RETURNING user_id`);
231
+ return rows[0]?.user_id ?? null;
232
+ },
233
+ async deleteExpiredResetTokens(now) {
234
+ const db = await sql();
235
+ const rows = (await db `DELETE FROM password_resets WHERE expires_at <= ${now.toISOString()} RETURNING token_hash`);
236
+ return rows.length;
237
+ },
238
+ };
239
+ }
240
+ //# sourceMappingURL=postgres.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres.js","sourceRoot":"","sources":["../src/postgres.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { sqliteAuthStore } from './stores/sqlite.ts';
2
+ export type { SqliteAuthStore } from './stores/sqlite.ts';
3
+ //# sourceMappingURL=sqlite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../src/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA"}
package/dist/sqlite.js ADDED
@@ -0,0 +1,2 @@
1
+ export { sqliteAuthStore } from "./stores/sqlite.js";
2
+ //# sourceMappingURL=sqlite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../src/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA"}
@@ -0,0 +1,4 @@
1
+ import type { AuthStore } from '../types.ts';
2
+ /** 内存实现:测试默认,也可用于单进程开发 */
3
+ export declare function memoryAuthStore(): AuthStore;
4
+ //# sourceMappingURL=memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/stores/memory.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAe,SAAS,EAAY,MAAM,aAAa,CAAA;AAcnE,0BAA0B;AAC1B,wBAAgB,eAAe,IAAI,SAAS,CAkJ3C"}