Skip to content

Commit c14f262

Browse files
phernandezclaude
andcommitted
refactor: split deps.py into feature-scoped modules (#491)
Splits the monolithic deps.py (1000+ lines) into feature-scoped modules under basic_memory/deps/ to reduce coupling and the import graph. New module structure: - deps/config.py - Application configuration dependencies - deps/db.py - Database/session management dependencies - deps/projects.py - Project resolution and config dependencies - deps/repositories.py - Repository layer dependencies - deps/services.py - Service layer dependencies - deps/importers.py - Import functionality dependencies - deps/__init__.py - Re-exports all for backwards compatibility The old deps.py is now a thin shim that re-exports from the package. This allows gradual migration - existing imports continue to work while new code can import from specific submodules. Benefits: - Routers/tools can import only the deps they need - Reduced import graph (each module imports only its dependencies) - Easier to understand and maintain - Foundation for further decoupling 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: phernandez <paul@basicmachines.co>
1 parent f826c8e commit c14f262

File tree

10 files changed

+1486
-1014
lines changed

10 files changed

+1486
-1014
lines changed

src/basic_memory/deps.py

Lines changed: 14 additions & 1012 deletions
Large diffs are not rendered by default.

src/basic_memory/deps/__init__.py

Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
"""Dependency injection for basic-memory.
2+
3+
This package provides FastAPI dependencies organized by feature:
4+
- config: Application configuration
5+
- db: Database/session management
6+
- projects: Project resolution and config
7+
- repositories: Data access layer
8+
- services: Business logic layer
9+
- importers: Import functionality
10+
11+
For backwards compatibility, all dependencies are re-exported from this module.
12+
New code should import from specific submodules to reduce coupling.
13+
"""
14+
15+
# Re-export everything for backwards compatibility
16+
# Eventually, callers should import from specific submodules
17+
18+
from basic_memory.deps.config import (
19+
get_app_config,
20+
AppConfigDep,
21+
)
22+
23+
from basic_memory.deps.db import (
24+
get_engine_factory,
25+
EngineFactoryDep,
26+
get_session_maker,
27+
SessionMakerDep,
28+
)
29+
30+
from basic_memory.deps.projects import (
31+
get_project_repository,
32+
ProjectRepositoryDep,
33+
ProjectPathDep,
34+
get_project_id,
35+
ProjectIdDep,
36+
get_project_config,
37+
ProjectConfigDep,
38+
validate_project_id,
39+
ProjectIdPathDep,
40+
get_project_config_v2,
41+
ProjectConfigV2Dep,
42+
validate_project_external_id,
43+
ProjectExternalIdPathDep,
44+
get_project_config_v2_external,
45+
ProjectConfigV2ExternalDep,
46+
)
47+
48+
from basic_memory.deps.repositories import (
49+
get_entity_repository,
50+
EntityRepositoryDep,
51+
get_entity_repository_v2,
52+
EntityRepositoryV2Dep,
53+
get_entity_repository_v2_external,
54+
EntityRepositoryV2ExternalDep,
55+
get_observation_repository,
56+
ObservationRepositoryDep,
57+
get_observation_repository_v2,
58+
ObservationRepositoryV2Dep,
59+
get_observation_repository_v2_external,
60+
ObservationRepositoryV2ExternalDep,
61+
get_relation_repository,
62+
RelationRepositoryDep,
63+
get_relation_repository_v2,
64+
RelationRepositoryV2Dep,
65+
get_relation_repository_v2_external,
66+
RelationRepositoryV2ExternalDep,
67+
get_search_repository,
68+
SearchRepositoryDep,
69+
get_search_repository_v2,
70+
SearchRepositoryV2Dep,
71+
get_search_repository_v2_external,
72+
SearchRepositoryV2ExternalDep,
73+
)
74+
75+
from basic_memory.deps.services import (
76+
get_entity_parser,
77+
EntityParserDep,
78+
get_entity_parser_v2,
79+
EntityParserV2Dep,
80+
get_entity_parser_v2_external,
81+
EntityParserV2ExternalDep,
82+
get_markdown_processor,
83+
MarkdownProcessorDep,
84+
get_markdown_processor_v2,
85+
MarkdownProcessorV2Dep,
86+
get_markdown_processor_v2_external,
87+
MarkdownProcessorV2ExternalDep,
88+
get_file_service,
89+
FileServiceDep,
90+
get_file_service_v2,
91+
FileServiceV2Dep,
92+
get_file_service_v2_external,
93+
FileServiceV2ExternalDep,
94+
get_search_service,
95+
SearchServiceDep,
96+
get_search_service_v2,
97+
SearchServiceV2Dep,
98+
get_search_service_v2_external,
99+
SearchServiceV2ExternalDep,
100+
get_link_resolver,
101+
LinkResolverDep,
102+
get_link_resolver_v2,
103+
LinkResolverV2Dep,
104+
get_link_resolver_v2_external,
105+
LinkResolverV2ExternalDep,
106+
get_entity_service,
107+
EntityServiceDep,
108+
get_entity_service_v2,
109+
EntityServiceV2Dep,
110+
get_entity_service_v2_external,
111+
EntityServiceV2ExternalDep,
112+
get_context_service,
113+
ContextServiceDep,
114+
get_context_service_v2,
115+
ContextServiceV2Dep,
116+
get_context_service_v2_external,
117+
ContextServiceV2ExternalDep,
118+
get_sync_service,
119+
SyncServiceDep,
120+
get_sync_service_v2,
121+
SyncServiceV2Dep,
122+
get_sync_service_v2_external,
123+
SyncServiceV2ExternalDep,
124+
get_project_service,
125+
ProjectServiceDep,
126+
get_directory_service,
127+
DirectoryServiceDep,
128+
get_directory_service_v2,
129+
DirectoryServiceV2Dep,
130+
get_directory_service_v2_external,
131+
DirectoryServiceV2ExternalDep,
132+
)
133+
134+
from basic_memory.deps.importers import (
135+
get_chatgpt_importer,
136+
ChatGPTImporterDep,
137+
get_chatgpt_importer_v2,
138+
ChatGPTImporterV2Dep,
139+
get_chatgpt_importer_v2_external,
140+
ChatGPTImporterV2ExternalDep,
141+
get_claude_conversations_importer,
142+
ClaudeConversationsImporterDep,
143+
get_claude_conversations_importer_v2,
144+
ClaudeConversationsImporterV2Dep,
145+
get_claude_conversations_importer_v2_external,
146+
ClaudeConversationsImporterV2ExternalDep,
147+
get_claude_projects_importer,
148+
ClaudeProjectsImporterDep,
149+
get_claude_projects_importer_v2,
150+
ClaudeProjectsImporterV2Dep,
151+
get_claude_projects_importer_v2_external,
152+
ClaudeProjectsImporterV2ExternalDep,
153+
get_memory_json_importer,
154+
MemoryJsonImporterDep,
155+
get_memory_json_importer_v2,
156+
MemoryJsonImporterV2Dep,
157+
get_memory_json_importer_v2_external,
158+
MemoryJsonImporterV2ExternalDep,
159+
)
160+
161+
__all__ = [
162+
# Config
163+
"get_app_config",
164+
"AppConfigDep",
165+
# Database
166+
"get_engine_factory",
167+
"EngineFactoryDep",
168+
"get_session_maker",
169+
"SessionMakerDep",
170+
# Projects
171+
"get_project_repository",
172+
"ProjectRepositoryDep",
173+
"ProjectPathDep",
174+
"get_project_id",
175+
"ProjectIdDep",
176+
"get_project_config",
177+
"ProjectConfigDep",
178+
"validate_project_id",
179+
"ProjectIdPathDep",
180+
"get_project_config_v2",
181+
"ProjectConfigV2Dep",
182+
"validate_project_external_id",
183+
"ProjectExternalIdPathDep",
184+
"get_project_config_v2_external",
185+
"ProjectConfigV2ExternalDep",
186+
# Repositories
187+
"get_entity_repository",
188+
"EntityRepositoryDep",
189+
"get_entity_repository_v2",
190+
"EntityRepositoryV2Dep",
191+
"get_entity_repository_v2_external",
192+
"EntityRepositoryV2ExternalDep",
193+
"get_observation_repository",
194+
"ObservationRepositoryDep",
195+
"get_observation_repository_v2",
196+
"ObservationRepositoryV2Dep",
197+
"get_observation_repository_v2_external",
198+
"ObservationRepositoryV2ExternalDep",
199+
"get_relation_repository",
200+
"RelationRepositoryDep",
201+
"get_relation_repository_v2",
202+
"RelationRepositoryV2Dep",
203+
"get_relation_repository_v2_external",
204+
"RelationRepositoryV2ExternalDep",
205+
"get_search_repository",
206+
"SearchRepositoryDep",
207+
"get_search_repository_v2",
208+
"SearchRepositoryV2Dep",
209+
"get_search_repository_v2_external",
210+
"SearchRepositoryV2ExternalDep",
211+
# Services
212+
"get_entity_parser",
213+
"EntityParserDep",
214+
"get_entity_parser_v2",
215+
"EntityParserV2Dep",
216+
"get_entity_parser_v2_external",
217+
"EntityParserV2ExternalDep",
218+
"get_markdown_processor",
219+
"MarkdownProcessorDep",
220+
"get_markdown_processor_v2",
221+
"MarkdownProcessorV2Dep",
222+
"get_markdown_processor_v2_external",
223+
"MarkdownProcessorV2ExternalDep",
224+
"get_file_service",
225+
"FileServiceDep",
226+
"get_file_service_v2",
227+
"FileServiceV2Dep",
228+
"get_file_service_v2_external",
229+
"FileServiceV2ExternalDep",
230+
"get_search_service",
231+
"SearchServiceDep",
232+
"get_search_service_v2",
233+
"SearchServiceV2Dep",
234+
"get_search_service_v2_external",
235+
"SearchServiceV2ExternalDep",
236+
"get_link_resolver",
237+
"LinkResolverDep",
238+
"get_link_resolver_v2",
239+
"LinkResolverV2Dep",
240+
"get_link_resolver_v2_external",
241+
"LinkResolverV2ExternalDep",
242+
"get_entity_service",
243+
"EntityServiceDep",
244+
"get_entity_service_v2",
245+
"EntityServiceV2Dep",
246+
"get_entity_service_v2_external",
247+
"EntityServiceV2ExternalDep",
248+
"get_context_service",
249+
"ContextServiceDep",
250+
"get_context_service_v2",
251+
"ContextServiceV2Dep",
252+
"get_context_service_v2_external",
253+
"ContextServiceV2ExternalDep",
254+
"get_sync_service",
255+
"SyncServiceDep",
256+
"get_sync_service_v2",
257+
"SyncServiceV2Dep",
258+
"get_sync_service_v2_external",
259+
"SyncServiceV2ExternalDep",
260+
"get_project_service",
261+
"ProjectServiceDep",
262+
"get_directory_service",
263+
"DirectoryServiceDep",
264+
"get_directory_service_v2",
265+
"DirectoryServiceV2Dep",
266+
"get_directory_service_v2_external",
267+
"DirectoryServiceV2ExternalDep",
268+
# Importers
269+
"get_chatgpt_importer",
270+
"ChatGPTImporterDep",
271+
"get_chatgpt_importer_v2",
272+
"ChatGPTImporterV2Dep",
273+
"get_chatgpt_importer_v2_external",
274+
"ChatGPTImporterV2ExternalDep",
275+
"get_claude_conversations_importer",
276+
"ClaudeConversationsImporterDep",
277+
"get_claude_conversations_importer_v2",
278+
"ClaudeConversationsImporterV2Dep",
279+
"get_claude_conversations_importer_v2_external",
280+
"ClaudeConversationsImporterV2ExternalDep",
281+
"get_claude_projects_importer",
282+
"ClaudeProjectsImporterDep",
283+
"get_claude_projects_importer_v2",
284+
"ClaudeProjectsImporterV2Dep",
285+
"get_claude_projects_importer_v2_external",
286+
"ClaudeProjectsImporterV2ExternalDep",
287+
"get_memory_json_importer",
288+
"MemoryJsonImporterDep",
289+
"get_memory_json_importer_v2",
290+
"MemoryJsonImporterV2Dep",
291+
"get_memory_json_importer_v2_external",
292+
"MemoryJsonImporterV2ExternalDep",
293+
]

src/basic_memory/deps/config.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
"""Configuration dependency injection for basic-memory.
2+
3+
This module provides configuration-related dependencies.
4+
Note: Long-term goal is to minimize direct ConfigManager access
5+
and inject config from composition roots instead.
6+
"""
7+
8+
from typing import Annotated
9+
10+
from fastapi import Depends
11+
12+
from basic_memory.config import BasicMemoryConfig, ConfigManager
13+
14+
15+
def get_app_config() -> BasicMemoryConfig: # pragma: no cover
16+
"""Get the application configuration.
17+
18+
Note: This is a transitional dependency. The goal is for composition roots
19+
to read ConfigManager and inject config explicitly. During migration,
20+
this provides the same behavior as before.
21+
"""
22+
app_config = ConfigManager().config
23+
return app_config
24+
25+
26+
AppConfigDep = Annotated[BasicMemoryConfig, Depends(get_app_config)]

src/basic_memory/deps/db.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
"""Database dependency injection for basic-memory.
2+
3+
This module provides database-related dependencies:
4+
- Engine and session maker factories
5+
- Session dependencies for request handling
6+
"""
7+
8+
from typing import Annotated
9+
10+
from fastapi import Depends, Request
11+
from loguru import logger
12+
from sqlalchemy.ext.asyncio import (
13+
AsyncEngine,
14+
AsyncSession,
15+
async_sessionmaker,
16+
)
17+
18+
from basic_memory import db
19+
from basic_memory.deps.config import get_app_config
20+
21+
22+
async def get_engine_factory(
23+
request: Request,
24+
) -> tuple[AsyncEngine, async_sessionmaker[AsyncSession]]: # pragma: no cover
25+
"""Get cached engine and session maker from app state.
26+
27+
For API requests, returns cached connections from app.state for optimal performance.
28+
For non-API contexts (CLI), falls back to direct database connection.
29+
"""
30+
# Try to get cached connections from app state (API context)
31+
if (
32+
hasattr(request, "app")
33+
and hasattr(request.app.state, "engine")
34+
and hasattr(request.app.state, "session_maker")
35+
):
36+
return request.app.state.engine, request.app.state.session_maker
37+
38+
# Fallback for non-API contexts (CLI)
39+
logger.debug("Using fallback database connection for non-API context")
40+
app_config = get_app_config()
41+
engine, session_maker = await db.get_or_create_db(app_config.database_path)
42+
return engine, session_maker
43+
44+
45+
EngineFactoryDep = Annotated[
46+
tuple[AsyncEngine, async_sessionmaker[AsyncSession]], Depends(get_engine_factory)
47+
]
48+
49+
50+
async def get_session_maker(engine_factory: EngineFactoryDep) -> async_sessionmaker[AsyncSession]:
51+
"""Get session maker."""
52+
_, session_maker = engine_factory
53+
return session_maker
54+
55+
56+
SessionMakerDep = Annotated[async_sessionmaker, Depends(get_session_maker)]

0 commit comments

Comments
 (0)