slyplan-mcp 1.7.3 → 1.7.5
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.
- package/dist/cli.js +4 -5
- package/dist/db.js +41 -28
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -347,11 +347,10 @@ function mergeMcpJson(existing, auth) {
|
|
|
347
347
|
else if (auth.refreshToken) {
|
|
348
348
|
env.SLYPLAN_REFRESH_TOKEN = auth.refreshToken;
|
|
349
349
|
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
args: ['-y', 'slyplan-mcp@latest'],
|
|
353
|
-
env
|
|
354
|
-
};
|
|
350
|
+
const isWindows = process.platform === 'win32';
|
|
351
|
+
result.mcpServers.slyplan = isWindows
|
|
352
|
+
? { command: 'cmd', args: ['/c', 'npx', '-y', 'slyplan-mcp@latest'], env }
|
|
353
|
+
: { command: 'npx', args: ['-y', 'slyplan-mcp@latest'], env };
|
|
355
354
|
return result;
|
|
356
355
|
}
|
|
357
356
|
// Hooks go in .claude/settings.json
|
package/dist/db.js
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
import { supabase, getUserId } from './supabase.js';
|
|
2
2
|
import { v4 as uuid } from 'uuid';
|
|
3
|
+
// --- Helpers ---
|
|
4
|
+
// Explicit column lists to reduce Supabase egress (avoid select('*'))
|
|
5
|
+
const NODE_COLUMNS = 'id,parent_id,type,title,description,status,progress,sort_order,collapsed,metadata,created_by,created_at,updated_at';
|
|
6
|
+
const LINK_COLUMNS = 'id,node_id,url,label,link_type,created_at';
|
|
7
|
+
/** Batch-fetch links for multiple node IDs in a single query */
|
|
8
|
+
async function batchGetLinks(nodeIds) {
|
|
9
|
+
const linksByNode = new Map();
|
|
10
|
+
if (nodeIds.length === 0)
|
|
11
|
+
return linksByNode;
|
|
12
|
+
const { data: linkRows } = await supabase
|
|
13
|
+
.from('links')
|
|
14
|
+
.select(LINK_COLUMNS)
|
|
15
|
+
.in('node_id', nodeIds);
|
|
16
|
+
for (const link of (linkRows || [])) {
|
|
17
|
+
const arr = linksByNode.get(link.node_id) || [];
|
|
18
|
+
arr.push(dbLinkToLink(link));
|
|
19
|
+
linksByNode.set(link.node_id, arr);
|
|
20
|
+
}
|
|
21
|
+
return linksByNode;
|
|
22
|
+
}
|
|
3
23
|
function dbNodeToTree(row, links, children) {
|
|
4
24
|
return {
|
|
5
25
|
id: row.id,
|
|
@@ -32,17 +52,17 @@ function dbLinkToLink(row) {
|
|
|
32
52
|
export async function getTree(rootId, maxDepth) {
|
|
33
53
|
const { data: allNodes, error: nodesErr } = await supabase
|
|
34
54
|
.from('nodes')
|
|
35
|
-
.select(
|
|
55
|
+
.select(NODE_COLUMNS)
|
|
36
56
|
.order('sort_order', { ascending: true });
|
|
37
57
|
if (nodesErr)
|
|
38
58
|
throw new Error(nodesErr.message);
|
|
39
59
|
const { data: allLinks, error: linksErr } = await supabase
|
|
40
60
|
.from('links')
|
|
41
|
-
.select(
|
|
61
|
+
.select(LINK_COLUMNS);
|
|
42
62
|
if (linksErr)
|
|
43
63
|
throw new Error(linksErr.message);
|
|
44
64
|
const linksByNode = new Map();
|
|
45
|
-
for (const link of allLinks || []) {
|
|
65
|
+
for (const link of (allLinks || [])) {
|
|
46
66
|
const arr = linksByNode.get(link.node_id) || [];
|
|
47
67
|
arr.push(dbLinkToLink(link));
|
|
48
68
|
linksByNode.set(link.node_id, arr);
|
|
@@ -88,16 +108,13 @@ export async function getTree(rootId, maxDepth) {
|
|
|
88
108
|
export async function getNode(id, maxDepth = 1) {
|
|
89
109
|
const { data: row, error } = await supabase
|
|
90
110
|
.from('nodes')
|
|
91
|
-
.select(
|
|
111
|
+
.select(NODE_COLUMNS)
|
|
92
112
|
.eq('id', id)
|
|
93
113
|
.single();
|
|
94
114
|
if (error || !row)
|
|
95
115
|
return null;
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
.select('*')
|
|
99
|
-
.eq('node_id', id);
|
|
100
|
-
const links = (linkRows || []).map(dbLinkToLink);
|
|
116
|
+
const linkMap = await batchGetLinks([id]);
|
|
117
|
+
const links = linkMap.get(id) || [];
|
|
101
118
|
const children = maxDepth > 0 ? await getChildrenRecursive(id, maxDepth, 1) : [];
|
|
102
119
|
let progress = row.progress;
|
|
103
120
|
if (children.length > 0) {
|
|
@@ -108,15 +125,17 @@ export async function getNode(id, maxDepth = 1) {
|
|
|
108
125
|
async function getChildrenRecursive(parentId, maxDepth, currentDepth) {
|
|
109
126
|
const { data: childRows } = await supabase
|
|
110
127
|
.from('nodes')
|
|
111
|
-
.select(
|
|
128
|
+
.select(NODE_COLUMNS)
|
|
112
129
|
.eq('parent_id', parentId)
|
|
113
130
|
.order('sort_order', { ascending: true });
|
|
131
|
+
const typedChildren = (childRows || []);
|
|
132
|
+
if (typedChildren.length === 0)
|
|
133
|
+
return [];
|
|
134
|
+
// Batch-fetch all links for this level in ONE query instead of N+1
|
|
135
|
+
const childIds = typedChildren.map(c => c.id);
|
|
136
|
+
const linkMap = await batchGetLinks(childIds);
|
|
114
137
|
const children = [];
|
|
115
|
-
for (const child of
|
|
116
|
-
const { data: childLinkRows } = await supabase
|
|
117
|
-
.from('links')
|
|
118
|
-
.select('*')
|
|
119
|
-
.eq('node_id', child.id);
|
|
138
|
+
for (const child of typedChildren) {
|
|
120
139
|
const grandchildren = currentDepth < maxDepth
|
|
121
140
|
? await getChildrenRecursive(child.id, maxDepth, currentDepth + 1)
|
|
122
141
|
: [];
|
|
@@ -124,7 +143,7 @@ async function getChildrenRecursive(parentId, maxDepth, currentDepth) {
|
|
|
124
143
|
if (grandchildren.length > 0) {
|
|
125
144
|
progress = Math.round(grandchildren.reduce((sum, c) => sum + c.progress, 0) / grandchildren.length);
|
|
126
145
|
}
|
|
127
|
-
children.push(dbNodeToTree({ ...child, progress }, (
|
|
146
|
+
children.push(dbNodeToTree({ ...child, progress }, linkMap.get(child.id) || [], grandchildren));
|
|
128
147
|
}
|
|
129
148
|
return children;
|
|
130
149
|
}
|
|
@@ -305,17 +324,11 @@ export async function getWorkMode() {
|
|
|
305
324
|
const nodeIds = wmRows.map(r => r.node_id);
|
|
306
325
|
const { data: nodeRows } = await supabase
|
|
307
326
|
.from('nodes')
|
|
308
|
-
.select(
|
|
327
|
+
.select(NODE_COLUMNS)
|
|
309
328
|
.in('id', nodeIds);
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
.from('links')
|
|
314
|
-
.select('*')
|
|
315
|
-
.eq('node_id', row.id);
|
|
316
|
-
results.push(dbNodeToTree(row, (linkRows || []).map(dbLinkToLink), []));
|
|
317
|
-
}
|
|
318
|
-
return results;
|
|
329
|
+
// Batch-fetch all links in ONE query instead of N+1
|
|
330
|
+
const linkMap = await batchGetLinks(nodeIds);
|
|
331
|
+
return (nodeRows || []).map(row => dbNodeToTree(row, linkMap.get(row.id) || [], []));
|
|
319
332
|
}
|
|
320
333
|
export async function addToWorkMode(nodeId) {
|
|
321
334
|
const userId = getUserId();
|
|
@@ -469,7 +482,7 @@ export async function removeFromWorkMode(nodeId) {
|
|
|
469
482
|
export async function searchNodes(query, filters) {
|
|
470
483
|
let q = supabase
|
|
471
484
|
.from('nodes')
|
|
472
|
-
.select(
|
|
485
|
+
.select(NODE_COLUMNS)
|
|
473
486
|
.or(`title.ilike.%${query}%,description.ilike.%${query}%`)
|
|
474
487
|
.order('sort_order', { ascending: true })
|
|
475
488
|
.limit(50);
|
|
@@ -524,7 +537,7 @@ export async function deleteDependency(id) {
|
|
|
524
537
|
export async function listDependencies(nodeIds) {
|
|
525
538
|
const { data, error } = await supabase
|
|
526
539
|
.from('node_dependencies')
|
|
527
|
-
.select('
|
|
540
|
+
.select('id,from_node_id,to_node_id,dependency_type,created_by,created_at')
|
|
528
541
|
.or(`from_node_id.in.(${nodeIds.join(',')}),to_node_id.in.(${nodeIds.join(',')})`);
|
|
529
542
|
if (error)
|
|
530
543
|
throw new Error(error.message);
|