Skip to content

Commit 1babae7

Browse files
committed
feat: add Repository abstraction with InMemoryRepository for testing pyramid (3.13)
Introduce a Repository base class, InMemoryRepository (Maps-backed, no SQLite), and SqliteRepository (delegates to existing fn(db,...) functions). Includes fluent TestRepoBuilder fixture factory and 105 new tests (51 unit + 54 parity) verifying behavioral equivalence between both implementations. Existing code and tests remain unchanged. Impact: 139 functions changed, 6 affected
1 parent f1ed6b3 commit 1babae7

8 files changed

Lines changed: 1940 additions & 1 deletion

File tree

src/db.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,12 @@ export {
5252
hasCoChanges,
5353
hasDataflowTable,
5454
hasEmbeddings,
55+
InMemoryRepository,
5556
iterateFunctionNodes,
5657
listFunctionNodes,
5758
purgeFileData,
5859
purgeFilesData,
60+
Repository,
61+
SqliteRepository,
5962
upsertCoChangeMeta,
6063
} from './db/repository/index.js';

src/db/repository/base.js

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
/**
2+
* Abstract Repository base class.
3+
*
4+
* Defines the contract for all graph data access. Every method throws
5+
* "not implemented" by default — concrete subclasses override what they support.
6+
*/
7+
export class Repository {
8+
// ── Node lookups ────────────────────────────────────────────────────
9+
/** @param {number} id @returns {object|undefined} */
10+
findNodeById(_id) {
11+
throw new Error('not implemented');
12+
}
13+
14+
/** @param {string} file @returns {object[]} */
15+
findNodesByFile(_file) {
16+
throw new Error('not implemented');
17+
}
18+
19+
/** @param {string} fileLike @returns {object[]} */
20+
findFileNodes(_fileLike) {
21+
throw new Error('not implemented');
22+
}
23+
24+
/** @param {string} namePattern @param {object} [opts] @returns {object[]} */
25+
findNodesWithFanIn(_namePattern, _opts) {
26+
throw new Error('not implemented');
27+
}
28+
29+
/** @returns {number} */
30+
countNodes() {
31+
throw new Error('not implemented');
32+
}
33+
34+
/** @returns {number} */
35+
countEdges() {
36+
throw new Error('not implemented');
37+
}
38+
39+
/** @returns {number} */
40+
countFiles() {
41+
throw new Error('not implemented');
42+
}
43+
44+
/** @param {string} name @param {string} kind @param {string} file @param {number} line @returns {number|undefined} */
45+
getNodeId(_name, _kind, _file, _line) {
46+
throw new Error('not implemented');
47+
}
48+
49+
/** @param {string} name @param {string} file @param {number} line @returns {number|undefined} */
50+
getFunctionNodeId(_name, _file, _line) {
51+
throw new Error('not implemented');
52+
}
53+
54+
/** @param {string} file @returns {{ id: number, name: string, kind: string, line: number }[]} */
55+
bulkNodeIdsByFile(_file) {
56+
throw new Error('not implemented');
57+
}
58+
59+
/** @param {number} parentId @returns {object[]} */
60+
findNodeChildren(_parentId) {
61+
throw new Error('not implemented');
62+
}
63+
64+
/** @param {string} scopeName @param {object} [opts] @returns {object[]} */
65+
findNodesByScope(_scopeName, _opts) {
66+
throw new Error('not implemented');
67+
}
68+
69+
/** @param {string} qualifiedName @param {object} [opts] @returns {object[]} */
70+
findNodeByQualifiedName(_qualifiedName, _opts) {
71+
throw new Error('not implemented');
72+
}
73+
74+
/** @param {object} [opts] @returns {object[]} */
75+
listFunctionNodes(_opts) {
76+
throw new Error('not implemented');
77+
}
78+
79+
/** @param {object} [opts] @returns {IterableIterator} */
80+
iterateFunctionNodes(_opts) {
81+
throw new Error('not implemented');
82+
}
83+
84+
/** @param {object} [opts] @returns {object[]} */
85+
findNodesForTriage(_opts) {
86+
throw new Error('not implemented');
87+
}
88+
89+
// ── Edge queries ────────────────────────────────────────────────────
90+
/** @param {number} nodeId @returns {object[]} */
91+
findCallees(_nodeId) {
92+
throw new Error('not implemented');
93+
}
94+
95+
/** @param {number} nodeId @returns {object[]} */
96+
findCallers(_nodeId) {
97+
throw new Error('not implemented');
98+
}
99+
100+
/** @param {number} nodeId @returns {object[]} */
101+
findDistinctCallers(_nodeId) {
102+
throw new Error('not implemented');
103+
}
104+
105+
/** @param {number} nodeId @returns {object[]} */
106+
findAllOutgoingEdges(_nodeId) {
107+
throw new Error('not implemented');
108+
}
109+
110+
/** @param {number} nodeId @returns {object[]} */
111+
findAllIncomingEdges(_nodeId) {
112+
throw new Error('not implemented');
113+
}
114+
115+
/** @param {number} nodeId @returns {string[]} */
116+
findCalleeNames(_nodeId) {
117+
throw new Error('not implemented');
118+
}
119+
120+
/** @param {number} nodeId @returns {string[]} */
121+
findCallerNames(_nodeId) {
122+
throw new Error('not implemented');
123+
}
124+
125+
/** @param {number} nodeId @returns {{ file: string, edge_kind: string }[]} */
126+
findImportTargets(_nodeId) {
127+
throw new Error('not implemented');
128+
}
129+
130+
/** @param {number} nodeId @returns {{ file: string, edge_kind: string }[]} */
131+
findImportSources(_nodeId) {
132+
throw new Error('not implemented');
133+
}
134+
135+
/** @param {number} nodeId @returns {object[]} */
136+
findImportDependents(_nodeId) {
137+
throw new Error('not implemented');
138+
}
139+
140+
/** @param {string} file @returns {Set<number>} */
141+
findCrossFileCallTargets(_file) {
142+
throw new Error('not implemented');
143+
}
144+
145+
/** @param {number} nodeId @param {string} file @returns {number} */
146+
countCrossFileCallers(_nodeId, _file) {
147+
throw new Error('not implemented');
148+
}
149+
150+
/** @param {number} classNodeId @returns {Set<number>} */
151+
getClassHierarchy(_classNodeId) {
152+
throw new Error('not implemented');
153+
}
154+
155+
/** @param {string} file @returns {{ caller_name: string, callee_name: string }[]} */
156+
findIntraFileCallEdges(_file) {
157+
throw new Error('not implemented');
158+
}
159+
160+
// ── Graph-read queries ──────────────────────────────────────────────
161+
/** @returns {{ id: number, name: string, kind: string, file: string }[]} */
162+
getCallableNodes() {
163+
throw new Error('not implemented');
164+
}
165+
166+
/** @returns {{ source_id: number, target_id: number }[]} */
167+
getCallEdges() {
168+
throw new Error('not implemented');
169+
}
170+
171+
/** @returns {{ id: number, name: string, file: string }[]} */
172+
getFileNodesAll() {
173+
throw new Error('not implemented');
174+
}
175+
176+
/** @returns {{ source_id: number, target_id: number }[]} */
177+
getImportEdges() {
178+
throw new Error('not implemented');
179+
}
180+
181+
// ── Optional table checks (default: false/undefined) ────────────────
182+
/** @returns {boolean} */
183+
hasCfgTables() {
184+
throw new Error('not implemented');
185+
}
186+
187+
/** @returns {boolean} */
188+
hasEmbeddings() {
189+
throw new Error('not implemented');
190+
}
191+
192+
/** @returns {boolean} */
193+
hasDataflowTable() {
194+
throw new Error('not implemented');
195+
}
196+
197+
/** @param {number} nodeId @returns {object|undefined} */
198+
getComplexityForNode(_nodeId) {
199+
throw new Error('not implemented');
200+
}
201+
}

0 commit comments

Comments
 (0)