@korajs/auth 1.0.0-beta.13 → 1.0.0-beta.14
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/server.cjs +38 -2
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +32 -2
- package/dist/server.d.ts +32 -2
- package/dist/server.js +38 -2
- package/dist/server.js.map +1 -1
- package/package.json +5 -5
- package/src/provider/built-in/postgres-user-store.ts +39 -2
- package/src/provider/built-in/sqlite-user-store.ts +13 -0
- package/src/provider/oauth/sqlite-oauth-store.ts +13 -0
- package/src/server.ts +5 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@korajs/auth",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.14",
|
|
4
4
|
"description": "Offline-first authentication for Kora.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"!src/**/*.test.ts"
|
|
68
68
|
],
|
|
69
69
|
"dependencies": {
|
|
70
|
-
"@korajs/core": "1.0.0-beta.
|
|
70
|
+
"@korajs/core": "1.0.0-beta.14"
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
73
|
"@types/better-sqlite3": "^7.6.13",
|
|
@@ -78,9 +78,9 @@
|
|
|
78
78
|
"typescript": "^5.7.0",
|
|
79
79
|
"vitest": "^3.0.0",
|
|
80
80
|
"vue": "^3.5.0",
|
|
81
|
-
"@korajs/server": "1.0.0-beta.
|
|
82
|
-
"@korajs/
|
|
83
|
-
"@korajs/
|
|
81
|
+
"@korajs/server": "1.0.0-beta.14",
|
|
82
|
+
"@korajs/sync": "1.0.0-beta.14",
|
|
83
|
+
"@korajs/store": "1.0.0-beta.14"
|
|
84
84
|
},
|
|
85
85
|
"peerDependencies": {
|
|
86
86
|
"react": "^18.0.0 || ^19.0.0",
|
|
@@ -13,6 +13,18 @@ import { DeviceOwnershipError, DuplicateEmailError } from './user-store'
|
|
|
13
13
|
interface PostgresClient {
|
|
14
14
|
begin<T>(fn: (sql: PostgresClient) => Promise<T>): Promise<T>
|
|
15
15
|
(template: TemplateStringsArray, ...args: unknown[]): Promise<Record<string, unknown>[]>
|
|
16
|
+
/** postgres-js: close every connection of the pool (optional in this subset). */
|
|
17
|
+
end?(options?: { timeout?: number }): Promise<void>
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Options for {@link PostgresUserStore}. */
|
|
21
|
+
export interface PostgresUserStoreOptions {
|
|
22
|
+
/**
|
|
23
|
+
* Whether {@link PostgresUserStore.close} ends the client's connections. True for
|
|
24
|
+
* a store made by `createPostgresUserStore` (it opened the client); false by
|
|
25
|
+
* default for a client you pass in, which you end yourself.
|
|
26
|
+
*/
|
|
27
|
+
ownsClient?: boolean
|
|
16
28
|
}
|
|
17
29
|
|
|
18
30
|
/**
|
|
@@ -33,6 +45,8 @@ interface PostgresClient {
|
|
|
33
45
|
* connectionString: 'postgres://user:pass@localhost:5432/mydb',
|
|
34
46
|
* })
|
|
35
47
|
* const routes = new BuiltInAuthRoutes({ userStore, tokenManager })
|
|
48
|
+
* // On shutdown (or at the end of a script):
|
|
49
|
+
* await userStore.close()
|
|
36
50
|
* ```
|
|
37
51
|
*/
|
|
38
52
|
export class PostgresUserStore implements UserStore {
|
|
@@ -41,11 +55,34 @@ export class PostgresUserStore implements UserStore {
|
|
|
41
55
|
|
|
42
56
|
private revocationStore: PostgresTokenRevocationStore | null = null
|
|
43
57
|
|
|
44
|
-
|
|
58
|
+
private readonly ownsClient: boolean
|
|
59
|
+
private closed = false
|
|
60
|
+
|
|
61
|
+
constructor(sql: PostgresClient, options: PostgresUserStoreOptions = {}) {
|
|
45
62
|
this.sql = sql
|
|
63
|
+
this.ownsClient = options.ownsClient ?? false
|
|
46
64
|
this.ready = this.ensureTables()
|
|
47
65
|
}
|
|
48
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Release the store's database connections, so a script using it can exit. Waits
|
|
69
|
+
* for table creation to settle first. A client passed to the constructor is left
|
|
70
|
+
* open unless `ownsClient` was set (end it yourself). Idempotent.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```typescript
|
|
74
|
+
* const users = await createPostgresUserStore({ connectionString })
|
|
75
|
+
* const device = await users.findDevice(nodeId)
|
|
76
|
+
* await users.close()
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
async close(): Promise<void> {
|
|
80
|
+
if (this.closed) return
|
|
81
|
+
this.closed = true
|
|
82
|
+
await this.ready.catch(() => {})
|
|
83
|
+
if (this.ownsClient) await this.sql.end?.({ timeout: 5 })
|
|
84
|
+
}
|
|
85
|
+
|
|
49
86
|
/** Token revocations stored in the same Postgres database as the users. */
|
|
50
87
|
getTokenRevocationStore(): TokenRevocationStore {
|
|
51
88
|
if (!this.revocationStore) {
|
|
@@ -262,7 +299,7 @@ export async function createPostgresUserStore(options: {
|
|
|
262
299
|
}): Promise<PostgresUserStore> {
|
|
263
300
|
const postgresClient = await loadPostgresDeps()
|
|
264
301
|
const sql = postgresClient(options.connectionString) as unknown as PostgresClient
|
|
265
|
-
return new PostgresUserStore(sql)
|
|
302
|
+
return new PostgresUserStore(sql, { ownsClient: true })
|
|
266
303
|
}
|
|
267
304
|
|
|
268
305
|
async function loadPostgresDeps(): Promise<(connectionString: string) => unknown> {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto'
|
|
2
|
+
import { mkdirSync } from 'node:fs'
|
|
3
|
+
import { dirname } from 'node:path'
|
|
2
4
|
import {
|
|
3
5
|
type SqliteRevocationDatabase,
|
|
4
6
|
SqliteTokenRevocationStore,
|
|
@@ -278,6 +280,7 @@ export async function createSqliteUserStore(options: {
|
|
|
278
280
|
filename: string
|
|
279
281
|
}): Promise<SqliteUserStore> {
|
|
280
282
|
const Database = await loadBetterSqlite3()
|
|
283
|
+
ensureDatabaseDirectory(options.filename)
|
|
281
284
|
const db = new Database(options.filename)
|
|
282
285
|
return new SqliteUserStore(db as unknown as SqliteDatabase)
|
|
283
286
|
}
|
|
@@ -320,3 +323,13 @@ function rowToDevice(row: DeviceRow): AuthDevice {
|
|
|
320
323
|
lastSeenAt: row.last_seen_at,
|
|
321
324
|
}
|
|
322
325
|
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Create the directory a SQLite database file lives in, so a default such as
|
|
329
|
+
* `./.kora/kora-server.db` works on a fresh checkout. In-memory databases and `file:`
|
|
330
|
+
* URIs are left alone.
|
|
331
|
+
*/
|
|
332
|
+
function ensureDatabaseDirectory(filename: string): void {
|
|
333
|
+
if (filename === '' || filename === ':memory:' || filename.startsWith('file:')) return
|
|
334
|
+
mkdirSync(dirname(filename), { recursive: true })
|
|
335
|
+
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto'
|
|
2
|
+
import { mkdirSync } from 'node:fs'
|
|
3
|
+
import { dirname } from 'node:path'
|
|
2
4
|
import { DuplicateLinkedIdentityError, type LinkedIdentityStore } from './linked-identity-store'
|
|
3
5
|
import type { LinkedIdentity, OAuthState, OAuthStateStore } from './oauth-types'
|
|
4
6
|
|
|
@@ -219,6 +221,7 @@ export async function createSqliteOAuthStores(options: { filename: string }): Pr
|
|
|
219
221
|
linkedIdentityStore: SqliteLinkedIdentityStore
|
|
220
222
|
}> {
|
|
221
223
|
const Database = await loadBetterSqlite3()
|
|
224
|
+
ensureDatabaseDirectory(options.filename)
|
|
222
225
|
const db = new Database(options.filename) as unknown as SqliteDatabase
|
|
223
226
|
return {
|
|
224
227
|
stateStore: new SqliteOAuthStateStore(db),
|
|
@@ -270,3 +273,13 @@ function rowToLinkedIdentity(row: LinkedIdentityRow): LinkedIdentity {
|
|
|
270
273
|
linkedAt: row.linked_at,
|
|
271
274
|
}
|
|
272
275
|
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Create the directory a SQLite database file lives in, so a default such as
|
|
279
|
+
* `./.kora/kora-server.db` works on a fresh checkout. In-memory databases and `file:`
|
|
280
|
+
* URIs are left alone.
|
|
281
|
+
*/
|
|
282
|
+
function ensureDatabaseDirectory(filename: string): void {
|
|
283
|
+
if (filename === '' || filename === ':memory:' || filename.startsWith('file:')) return
|
|
284
|
+
mkdirSync(dirname(filename), { recursive: true })
|
|
285
|
+
}
|
package/src/server.ts
CHANGED
|
@@ -103,7 +103,11 @@ export type { UserStore, AuthUser, StoredUser, AuthDevice } from './provider/bui
|
|
|
103
103
|
export { SqliteUserStore, createSqliteUserStore } from './provider/built-in/sqlite-user-store'
|
|
104
104
|
|
|
105
105
|
// === PostgreSQL User Store ===
|
|
106
|
-
export {
|
|
106
|
+
export {
|
|
107
|
+
PostgresUserStore,
|
|
108
|
+
type PostgresUserStoreOptions,
|
|
109
|
+
createPostgresUserStore,
|
|
110
|
+
} from './provider/built-in/postgres-user-store'
|
|
107
111
|
|
|
108
112
|
// === Provider Adapter ===
|
|
109
113
|
export { BuiltInProvider, AuthProviderError } from './provider/adapter'
|