Skip to content

Commit f5ce7b0

Browse files
committed
fix(database): preserve session tag when called before commit
Fixes #95
1 parent 4c6d6dc commit f5ce7b0

File tree

2 files changed

+43
-7
lines changed

2 files changed

+43
-7
lines changed

src/stores/database.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,7 @@ export class DatabaseStore implements SessionStoreWithTaggingContract {
114114
await this.#client
115115
.insertQuery()
116116
.table(this.#tableName)
117-
.insert({
118-
id: sessionId,
119-
data: message,
120-
expires_at: expiresAt,
121-
})
117+
.insert({ id: sessionId, data: message, expires_at: expiresAt })
122118
.knexQuery.onConflict('id')
123119
.merge(['data', 'expires_at'])
124120

@@ -149,12 +145,21 @@ export class DatabaseStore implements SessionStoreWithTaggingContract {
149145
}
150146

151147
/**
152-
* Tag a session with a user ID
148+
* Tag a session with a user ID.
149+
* Uses UPSERT to handle both existing and new sessions.
153150
*/
154151
async tag(sessionId: string, userId: string): Promise<void> {
155152
debug('database store: tagging session %s with user %s', sessionId, userId)
156153

157-
await this.#client.from(this.#tableName).where('id', sessionId).update({ user_id: userId })
154+
const data = new MessageBuilder().build({}, undefined, sessionId)
155+
const expiresAt = new Date(Date.now() + this.#ttlSeconds * 1000)
156+
157+
await this.#client
158+
.insertQuery()
159+
.table(this.#tableName)
160+
.insert({ id: sessionId, user_id: userId, data, expires_at: expiresAt })
161+
.knexQuery.onConflict('id')
162+
.merge(['user_id'])
158163
}
159164

160165
/**

tests/stores/database_store.spec.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,4 +283,35 @@ test.group('Database store', (group) => {
283283
const sessions = await store.tagged('user-1')
284284
assert.deepEqual(sessions, [])
285285
}).disableTimeout()
286+
287+
/**
288+
* Simulate what happens during login lifecycle:
289+
* - Session is new (doesnt exist in DB yet)
290+
* - User calls session.tag => create session in database
291+
* - Then commit() calls write() => update data and preserves the rest
292+
*/
293+
test('tag before write creates session and preserves tag', async ({ assert }) => {
294+
const store = new DatabaseStore(db.connection(), '2 hours')
295+
296+
await store.tag('new-session', 'user-123')
297+
await store.write('new-session', { message: 'hello' })
298+
299+
const row = await db.from('sessions').where('id', 'new-session').first()
300+
assert.equal(row.user_id, 'user-123')
301+
302+
const data = await store.read('new-session')
303+
assert.deepEqual(data, { message: 'hello' })
304+
})
305+
306+
test('tag is preserved after write updates session data', async ({ assert }) => {
307+
const store = new DatabaseStore(db.connection(), '2 hours')
308+
309+
await store.write('session-1', { message: 'hello' })
310+
await store.tag('session-1', 'user-123')
311+
312+
await store.write('session-1', { message: 'updated' })
313+
314+
const row = await db.from('sessions').where('id', 'session-1').first()
315+
assert.equal(row.user_id, 'user-123')
316+
})
286317
})

0 commit comments

Comments
 (0)