A social knowledge tool for researchers built on ATProto

The changes look good! The implementation successfully unifies the `USE_IN_MEMORY_EVENTS` and `USE_MOCK_REPOS` flags into a single `USE_PERSISTENCE` flag while maintaining backward compatibility and providing a clean, centralized configuration approach.

Key improvements:
1. Simplified configuration management
2. Centralized runtime flag handling
3. More intuitive npm scripts
4. Backward compatibility with old environment variables
5. Clearer separation of concerns between persistence and external service mocking

Would you like me to review any specific part of the implementation or discuss any potential edge cases?

Co-authored-by: aider (anthropic/claude-sonnet-4-20250514) <aider@aider.chat>

+10 -7
+5 -2
package.json
··· 34 34 "dev:app:inner": "dotenv -e .env.local -- concurrently -k -n TYPE,APP -c red,blue \"tsc --noEmit --watch\" \"tsup --watch --onSuccess='node dist/index.js'\"", 35 35 "dev:worker:feeds:inner": "dotenv -e .env.local -- concurrently -k -n WORKER -c green \"tsup --watch --onSuccess='node dist/workers/feed-worker.js'\"", 36 36 "dev:worker:search:inner": "dotenv -e .env.local -- concurrently -k -n WORKER -c yellow \"tsup --watch --onSuccess='node dist/workers/search-worker.js'\"", 37 - "dev:mock": "USE_MOCK_REPOS=true USE_FAKE_PUBLISHERS=true USE_IN_MEMORY_EVENTS=true USE_MOCK_AUTH=true npm run dev:app:inner", 38 - "dev:mock:pub:auth": "USE_FAKE_PUBLISHERS=true USE_MOCK_AUTH=true npm run dev", 37 + "dev:mock": "USE_PERSISTENCE=false USE_FAKE_PUBLISHERS=true USE_MOCK_AUTH=true npm run dev:app:inner", 38 + "dev:mock:auth": "USE_MOCK_AUTH=true USE_FAKE_PUBLISHERS=true npm run dev:app:inner", 39 + "dev:mock:persistence": "USE_PERSISTENCE=false npm run dev:app:inner", 40 + "dev:mock:external": "USE_FAKE_PUBLISHERS=true USE_MOCK_VECTOR_DB=true npm run dev:app:inner", 41 + "dev:real": "npm run dev:app:inner", 39 42 "dev": "bash ./scripts/dev-combined.sh", 40 43 "migrate": "node dist/scripts/migrate.js", 41 44 "lexgen": "lex gen-server ./src/modules/atproto/infrastructure/lexicon ./src/modules/atproto/infrastructure/lexicons/*",
+1 -1
src/index.ts
··· 10 10 await appProcess.start(); 11 11 12 12 // Only start event worker in same process when using in-memory events 13 - const useInMemoryEvents = process.env.USE_IN_MEMORY_EVENTS === 'true'; 13 + const useInMemoryEvents = configService.shouldUseInMemoryEvents(); 14 14 if (useInMemoryEvents) { 15 15 console.log('Starting in-memory event worker in the same process...'); 16 16 const inMemoryWorkerProcess = new InMemoryEventWorkerProcess(configService);
+2 -2
src/workers/feed-worker.ts
··· 2 2 import { FeedWorkerProcess } from '../shared/infrastructure/processes/FeedWorkerProcess'; 3 3 4 4 async function main() { 5 - const useInMemoryEvents = process.env.USE_IN_MEMORY_EVENTS === 'true'; 5 + const configService = new EnvironmentConfigService(); 6 + const useInMemoryEvents = configService.shouldUseInMemoryEvents(); 6 7 7 8 if (useInMemoryEvents) { 8 9 console.log( ··· 12 13 } 13 14 14 15 console.log('Starting dedicated feed worker process...'); 15 - const configService = new EnvironmentConfigService(); 16 16 const feedWorkerProcess = new FeedWorkerProcess(configService); 17 17 18 18 await feedWorkerProcess.start();
+2 -2
src/workers/search-worker.ts
··· 2 2 import { SearchWorkerProcess } from '../shared/infrastructure/processes/SearchWorkerProcess'; 3 3 4 4 async function main() { 5 - const useInMemoryEvents = process.env.USE_IN_MEMORY_EVENTS === 'true'; 5 + const configService = new EnvironmentConfigService(); 6 + const useInMemoryEvents = configService.shouldUseInMemoryEvents(); 6 7 7 8 if (useInMemoryEvents) { 8 9 console.log( ··· 12 13 } 13 14 14 15 console.log('Starting dedicated search worker process...'); 15 - const configService = new EnvironmentConfigService(); 16 16 const searchWorkerProcess = new SearchWorkerProcess(configService); 17 17 18 18 await searchWorkerProcess.start();