feat(04-02): implement listEmitter + listAccess; all 9 tests GREEN

listEmitter.ts:
- Module-level EventEmitter singleton; setMaxListeners(200) (T-04-04)
- publishListEvent(listId, event): emits on list:${listId} channel
- subscribeListEvents(listId, handler): registers listener, returns unsub closure
- ListEvent type union: item:added/updated/deleted, list:updated/deleted
- D-04 isolation guaranteed by per-list channel keying

listAccess.ts:
- getAccessibleListIds(userId): two SELECT queries (owned + shared), Set dedupe
- Satisfies T-04-02/T-04-03: over-returning proven impossible by Test 7

listAccess.test.ts fix:
- Use randomUUID() suffix in seedUser to avoid oidc_sub unique-key collisions
  across test re-runs (users table not truncated by global afterEach)

vitest.config.ts:
- pool: 'forks' + singleFork: true to prevent FK violations from concurrent
  DB workers racing against the shared-state global afterEach cleanup
- sequence.concurrent: false as belt-and-suspenders

ioredis NOT introduced (D-18 abstraction boundary satisfied)
This commit is contained in:
Lucas Berger
2026-06-09 12:20:38 -04:00
parent 2d250afce2
commit 792efeb3df
4 changed files with 116 additions and 4 deletions
+12
View File
@@ -5,5 +5,17 @@ export default defineConfig({
environment: 'node',
globals: true,
setupFiles: ['./test/setup.ts'],
// Run test files sequentially so concurrent DB tests do not interfere via
// the shared MariaDB (global afterEach in test/setup.ts truncates list tables
// which causes FK violations if two workers share the DB concurrently).
sequence: {
concurrent: false,
},
pool: 'forks',
// singleFork: top-level in vitest 4.x (poolOptions removed in v4).
// Runs all test files in one forked process so the shared MariaDB
// teardown (afterEach in test/setup.ts) never races with inserts
// from a concurrent worker.
singleFork: true,
},
})