sdl-mcp 0.9.2 → 0.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -19,39 +19,39 @@ function toMemoryRow(row) {
19
19
  deleted: toBoolean(row.deleted),
20
20
  };
21
21
  }
22
- const MEMORY_RETURN_FIELDS = `
23
- m.memoryId AS memoryId,
24
- m.repoId AS repoId,
25
- m.type AS type,
26
- m.title AS title,
27
- m.content AS content,
28
- m.contentHash AS contentHash,
29
- m.searchText AS searchText,
30
- m.tagsJson AS tagsJson,
31
- m.confidence AS confidence,
32
- m.createdAt AS createdAt,
33
- m.updatedAt AS updatedAt,
34
- m.createdByVersion AS createdByVersion,
35
- m.stale AS stale,
36
- m.staleVersion AS staleVersion,
37
- m.sourceFile AS sourceFile,
22
+ const MEMORY_RETURN_FIELDS = `
23
+ m.memoryId AS memoryId,
24
+ m.repoId AS repoId,
25
+ m.type AS type,
26
+ m.title AS title,
27
+ m.content AS content,
28
+ m.contentHash AS contentHash,
29
+ m.searchText AS searchText,
30
+ m.tagsJson AS tagsJson,
31
+ m.confidence AS confidence,
32
+ m.createdAt AS createdAt,
33
+ m.updatedAt AS updatedAt,
34
+ m.createdByVersion AS createdByVersion,
35
+ m.stale AS stale,
36
+ m.staleVersion AS staleVersion,
37
+ m.sourceFile AS sourceFile,
38
38
  m.deleted AS deleted`;
39
39
  export async function upsertMemory(conn, row) {
40
- await exec(conn, `MERGE (m:Memory {memoryId: $memoryId})
41
- SET m.repoId = $repoId,
42
- m.type = $type,
43
- m.title = $title,
44
- m.content = $content,
45
- m.contentHash = $contentHash,
46
- m.searchText = $searchText,
47
- m.tagsJson = $tagsJson,
48
- m.confidence = $confidence,
49
- m.createdAt = $createdAt,
50
- m.updatedAt = $updatedAt,
51
- m.createdByVersion = $createdByVersion,
52
- m.stale = $stale,
53
- m.staleVersion = $staleVersion,
54
- m.sourceFile = $sourceFile,
40
+ await exec(conn, `MERGE (m:Memory {memoryId: $memoryId})
41
+ SET m.repoId = $repoId,
42
+ m.type = $type,
43
+ m.title = $title,
44
+ m.content = $content,
45
+ m.contentHash = $contentHash,
46
+ m.searchText = $searchText,
47
+ m.tagsJson = $tagsJson,
48
+ m.confidence = $confidence,
49
+ m.createdAt = $createdAt,
50
+ m.updatedAt = $updatedAt,
51
+ m.createdByVersion = $createdByVersion,
52
+ m.stale = $stale,
53
+ m.staleVersion = $staleVersion,
54
+ m.sourceFile = $sourceFile,
55
55
  m.deleted = $deleted`, {
56
56
  memoryId: row.memoryId,
57
57
  repoId: row.repoId,
@@ -72,13 +72,13 @@ export async function upsertMemory(conn, row) {
72
72
  });
73
73
  }
74
74
  export async function getMemory(conn, memoryId) {
75
- const row = await querySingle(conn, `MATCH (m:Memory {memoryId: $memoryId})
75
+ const row = await querySingle(conn, `MATCH (m:Memory {memoryId: $memoryId})
76
76
  RETURN ${MEMORY_RETURN_FIELDS}`, { memoryId });
77
77
  return row ? toMemoryRow(row) : null;
78
78
  }
79
79
  export async function getMemoryByContentHash(conn, contentHash) {
80
- const row = await querySingle(conn, `MATCH (m:Memory {contentHash: $contentHash})
81
- WHERE m.deleted = false
80
+ const row = await querySingle(conn, `MATCH (m:Memory {contentHash: $contentHash})
81
+ WHERE m.deleted = false
82
82
  RETURN ${MEMORY_RETURN_FIELDS}`, { contentHash });
83
83
  return row ? toMemoryRow(row) : null;
84
84
  }
@@ -88,9 +88,9 @@ export async function queryMemories(conn, options) {
88
88
  const useSymbolFilter = options.symbolIds && options.symbolIds.length > 0;
89
89
  // When filtering by symbolIds, traverse MEMORY_OF edges
90
90
  const matchClause = useSymbolFilter
91
- ? `MATCH (m:Memory)-[:MEMORY_OF]->(s:Symbol)
91
+ ? `MATCH (m:Memory)-[:MEMORY_OF]->(s:Symbol)
92
92
  WHERE s.symbolId IN $symbolIds AND m.repoId = $repoId AND m.deleted = false`
93
- : `MATCH (m:Memory)
93
+ : `MATCH (m:Memory)
94
94
  WHERE m.repoId = $repoId AND m.deleted = false`;
95
95
  const conditions = [];
96
96
  const params = { repoId: options.repoId };
@@ -115,9 +115,9 @@ export async function queryMemories(conn, options) {
115
115
  const orderBy = options.sortBy === "confidence"
116
116
  ? "ORDER BY confidence DESC"
117
117
  : "ORDER BY updatedAt DESC";
118
- const cypher = `${matchClause}
119
- ${whereClause}
120
- RETURN DISTINCT ${MEMORY_RETURN_FIELDS}
118
+ const cypher = `${matchClause}
119
+ ${whereClause}
120
+ RETURN DISTINCT ${MEMORY_RETURN_FIELDS}
121
121
  ${orderBy}`;
122
122
  let rows = await queryAll(conn, cypher, params);
123
123
  // Post-filter tags at application level for exact array-element matching
@@ -135,38 +135,38 @@ export async function queryMemories(conn, options) {
135
135
  return rows.slice(0, safeLimit).map(toMemoryRow);
136
136
  }
137
137
  export async function softDeleteMemory(conn, memoryId) {
138
- await exec(conn, `MATCH (m:Memory {memoryId: $memoryId})
138
+ await exec(conn, `MATCH (m:Memory {memoryId: $memoryId})
139
139
  SET m.deleted = true`, { memoryId });
140
140
  }
141
141
  export async function createHasMemoryEdge(conn, repoId, memoryId) {
142
- await exec(conn, `MATCH (r:Repo {repoId: $repoId}), (m:Memory {memoryId: $memoryId})
142
+ await exec(conn, `MATCH (r:Repo {repoId: $repoId}), (m:Memory {memoryId: $memoryId})
143
143
  MERGE (r)-[:HAS_MEMORY]->(m)`, { repoId, memoryId });
144
144
  }
145
145
  export async function createMemoryOfEdge(conn, memoryId, symbolId) {
146
- await exec(conn, `MATCH (m:Memory {memoryId: $memoryId}), (s:Symbol {symbolId: $symbolId})
146
+ await exec(conn, `MATCH (m:Memory {memoryId: $memoryId}), (s:Symbol {symbolId: $symbolId})
147
147
  MERGE (m)-[:MEMORY_OF]->(s)`, { memoryId, symbolId });
148
148
  }
149
149
  export async function createMemoryOfFileEdge(conn, memoryId, fileId) {
150
- await exec(conn, `MATCH (m:Memory {memoryId: $memoryId}), (f:File {fileId: $fileId})
150
+ await exec(conn, `MATCH (m:Memory {memoryId: $memoryId}), (f:File {fileId: $fileId})
151
151
  MERGE (m)-[:MEMORY_OF_FILE]->(f)`, { memoryId, fileId });
152
152
  }
153
153
  export async function deleteMemoryEdges(conn, memoryId) {
154
154
  // Delete HAS_MEMORY edges (Repo->Memory)
155
- await exec(conn, `MATCH (r:Repo)-[e:HAS_MEMORY]->(m:Memory {memoryId: $memoryId})
155
+ await exec(conn, `MATCH (r:Repo)-[e:HAS_MEMORY]->(m:Memory {memoryId: $memoryId})
156
156
  DELETE e`, { memoryId });
157
157
  // Delete MEMORY_OF edges (Memory->Symbol)
158
- await exec(conn, `MATCH (m:Memory {memoryId: $memoryId})-[e:MEMORY_OF]->(s:Symbol)
158
+ await exec(conn, `MATCH (m:Memory {memoryId: $memoryId})-[e:MEMORY_OF]->(s:Symbol)
159
159
  DELETE e`, { memoryId });
160
160
  // Delete MEMORY_OF_FILE edges (Memory->File)
161
- await exec(conn, `MATCH (m:Memory {memoryId: $memoryId})-[e:MEMORY_OF_FILE]->(f:File)
161
+ await exec(conn, `MATCH (m:Memory {memoryId: $memoryId})-[e:MEMORY_OF_FILE]->(f:File)
162
162
  DELETE e`, { memoryId });
163
163
  }
164
164
  export async function getMemoriesForSymbols(conn, symbolIds, limit) {
165
165
  assertSafeInt(limit, "limit");
166
- const rows = await queryAll(conn, `MATCH (m:Memory)-[:MEMORY_OF]->(s:Symbol)
167
- WHERE s.symbolId IN $symbolIds AND m.deleted = false
168
- RETURN ${MEMORY_RETURN_FIELDS},
169
- s.symbolId AS linkedSymbolId
166
+ const rows = await queryAll(conn, `MATCH (m:Memory)-[:MEMORY_OF]->(s:Symbol)
167
+ WHERE s.symbolId IN $symbolIds AND m.deleted = false
168
+ RETURN ${MEMORY_RETURN_FIELDS},
169
+ s.symbolId AS linkedSymbolId
170
170
  ORDER BY confidence DESC`, { symbolIds });
171
171
  return rows.slice(0, limit).map((row) => ({
172
172
  ...toMemoryRow(row),
@@ -175,18 +175,18 @@ export async function getMemoriesForSymbols(conn, symbolIds, limit) {
175
175
  }
176
176
  export async function getRepoMemories(conn, repoId, limit) {
177
177
  assertSafeInt(limit, "limit");
178
- const rows = await queryAll(conn, `MATCH (r:Repo {repoId: $repoId})-[:HAS_MEMORY]->(m:Memory)
179
- WHERE m.deleted = false
180
- RETURN ${MEMORY_RETURN_FIELDS}
178
+ const rows = await queryAll(conn, `MATCH (r:Repo {repoId: $repoId})-[:HAS_MEMORY]->(m:Memory)
179
+ WHERE m.deleted = false
180
+ RETURN ${MEMORY_RETURN_FIELDS}
181
181
  ORDER BY updatedAt DESC`, { repoId });
182
182
  return rows.slice(0, limit).map(toMemoryRow);
183
183
  }
184
184
  export async function flagMemoriesStale(conn, symbolIds, staleVersion) {
185
185
  if (symbolIds.length === 0)
186
186
  return 0;
187
- const rows = await queryAll(conn, `MATCH (m:Memory)-[:MEMORY_OF]->(s:Symbol)
188
- WHERE s.symbolId IN $symbolIds AND m.deleted = false AND m.stale = false
189
- SET m.stale = true, m.staleVersion = $staleVersion
187
+ const rows = await queryAll(conn, `MATCH (m:Memory)-[:MEMORY_OF]->(s:Symbol)
188
+ WHERE s.symbolId IN $symbolIds AND m.deleted = false AND m.stale = false
189
+ SET m.stale = true, m.staleVersion = $staleVersion
190
190
  RETURN DISTINCT m.memoryId AS memoryId`, { symbolIds, staleVersion });
191
191
  return rows.length;
192
192
  }
@@ -1,11 +1,11 @@
1
1
  import { exec, queryAll, querySingle, toNumber, assertSafeInt, withTransaction, } from "./ladybug-core.js";
2
2
  export async function upsertMetrics(conn, metrics) {
3
- await exec(conn, `MERGE (m:Metrics {symbolId: $symbolId})
4
- SET m.fanIn = $fanIn,
5
- m.fanOut = $fanOut,
6
- m.churn30d = $churn30d,
7
- m.testRefsJson = $testRefsJson,
8
- m.canonicalTestJson = $canonicalTestJson,
3
+ await exec(conn, `MERGE (m:Metrics {symbolId: $symbolId})
4
+ SET m.fanIn = $fanIn,
5
+ m.fanOut = $fanOut,
6
+ m.churn30d = $churn30d,
7
+ m.testRefsJson = $testRefsJson,
8
+ m.canonicalTestJson = $canonicalTestJson,
9
9
  m.updatedAt = $updatedAt`, {
10
10
  symbolId: metrics.symbolId,
11
11
  fanIn: metrics.fanIn,
@@ -25,12 +25,12 @@ export async function upsertMetricsBatch(conn, rows) {
25
25
  return;
26
26
  await withTransaction(conn, async (txConn) => {
27
27
  for (const metrics of rows) {
28
- await exec(txConn, `MERGE (m:Metrics {symbolId: $symbolId})
29
- SET m.fanIn = $fanIn,
30
- m.fanOut = $fanOut,
31
- m.churn30d = $churn30d,
32
- m.testRefsJson = $testRefsJson,
33
- m.canonicalTestJson = $canonicalTestJson,
28
+ await exec(txConn, `MERGE (m:Metrics {symbolId: $symbolId})
29
+ SET m.fanIn = $fanIn,
30
+ m.fanOut = $fanOut,
31
+ m.churn30d = $churn30d,
32
+ m.testRefsJson = $testRefsJson,
33
+ m.canonicalTestJson = $canonicalTestJson,
34
34
  m.updatedAt = $updatedAt`, {
35
35
  symbolId: metrics.symbolId,
36
36
  fanIn: metrics.fanIn,
@@ -53,8 +53,8 @@ export async function upsertCanonicalTestBatch(conn, rows) {
53
53
  return;
54
54
  await withTransaction(conn, async (txConn) => {
55
55
  for (const row of rows) {
56
- await exec(txConn, `MERGE (m:Metrics {symbolId: $symbolId})
57
- SET m.canonicalTestJson = $canonicalTestJson,
56
+ await exec(txConn, `MERGE (m:Metrics {symbolId: $symbolId})
57
+ SET m.canonicalTestJson = $canonicalTestJson,
58
58
  m.updatedAt = $updatedAt`, {
59
59
  symbolId: row.symbolId,
60
60
  canonicalTestJson: row.canonicalTestJson,
@@ -64,13 +64,13 @@ export async function upsertCanonicalTestBatch(conn, rows) {
64
64
  });
65
65
  }
66
66
  export async function getMetrics(conn, symbolId) {
67
- const row = await querySingle(conn, `MATCH (m:Metrics {symbolId: $symbolId})
68
- RETURN m.symbolId AS symbolId,
69
- m.fanIn AS fanIn,
70
- m.fanOut AS fanOut,
71
- m.churn30d AS churn30d,
72
- m.testRefsJson AS testRefsJson,
73
- m.canonicalTestJson AS canonicalTestJson,
67
+ const row = await querySingle(conn, `MATCH (m:Metrics {symbolId: $symbolId})
68
+ RETURN m.symbolId AS symbolId,
69
+ m.fanIn AS fanIn,
70
+ m.fanOut AS fanOut,
71
+ m.churn30d AS churn30d,
72
+ m.testRefsJson AS testRefsJson,
73
+ m.canonicalTestJson AS canonicalTestJson,
74
74
  m.updatedAt AS updatedAt`, { symbolId });
75
75
  if (!row)
76
76
  return null;
@@ -87,14 +87,14 @@ export async function getMetrics(conn, symbolId) {
87
87
  export async function getMetricsBySymbolIds(conn, symbolIds) {
88
88
  if (symbolIds.length === 0)
89
89
  return new Map();
90
- const rows = await queryAll(conn, `MATCH (m:Metrics)
91
- WHERE m.symbolId IN $symbolIds
92
- RETURN m.symbolId AS symbolId,
93
- m.fanIn AS fanIn,
94
- m.fanOut AS fanOut,
95
- m.churn30d AS churn30d,
96
- m.testRefsJson AS testRefsJson,
97
- m.canonicalTestJson AS canonicalTestJson,
90
+ const rows = await queryAll(conn, `MATCH (m:Metrics)
91
+ WHERE m.symbolId IN $symbolIds
92
+ RETURN m.symbolId AS symbolId,
93
+ m.fanIn AS fanIn,
94
+ m.fanOut AS fanOut,
95
+ m.churn30d AS churn30d,
96
+ m.testRefsJson AS testRefsJson,
97
+ m.canonicalTestJson AS canonicalTestJson,
98
98
  m.updatedAt AS updatedAt`, { symbolIds });
99
99
  const result = new Map();
100
100
  for (const row of rows) {
@@ -114,13 +114,13 @@ export async function getTopSymbolsByFanIn(conn, repoId, limit = 10) {
114
114
  assertSafeInt(limit, "limit");
115
115
  limit = Math.max(0, Math.min(limit, 1000));
116
116
  const maxFetch = Math.min(limit, 10000);
117
- const rows = await queryAll(conn, `MATCH (r:Repo {repoId: $repoId})<-[:SYMBOL_IN_REPO]-(s:Symbol)
118
- MATCH (m:Metrics {symbolId: s.symbolId})
119
- RETURN s.symbolId AS symbolId,
120
- m.fanIn AS fanIn,
121
- m.fanOut AS fanOut,
122
- m.churn30d AS churn30d
123
- ORDER BY m.fanIn DESC
117
+ const rows = await queryAll(conn, `MATCH (r:Repo {repoId: $repoId})<-[:SYMBOL_IN_REPO]-(s:Symbol)
118
+ MATCH (m:Metrics {symbolId: s.symbolId})
119
+ RETURN s.symbolId AS symbolId,
120
+ m.fanIn AS fanIn,
121
+ m.fanOut AS fanOut,
122
+ m.churn30d AS churn30d
123
+ ORDER BY m.fanIn DESC
124
124
  LIMIT $limit`, { repoId, limit: maxFetch });
125
125
  return rows.map((row) => ({
126
126
  symbolId: row.symbolId,
@@ -130,14 +130,14 @@ export async function getTopSymbolsByFanIn(conn, repoId, limit = 10) {
130
130
  }));
131
131
  }
132
132
  export async function getMetricsByRepo(conn, repoId) {
133
- const rows = await queryAll(conn, `MATCH (r:Repo {repoId: $repoId})<-[:SYMBOL_IN_REPO]-(s:Symbol)
134
- MATCH (m:Metrics {symbolId: s.symbolId})
135
- RETURN m.symbolId AS symbolId,
136
- m.fanIn AS fanIn,
137
- m.fanOut AS fanOut,
138
- m.churn30d AS churn30d,
139
- m.testRefsJson AS testRefsJson,
140
- m.canonicalTestJson AS canonicalTestJson,
133
+ const rows = await queryAll(conn, `MATCH (r:Repo {repoId: $repoId})<-[:SYMBOL_IN_REPO]-(s:Symbol)
134
+ MATCH (m:Metrics {symbolId: s.symbolId})
135
+ RETURN m.symbolId AS symbolId,
136
+ m.fanIn AS fanIn,
137
+ m.fanOut AS fanOut,
138
+ m.churn30d AS churn30d,
139
+ m.testRefsJson AS testRefsJson,
140
+ m.canonicalTestJson AS canonicalTestJson,
141
141
  m.updatedAt AS updatedAt`, { repoId });
142
142
  const result = new Map();
143
143
  for (const row of rows) {
@@ -157,13 +157,13 @@ export async function getTopSymbolsByChurn(conn, repoId, limit = 10) {
157
157
  assertSafeInt(limit, "limit");
158
158
  limit = Math.max(0, Math.min(limit, 1000));
159
159
  const maxFetch = Math.min(limit, 10000);
160
- const rows = await queryAll(conn, `MATCH (r:Repo {repoId: $repoId})<-[:SYMBOL_IN_REPO]-(s:Symbol)
161
- MATCH (m:Metrics {symbolId: s.symbolId})
162
- RETURN s.symbolId AS symbolId,
163
- m.fanIn AS fanIn,
164
- m.fanOut AS fanOut,
165
- m.churn30d AS churn30d
166
- ORDER BY m.churn30d DESC
160
+ const rows = await queryAll(conn, `MATCH (r:Repo {repoId: $repoId})<-[:SYMBOL_IN_REPO]-(s:Symbol)
161
+ MATCH (m:Metrics {symbolId: s.symbolId})
162
+ RETURN s.symbolId AS symbolId,
163
+ m.fanIn AS fanIn,
164
+ m.fanOut AS fanOut,
165
+ m.churn30d AS churn30d
166
+ ORDER BY m.churn30d DESC
167
167
  LIMIT $limit`, { repoId, limit: maxFetch });
168
168
  return rows.map((row) => ({
169
169
  symbolId: row.symbolId,
@@ -173,10 +173,10 @@ export async function getTopSymbolsByChurn(conn, repoId, limit = 10) {
173
173
  }));
174
174
  }
175
175
  export async function computeFanInOut(conn, symbolId) {
176
- const row = await querySingle(conn, `MATCH (s:Symbol {symbolId: $symbolId})
177
- OPTIONAL MATCH (s)<-[i:DEPENDS_ON]-(:Symbol)
178
- WITH s, count(i) AS fanIn
179
- OPTIONAL MATCH (s)-[o:DEPENDS_ON]->(:Symbol)
176
+ const row = await querySingle(conn, `MATCH (s:Symbol {symbolId: $symbolId})
177
+ OPTIONAL MATCH (s)<-[i:DEPENDS_ON]-(:Symbol)
178
+ WITH s, count(i) AS fanIn
179
+ OPTIONAL MATCH (s)-[o:DEPENDS_ON]->(:Symbol)
180
180
  RETURN fanIn AS fanIn, count(o) AS fanOut`, { symbolId });
181
181
  if (!row)
182
182
  return { fanIn: 0, fanOut: 0 };
@@ -195,18 +195,18 @@ export async function batchComputeFanInOut(conn, symbolIds) {
195
195
  // NOTE: Ladybug can produce incorrect counts for large UNWIND lists, especially
196
196
  // when the input list contains many missing symbols. Prefer WHERE ... IN and
197
197
  // fill missing IDs in JS.
198
- const fanInRows = await queryAll(conn, `MATCH (s:Symbol)
199
- WHERE s.symbolId IN $symbolIds
200
- OPTIONAL MATCH (s)<-[i:DEPENDS_ON]-(:Symbol)
198
+ const fanInRows = await queryAll(conn, `MATCH (s:Symbol)
199
+ WHERE s.symbolId IN $symbolIds
200
+ OPTIONAL MATCH (s)<-[i:DEPENDS_ON]-(:Symbol)
201
201
  RETURN s.symbolId AS symbolId, count(i) AS fanIn`, { symbolIds });
202
202
  for (const row of fanInRows) {
203
203
  const entry = result.get(row.symbolId);
204
204
  if (entry)
205
205
  entry.fanIn = toNumber(row.fanIn);
206
206
  }
207
- const fanOutRows = await queryAll(conn, `MATCH (s:Symbol)
208
- WHERE s.symbolId IN $symbolIds
209
- OPTIONAL MATCH (s)-[o:DEPENDS_ON]->(:Symbol)
207
+ const fanOutRows = await queryAll(conn, `MATCH (s:Symbol)
208
+ WHERE s.symbolId IN $symbolIds
209
+ OPTIONAL MATCH (s)-[o:DEPENDS_ON]->(:Symbol)
210
210
  RETURN s.symbolId AS symbolId, count(o) AS fanOut`, { symbolIds });
211
211
  for (const row of fanOutRows) {
212
212
  const entry = result.get(row.symbolId);
@@ -1,13 +1,13 @@
1
1
  import { exec, queryAll, querySingle, toNumber, withTransaction, } from "./ladybug-core.js";
2
2
  export async function upsertProcess(conn, row) {
3
- await exec(conn, `MATCH (r:Repo {repoId: $repoId})
4
- MERGE (p:Process {processId: $processId})
5
- SET p.repoId = $repoId,
6
- p.entrySymbolId = $entrySymbolId,
7
- p.label = $label,
8
- p.depth = $depth,
9
- p.versionId = $versionId,
10
- p.createdAt = $createdAt
3
+ await exec(conn, `MATCH (r:Repo {repoId: $repoId})
4
+ MERGE (p:Process {processId: $processId})
5
+ SET p.repoId = $repoId,
6
+ p.entrySymbolId = $entrySymbolId,
7
+ p.label = $label,
8
+ p.depth = $depth,
9
+ p.versionId = $versionId,
10
+ p.createdAt = $createdAt
11
11
  MERGE (p)-[:PROCESS_IN_REPO]->(r)`, {
12
12
  processId: row.processId,
13
13
  repoId: row.repoId,
@@ -19,10 +19,10 @@ export async function upsertProcess(conn, row) {
19
19
  });
20
20
  }
21
21
  export async function upsertProcessStep(conn, row) {
22
- await exec(conn, `MATCH (s:Symbol {symbolId: $symbolId})
23
- MATCH (p:Process {processId: $processId})
24
- MERGE (s)-[r:PARTICIPATES_IN]->(p)
25
- SET r.stepOrder = $stepOrder,
22
+ await exec(conn, `MATCH (s:Symbol {symbolId: $symbolId})
23
+ MATCH (p:Process {processId: $processId})
24
+ MERGE (s)-[r:PARTICIPATES_IN]->(p)
25
+ SET r.stepOrder = $stepOrder,
26
26
  r.role = $role`, {
27
27
  processId: row.processId,
28
28
  symbolId: row.symbolId,
@@ -35,10 +35,10 @@ export async function upsertProcessStepsBatch(conn, steps) {
35
35
  return;
36
36
  await withTransaction(conn, async (txConn) => {
37
37
  for (const step of steps) {
38
- await exec(txConn, `MATCH (s:Symbol {symbolId: $symbolId})
39
- MATCH (p:Process {processId: $processId})
40
- MERGE (s)-[r:PARTICIPATES_IN]->(p)
41
- SET r.stepOrder = $stepOrder,
38
+ await exec(txConn, `MATCH (s:Symbol {symbolId: $symbolId})
39
+ MATCH (p:Process {processId: $processId})
40
+ MERGE (s)-[r:PARTICIPATES_IN]->(p)
41
+ SET r.stepOrder = $stepOrder,
42
42
  r.role = $role`, {
43
43
  processId: step.processId,
44
44
  symbolId: step.symbolId,
@@ -49,13 +49,13 @@ export async function upsertProcessStepsBatch(conn, steps) {
49
49
  });
50
50
  }
51
51
  export async function getProcessesForSymbol(conn, symbolId) {
52
- const rows = await queryAll(conn, `MATCH (s:Symbol {symbolId: $symbolId})-[r:PARTICIPATES_IN]->(p:Process)
53
- RETURN p.processId AS processId,
54
- p.entrySymbolId AS entrySymbolId,
55
- p.label AS label,
56
- p.depth AS depth,
57
- r.stepOrder AS stepOrder,
58
- r.role AS role
52
+ const rows = await queryAll(conn, `MATCH (s:Symbol {symbolId: $symbolId})-[r:PARTICIPATES_IN]->(p:Process)
53
+ RETURN p.processId AS processId,
54
+ p.entrySymbolId AS entrySymbolId,
55
+ p.label AS label,
56
+ p.depth AS depth,
57
+ r.stepOrder AS stepOrder,
58
+ r.role AS role
59
59
  ORDER BY r.stepOrder ASC, processId ASC`, { symbolId });
60
60
  return rows.map((row) => ({
61
61
  processId: row.processId,
@@ -69,15 +69,15 @@ export async function getProcessesForSymbol(conn, symbolId) {
69
69
  export async function getProcessesForSymbols(conn, symbolIds) {
70
70
  if (symbolIds.length === 0)
71
71
  return new Map();
72
- const rows = await queryAll(conn, `MATCH (s:Symbol)-[r:PARTICIPATES_IN]->(p:Process)
73
- WHERE s.symbolId IN $symbolIds
74
- RETURN s.symbolId AS symbolId,
75
- p.processId AS processId,
76
- p.entrySymbolId AS entrySymbolId,
77
- p.label AS label,
78
- p.depth AS depth,
79
- r.stepOrder AS stepOrder,
80
- r.role AS role
72
+ const rows = await queryAll(conn, `MATCH (s:Symbol)-[r:PARTICIPATES_IN]->(p:Process)
73
+ WHERE s.symbolId IN $symbolIds
74
+ RETURN s.symbolId AS symbolId,
75
+ p.processId AS processId,
76
+ p.entrySymbolId AS entrySymbolId,
77
+ p.label AS label,
78
+ p.depth AS depth,
79
+ r.stepOrder AS stepOrder,
80
+ r.role AS role
81
81
  ORDER BY symbolId ASC, r.stepOrder ASC, processId ASC`, { symbolIds });
82
82
  const map = new Map();
83
83
  for (const row of rows) {
@@ -95,15 +95,15 @@ export async function getProcessesForSymbols(conn, symbolIds) {
95
95
  return map;
96
96
  }
97
97
  export async function getProcessOverviewStats(conn, repoId) {
98
- const agg = await querySingle(conn, `MATCH (r:Repo {repoId: $repoId})<-[:PROCESS_IN_REPO]-(p:Process)
99
- RETURN COUNT(p) AS totalProcesses,
100
- AVG(p.depth) AS averageDepth,
98
+ const agg = await querySingle(conn, `MATCH (r:Repo {repoId: $repoId})<-[:PROCESS_IN_REPO]-(p:Process)
99
+ RETURN COUNT(p) AS totalProcesses,
100
+ AVG(p.depth) AS averageDepth,
101
101
  COUNT(DISTINCT p.entrySymbolId) AS entryPoints`, { repoId });
102
- const top = await queryAll(conn, `MATCH (r:Repo {repoId: $repoId})<-[:PROCESS_IN_REPO]-(p:Process)
103
- RETURN p.processId AS processId,
104
- p.label AS label,
105
- p.depth AS depth
106
- ORDER BY depth DESC, processId ASC
102
+ const top = await queryAll(conn, `MATCH (r:Repo {repoId: $repoId})<-[:PROCESS_IN_REPO]-(p:Process)
103
+ RETURN p.processId AS processId,
104
+ p.label AS label,
105
+ p.depth AS depth
106
+ ORDER BY depth DESC, processId ASC
107
107
  LIMIT 5`, { repoId });
108
108
  return {
109
109
  totalProcesses: toNumber(agg?.totalProcesses ?? 0),
@@ -117,10 +117,10 @@ export async function getProcessOverviewStats(conn, repoId) {
117
117
  };
118
118
  }
119
119
  export async function getProcessFlow(conn, processId) {
120
- const rows = await queryAll(conn, `MATCH (s:Symbol)-[r:PARTICIPATES_IN]->(p:Process {processId: $processId})
121
- RETURN s.symbolId AS symbolId,
122
- r.stepOrder AS stepOrder,
123
- r.role AS role
120
+ const rows = await queryAll(conn, `MATCH (s:Symbol)-[r:PARTICIPATES_IN]->(p:Process {processId: $processId})
121
+ RETURN s.symbolId AS symbolId,
122
+ r.stepOrder AS stepOrder,
123
+ r.role AS role
124
124
  ORDER BY r.stepOrder ASC, symbolId ASC`, { processId });
125
125
  return rows.map((row) => ({
126
126
  symbolId: row.symbolId,
@@ -129,13 +129,13 @@ export async function getProcessFlow(conn, processId) {
129
129
  }));
130
130
  }
131
131
  export async function getProcessStepsAfterSymbol(conn, processId, symbolId) {
132
- const rows = await queryAll(conn, `MATCH (s:Symbol {symbolId: $symbolId})-[r:PARTICIPATES_IN]->(p:Process {processId: $processId})
133
- WITH p, r.stepOrder AS startOrder
134
- MATCH (s2:Symbol)-[r2:PARTICIPATES_IN]->(p)
135
- WHERE r2.stepOrder > startOrder
136
- RETURN s2.symbolId AS symbolId,
137
- r2.stepOrder AS stepOrder,
138
- r2.role AS role
132
+ const rows = await queryAll(conn, `MATCH (s:Symbol {symbolId: $symbolId})-[r:PARTICIPATES_IN]->(p:Process {processId: $processId})
133
+ WITH p, r.stepOrder AS startOrder
134
+ MATCH (s2:Symbol)-[r2:PARTICIPATES_IN]->(p)
135
+ WHERE r2.stepOrder > startOrder
136
+ RETURN s2.symbolId AS symbolId,
137
+ r2.stepOrder AS stepOrder,
138
+ r2.role AS role
139
139
  ORDER BY r2.stepOrder ASC, symbolId ASC`, { processId, symbolId });
140
140
  return rows.map((row) => ({
141
141
  symbolId: row.symbolId,
@@ -145,12 +145,12 @@ export async function getProcessStepsAfterSymbol(conn, processId, symbolId) {
145
145
  }
146
146
  export async function deleteProcessesByRepo(conn, repoId) {
147
147
  await withTransaction(conn, async (txConn) => {
148
- await exec(txConn, `MATCH (p:Process {repoId: $repoId})
149
- OPTIONAL MATCH (:Symbol)-[m:PARTICIPATES_IN]->(p)
148
+ await exec(txConn, `MATCH (p:Process {repoId: $repoId})
149
+ OPTIONAL MATCH (:Symbol)-[m:PARTICIPATES_IN]->(p)
150
150
  DELETE m`, { repoId });
151
- await exec(txConn, `MATCH (p:Process {repoId: $repoId})-[rel:PROCESS_IN_REPO]->(:Repo {repoId: $repoId})
151
+ await exec(txConn, `MATCH (p:Process {repoId: $repoId})-[rel:PROCESS_IN_REPO]->(:Repo {repoId: $repoId})
152
152
  DELETE rel`, { repoId });
153
- await exec(txConn, `MATCH (p:Process {repoId: $repoId})
153
+ await exec(txConn, `MATCH (p:Process {repoId: $repoId})
154
154
  DELETE p`, { repoId });
155
155
  });
156
156
  }