@noteplanco/noteplan-mcp 1.1.23 → 1.1.24
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/README.md +7 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/noteplan/attachments-paths.d.ts +13 -0
- package/dist/noteplan/attachments-paths.d.ts.map +1 -0
- package/dist/noteplan/attachments-paths.js +27 -0
- package/dist/noteplan/attachments-paths.js.map +1 -0
- package/dist/noteplan/embeddings.js +1 -1
- package/dist/noteplan/embeddings.js.map +1 -1
- package/dist/noteplan/file-reader.d.ts +37 -46
- package/dist/noteplan/file-reader.d.ts.map +1 -1
- package/dist/noteplan/file-reader.js +200 -202
- package/dist/noteplan/file-reader.js.map +1 -1
- package/dist/noteplan/file-reader.test.d.ts +2 -0
- package/dist/noteplan/file-reader.test.d.ts.map +1 -0
- package/dist/noteplan/file-reader.test.js +67 -0
- package/dist/noteplan/file-reader.test.js.map +1 -0
- package/dist/noteplan/file-writer.d.ts +35 -31
- package/dist/noteplan/file-writer.d.ts.map +1 -1
- package/dist/noteplan/file-writer.js +280 -164
- package/dist/noteplan/file-writer.js.map +1 -1
- package/dist/noteplan/file-writer.test.js +704 -191
- package/dist/noteplan/file-writer.test.js.map +1 -1
- package/dist/noteplan/filter-store.d.ts +5 -5
- package/dist/noteplan/filter-store.d.ts.map +1 -1
- package/dist/noteplan/filter-store.js +94 -79
- package/dist/noteplan/filter-store.js.map +1 -1
- package/dist/noteplan/ripgrep-search.d.ts +25 -2
- package/dist/noteplan/ripgrep-search.d.ts.map +1 -1
- package/dist/noteplan/ripgrep-search.js +75 -2
- package/dist/noteplan/ripgrep-search.js.map +1 -1
- package/dist/noteplan/space-row-utils.d.ts +20 -0
- package/dist/noteplan/space-row-utils.d.ts.map +1 -0
- package/dist/noteplan/space-row-utils.js +78 -0
- package/dist/noteplan/space-row-utils.js.map +1 -0
- package/dist/noteplan/space-row-utils.test.d.ts +2 -0
- package/dist/noteplan/space-row-utils.test.d.ts.map +1 -0
- package/dist/noteplan/space-row-utils.test.js +123 -0
- package/dist/noteplan/space-row-utils.test.js.map +1 -0
- package/dist/noteplan/sqlite-reader.d.ts +12 -27
- package/dist/noteplan/sqlite-reader.d.ts.map +1 -1
- package/dist/noteplan/sqlite-reader.js +315 -221
- package/dist/noteplan/sqlite-reader.js.map +1 -1
- package/dist/noteplan/sqlite-writer.d.ts +1 -1
- package/dist/noteplan/sqlite-writer.d.ts.map +1 -1
- package/dist/noteplan/sqlite-writer.js +2 -2
- package/dist/noteplan/sqlite-writer.js.map +1 -1
- package/dist/noteplan/unified-store.d.ts +41 -30
- package/dist/noteplan/unified-store.d.ts.map +1 -1
- package/dist/noteplan/unified-store.js +257 -159
- package/dist/noteplan/unified-store.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +142 -61
- package/dist/server.js.map +1 -1
- package/dist/tools/attachments.d.ts +9 -9
- package/dist/tools/attachments.d.ts.map +1 -1
- package/dist/tools/attachments.js +74 -83
- package/dist/tools/attachments.js.map +1 -1
- package/dist/tools/attachments.test.js +170 -129
- package/dist/tools/attachments.test.js.map +1 -1
- package/dist/tools/calendar.d.ts +16 -13
- package/dist/tools/calendar.d.ts.map +1 -1
- package/dist/tools/calendar.js +17 -16
- package/dist/tools/calendar.js.map +1 -1
- package/dist/tools/embeddings.d.ts +6 -6
- package/dist/tools/embeddings.d.ts.map +1 -1
- package/dist/tools/embeddings.js +6 -6
- package/dist/tools/embeddings.js.map +1 -1
- package/dist/tools/events.d.ts +7 -3
- package/dist/tools/events.d.ts.map +1 -1
- package/dist/tools/events.js +51 -16
- package/dist/tools/events.js.map +1 -1
- package/dist/tools/filters.d.ts +28 -33
- package/dist/tools/filters.d.ts.map +1 -1
- package/dist/tools/filters.js +42 -105
- package/dist/tools/filters.js.map +1 -1
- package/dist/tools/notes.d.ts +80 -218
- package/dist/tools/notes.d.ts.map +1 -1
- package/dist/tools/notes.js +180 -177
- package/dist/tools/notes.js.map +1 -1
- package/dist/tools/notes.test.js +242 -21
- package/dist/tools/notes.test.js.map +1 -1
- package/dist/tools/search.d.ts +4 -3
- package/dist/tools/search.d.ts.map +1 -1
- package/dist/tools/search.js +9 -5
- package/dist/tools/search.js.map +1 -1
- package/dist/tools/search.test.d.ts +2 -0
- package/dist/tools/search.test.d.ts.map +1 -0
- package/dist/tools/search.test.js +37 -0
- package/dist/tools/search.test.js.map +1 -0
- package/dist/tools/spaces.d.ts +20 -20
- package/dist/tools/spaces.d.ts.map +1 -1
- package/dist/tools/spaces.js +28 -28
- package/dist/tools/spaces.js.map +1 -1
- package/dist/tools/tasks.d.ts +22 -22
- package/dist/tools/tasks.d.ts.map +1 -1
- package/dist/tools/tasks.js +22 -22
- package/dist/tools/tasks.js.map +1 -1
- package/dist/tools/templates.d.ts +7 -7
- package/dist/tools/templates.d.ts.map +1 -1
- package/dist/tools/templates.js +4 -4
- package/dist/tools/templates.js.map +1 -1
- package/dist/tools/themes.js +1 -1
- package/dist/tools/themes.js.map +1 -1
- package/dist/transport/bridge-availability.d.ts +5 -0
- package/dist/transport/bridge-availability.d.ts.map +1 -0
- package/dist/transport/bridge-availability.js +92 -0
- package/dist/transport/bridge-availability.js.map +1 -0
- package/dist/transport/bridge-cascade.d.ts +18 -0
- package/dist/transport/bridge-cascade.d.ts.map +1 -0
- package/dist/transport/bridge-cascade.js +78 -0
- package/dist/transport/bridge-cascade.js.map +1 -0
- package/dist/transport/bridge-cascade.test.d.ts +2 -0
- package/dist/transport/bridge-cascade.test.d.ts.map +1 -0
- package/dist/transport/bridge-cascade.test.js +160 -0
- package/dist/transport/bridge-cascade.test.js.map +1 -0
- package/dist/transport/bridge-client.d.ts +197 -0
- package/dist/transport/bridge-client.d.ts.map +1 -0
- package/dist/transport/bridge-client.js +288 -0
- package/dist/transport/bridge-client.js.map +1 -0
- package/dist/transport/bridge-client.test.d.ts +2 -0
- package/dist/transport/bridge-client.test.d.ts.map +1 -0
- package/dist/transport/bridge-client.test.js +384 -0
- package/dist/transport/bridge-client.test.js.map +1 -0
- package/dist/transport/bridge-context.d.ts +10 -0
- package/dist/transport/bridge-context.d.ts.map +1 -0
- package/dist/transport/bridge-context.js +18 -0
- package/dist/transport/bridge-context.js.map +1 -0
- package/dist/transport/bridge-fs.d.ts +25 -0
- package/dist/transport/bridge-fs.d.ts.map +1 -0
- package/dist/transport/bridge-fs.js +129 -0
- package/dist/transport/bridge-fs.js.map +1 -0
- package/dist/utils/date-utils.d.ts +24 -0
- package/dist/utils/date-utils.d.ts.map +1 -1
- package/dist/utils/date-utils.js +55 -0
- package/dist/utils/date-utils.js.map +1 -1
- package/dist/utils/date-utils.test.d.ts +2 -0
- package/dist/utils/date-utils.test.d.ts.map +1 -0
- package/dist/utils/date-utils.test.js +109 -0
- package/dist/utils/date-utils.test.js.map +1 -0
- package/dist/utils/folder-access.d.ts +23 -0
- package/dist/utils/folder-access.d.ts.map +1 -0
- package/dist/utils/folder-access.js +131 -0
- package/dist/utils/folder-access.js.map +1 -0
- package/dist/utils/folder-access.test.d.ts +2 -0
- package/dist/utils/folder-access.test.d.ts.map +1 -0
- package/dist/utils/folder-access.test.js +182 -0
- package/dist/utils/folder-access.test.js.map +1 -0
- package/dist/utils/folder-matcher.d.ts.map +1 -1
- package/dist/utils/folder-matcher.js +16 -0
- package/dist/utils/folder-matcher.js.map +1 -1
- package/dist/utils/folder-matcher.test.js +42 -0
- package/dist/utils/folder-matcher.test.js.map +1 -1
- package/dist/utils/server-config.d.ts +10 -2
- package/dist/utils/server-config.d.ts.map +1 -1
- package/dist/utils/server-config.js +16 -2
- package/dist/utils/server-config.js.map +1 -1
- package/dist/utils/version.d.ts +2 -0
- package/dist/utils/version.d.ts.map +1 -1
- package/dist/utils/version.js +5 -1
- package/dist/utils/version.js.map +1 -1
- package/package.json +4 -3
- package/scripts/calendar-helper +0 -0
- package/scripts/reminders-helper +0 -0
|
@@ -1,12 +1,45 @@
|
|
|
1
1
|
// Ripgrep wrapper for fast local file search
|
|
2
2
|
import { spawn } from 'child_process';
|
|
3
3
|
import { getNotesPath, getCalendarPath } from './file-reader.js';
|
|
4
|
+
import { getBridgeClient } from '../transport/bridge-availability.js';
|
|
4
5
|
/**
|
|
5
|
-
* Search files using
|
|
6
|
-
*
|
|
6
|
+
* Search files using the NotePlan bridge (preferred) or ripgrep (fallback).
|
|
7
|
+
*
|
|
8
|
+
* The bridge path runs the regex against NoteCache inside NotePlan, which
|
|
9
|
+
* avoids two problems with calling ripgrep from the MCP process:
|
|
10
|
+
* 1. TCC interrupts ripgrep when the parent (Claude Code's node) lacks
|
|
11
|
+
* Full Disk Access — manifested as "ripgrep interrupted" warnings.
|
|
12
|
+
* 2. Spawning a subprocess per search is slower on large vaults.
|
|
13
|
+
*
|
|
14
|
+
* Falls back to ripgrep when the bridge is unavailable (NotePlan closed
|
|
15
|
+
* or older build) and finally errors out if ripgrep isn't installed.
|
|
16
|
+
*
|
|
17
|
+
* Note: the bridge path doesn't currently support `paths` (folder-scoped
|
|
18
|
+
* search), `wordBoundary`, or `contextLines`; if any of those is
|
|
19
|
+
* requested we go straight to ripgrep so the caller still gets the
|
|
20
|
+
* exact behaviour they asked for.
|
|
7
21
|
*/
|
|
8
22
|
export async function searchWithRipgrep(pattern, options = {}) {
|
|
9
23
|
const { caseSensitive = false, wordBoundary = false, contextLines = 0, maxResults = 100, paths = [getNotesPath(), getCalendarPath()], } = options;
|
|
24
|
+
// The bridge backs onto SearchHelper, which is always case-insensitive
|
|
25
|
+
// and uses all-words matching (not regex). Fall through to ripgrep when
|
|
26
|
+
// the caller needs anything more specific.
|
|
27
|
+
const canUseBridge = !wordBoundary &&
|
|
28
|
+
contextLines === 0 &&
|
|
29
|
+
options.paths === undefined &&
|
|
30
|
+
!caseSensitive;
|
|
31
|
+
if (canUseBridge) {
|
|
32
|
+
const bridge = await getBridgeClient();
|
|
33
|
+
if (bridge) {
|
|
34
|
+
try {
|
|
35
|
+
const matches = await bridge.search(pattern, { limit: maxResults });
|
|
36
|
+
return { matches, partialResults: false, backend: 'bridge' };
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
console.error('[bridge.search] failed, falling back to ripgrep:', err instanceof Error ? err.message : err);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
10
43
|
// Build args array (safe - no shell interpretation)
|
|
11
44
|
const args = [
|
|
12
45
|
'--json', // JSON output for parsing
|
|
@@ -45,6 +78,7 @@ export async function searchWithRipgrep(pattern, options = {}) {
|
|
|
45
78
|
resolve({
|
|
46
79
|
matches: parseRipgrepJson(stdout),
|
|
47
80
|
partialResults: false,
|
|
81
|
+
backend: 'ripgrep',
|
|
48
82
|
});
|
|
49
83
|
}
|
|
50
84
|
else {
|
|
@@ -55,6 +89,7 @@ export async function searchWithRipgrep(pattern, options = {}) {
|
|
|
55
89
|
matches: partialMatches,
|
|
56
90
|
partialResults: true,
|
|
57
91
|
warning: 'ripgrep interrupted; returning partial local matches',
|
|
92
|
+
backend: 'ripgrep',
|
|
58
93
|
});
|
|
59
94
|
return;
|
|
60
95
|
}
|
|
@@ -107,4 +142,42 @@ export async function isRipgrepAvailable() {
|
|
|
107
142
|
rg.on('error', () => resolve(false));
|
|
108
143
|
});
|
|
109
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* Run ripgrep with --only-matching against the given paths and pattern.
|
|
147
|
+
* Returns each raw match as a string (no file/line context). Used for
|
|
148
|
+
* cheap aggregation tasks like global tag extraction where reading every
|
|
149
|
+
* note's full content via the bridge would take ~minutes.
|
|
150
|
+
*
|
|
151
|
+
* Returns null when ripgrep isn't available so the caller can fall back.
|
|
152
|
+
*/
|
|
153
|
+
export async function ripgrepOnlyMatching(pattern, paths) {
|
|
154
|
+
if (paths.length === 0)
|
|
155
|
+
return [];
|
|
156
|
+
const args = [
|
|
157
|
+
'--no-filename',
|
|
158
|
+
'--no-line-number',
|
|
159
|
+
'--only-matching',
|
|
160
|
+
'-g', '*.md',
|
|
161
|
+
'-g', '*.txt',
|
|
162
|
+
'--', pattern,
|
|
163
|
+
...paths,
|
|
164
|
+
];
|
|
165
|
+
return new Promise((resolve) => {
|
|
166
|
+
const rg = spawn('rg', args, { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
167
|
+
let stdout = '';
|
|
168
|
+
let stderr = '';
|
|
169
|
+
rg.stdout.on('data', (d) => { stdout += d; });
|
|
170
|
+
rg.stderr.on('data', (d) => { stderr += d; });
|
|
171
|
+
rg.on('close', (code) => {
|
|
172
|
+
// 0 = matches, 1 = no matches, 2+ = error
|
|
173
|
+
if (code === 0 || code === 1) {
|
|
174
|
+
resolve(stdout.split('\n').map((l) => l.trim()).filter(Boolean));
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
console.error(`[ripgrep] only-matching failed (code ${code}): ${stderr.slice(0, 200)}`);
|
|
178
|
+
resolve(null);
|
|
179
|
+
});
|
|
180
|
+
rg.on('error', () => resolve(null));
|
|
181
|
+
});
|
|
182
|
+
}
|
|
110
183
|
//# sourceMappingURL=ripgrep-search.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ripgrep-search.js","sourceRoot":"","sources":["../../src/noteplan/ripgrep-search.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAE7C,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"ripgrep-search.js","sourceRoot":"","sources":["../../src/noteplan/ripgrep-search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Note } from './types.js';
|
|
2
|
+
import type { BridgeSpaceRow } from '../transport/bridge-client.js';
|
|
3
|
+
export declare function isTrashFolderRow(row: {
|
|
4
|
+
is_dir: number;
|
|
5
|
+
title?: string | null;
|
|
6
|
+
}): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Trash filtering over bridge rows (notes + folders, no SQL). Returns
|
|
9
|
+
* the input unchanged when `includeTrash` is true. Otherwise BFSes from
|
|
10
|
+
* every `@Trash` folder ID and excludes their descendants.
|
|
11
|
+
*/
|
|
12
|
+
export declare function filterBridgeRowsByTrash(rows: BridgeSpaceRow[], includeTrash?: boolean): BridgeSpaceRow[];
|
|
13
|
+
export declare function bridgeRowToNote(row: BridgeSpaceRow, allRows?: BridgeSpaceRow[]): Note;
|
|
14
|
+
/**
|
|
15
|
+
* Walk the parent chain to find a row's root teamspace ID. Defensive
|
|
16
|
+
* against parent cycles (corrupt or hand-edited DB rows): a `seen` set
|
|
17
|
+
* breaks any loop and returns undefined.
|
|
18
|
+
*/
|
|
19
|
+
export declare function findRootSpaceIdFromRows(noteId: string, rows: BridgeSpaceRow[]): string | undefined;
|
|
20
|
+
//# sourceMappingURL=space-row-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"space-row-utils.d.ts","sourceRoot":"","sources":["../../src/noteplan/space-row-utils.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAGlC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAIpE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,OAAO,CAExF;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,cAAc,EAAE,EACtB,YAAY,UAAQ,GACnB,cAAc,EAAE,CAsBlB;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,cAAc,EAAE,GAAG,IAAI,CAerF;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,MAAM,GAAG,SAAS,CAalG"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// Pure helpers that operate on `BridgeSpaceRow[]` (the row shape the
|
|
2
|
+
// `/spaces/notes` bridge endpoint returns). Extracted so they can be
|
|
3
|
+
// unit-tested without spinning up a database or a bridge connection.
|
|
4
|
+
import { extractTitle } from './markdown-parser.js';
|
|
5
|
+
import { SQLITE_NOTE_TYPES } from './types.js';
|
|
6
|
+
const SPACE_TRASH_FOLDER_TITLE_LOWER = '@trash';
|
|
7
|
+
export function isTrashFolderRow(row) {
|
|
8
|
+
return row.is_dir === 1 && (row.title ?? '').toLowerCase() === SPACE_TRASH_FOLDER_TITLE_LOWER;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Trash filtering over bridge rows (notes + folders, no SQL). Returns
|
|
12
|
+
* the input unchanged when `includeTrash` is true. Otherwise BFSes from
|
|
13
|
+
* every `@Trash` folder ID and excludes their descendants.
|
|
14
|
+
*/
|
|
15
|
+
export function filterBridgeRowsByTrash(rows, includeTrash = false) {
|
|
16
|
+
if (includeTrash)
|
|
17
|
+
return rows;
|
|
18
|
+
const trashFolderIds = rows.filter(isTrashFolderRow).map((r) => r.id);
|
|
19
|
+
if (trashFolderIds.length === 0)
|
|
20
|
+
return rows;
|
|
21
|
+
const childrenByParent = new Map();
|
|
22
|
+
for (const r of rows) {
|
|
23
|
+
if (r.parent) {
|
|
24
|
+
const arr = childrenByParent.get(r.parent) ?? [];
|
|
25
|
+
arr.push(r.id);
|
|
26
|
+
childrenByParent.set(r.parent, arr);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const trashed = new Set();
|
|
30
|
+
const queue = [...trashFolderIds];
|
|
31
|
+
while (queue.length > 0) {
|
|
32
|
+
const id = queue.shift();
|
|
33
|
+
if (trashed.has(id))
|
|
34
|
+
continue;
|
|
35
|
+
trashed.add(id);
|
|
36
|
+
queue.push(...(childrenByParent.get(id) ?? []));
|
|
37
|
+
}
|
|
38
|
+
return rows.filter((r) => !trashed.has(r.id));
|
|
39
|
+
}
|
|
40
|
+
export function bridgeRowToNote(row, allRows) {
|
|
41
|
+
const isCalendar = row.note_type === SQLITE_NOTE_TYPES.TEAMSPACE_CALENDAR;
|
|
42
|
+
const spaceId = allRows ? findRootSpaceIdFromRows(row.id, allRows) : undefined;
|
|
43
|
+
return {
|
|
44
|
+
id: row.id,
|
|
45
|
+
title: row.content ? extractTitle(row.content) : row.title || 'Untitled',
|
|
46
|
+
filename: row.filename,
|
|
47
|
+
content: row.content || '',
|
|
48
|
+
type: isCalendar ? 'calendar' : 'note',
|
|
49
|
+
source: 'space',
|
|
50
|
+
spaceId,
|
|
51
|
+
folder: row.parent || undefined,
|
|
52
|
+
modifiedAt: row.modified_at ? new Date(row.modified_at) : undefined,
|
|
53
|
+
createdAt: row.created_at ? new Date(row.created_at) : undefined,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Walk the parent chain to find a row's root teamspace ID. Defensive
|
|
58
|
+
* against parent cycles (corrupt or hand-edited DB rows): a `seen` set
|
|
59
|
+
* breaks any loop and returns undefined.
|
|
60
|
+
*/
|
|
61
|
+
export function findRootSpaceIdFromRows(noteId, rows) {
|
|
62
|
+
const byId = new Map(rows.map((r) => [r.id, r]));
|
|
63
|
+
const seen = new Set();
|
|
64
|
+
let current = byId.get(noteId);
|
|
65
|
+
while (current && current.parent) {
|
|
66
|
+
if (seen.has(current.id))
|
|
67
|
+
return undefined;
|
|
68
|
+
seen.add(current.id);
|
|
69
|
+
const parent = byId.get(current.parent);
|
|
70
|
+
if (!parent)
|
|
71
|
+
break;
|
|
72
|
+
if (parent.note_type === SQLITE_NOTE_TYPES.TEAMSPACE)
|
|
73
|
+
return parent.id;
|
|
74
|
+
current = parent;
|
|
75
|
+
}
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=space-row-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"space-row-utils.js","sourceRoot":"","sources":["../../src/noteplan/space-row-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"space-row-utils.test.d.ts","sourceRoot":"","sources":["../../src/noteplan/space-row-utils.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { filterBridgeRowsByTrash, findRootSpaceIdFromRows, isTrashFolderRow, } from './space-row-utils.js';
|
|
3
|
+
import { SQLITE_NOTE_TYPES } from './types.js';
|
|
4
|
+
function row(overrides) {
|
|
5
|
+
return {
|
|
6
|
+
content: '',
|
|
7
|
+
note_type: SQLITE_NOTE_TYPES.TEAMSPACE_NOTE,
|
|
8
|
+
title: '',
|
|
9
|
+
filename: '',
|
|
10
|
+
parent: null,
|
|
11
|
+
is_dir: 0,
|
|
12
|
+
...overrides,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
describe('isTrashFolderRow', () => {
|
|
16
|
+
it('matches @Trash folder regardless of casing', () => {
|
|
17
|
+
expect(isTrashFolderRow({ is_dir: 1, title: '@Trash' })).toBe(true);
|
|
18
|
+
expect(isTrashFolderRow({ is_dir: 1, title: '@trash' })).toBe(true);
|
|
19
|
+
expect(isTrashFolderRow({ is_dir: 1, title: '@TRASH' })).toBe(true);
|
|
20
|
+
});
|
|
21
|
+
it('rejects regular folders', () => {
|
|
22
|
+
expect(isTrashFolderRow({ is_dir: 1, title: 'Notes' })).toBe(false);
|
|
23
|
+
});
|
|
24
|
+
it('rejects notes named @Trash', () => {
|
|
25
|
+
// is_dir = 0 — a note literally titled "@Trash" should not be treated as the system folder.
|
|
26
|
+
expect(isTrashFolderRow({ is_dir: 0, title: '@Trash' })).toBe(false);
|
|
27
|
+
});
|
|
28
|
+
it('handles missing/null title', () => {
|
|
29
|
+
expect(isTrashFolderRow({ is_dir: 1, title: undefined })).toBe(false);
|
|
30
|
+
expect(isTrashFolderRow({ is_dir: 1, title: null })).toBe(false);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
describe('filterBridgeRowsByTrash', () => {
|
|
34
|
+
it('returns input unchanged when includeTrash=true', () => {
|
|
35
|
+
const rows = [row({ id: 'a' }), row({ id: 'b' })];
|
|
36
|
+
expect(filterBridgeRowsByTrash(rows, true)).toBe(rows);
|
|
37
|
+
});
|
|
38
|
+
it('returns input unchanged when no @Trash folder exists', () => {
|
|
39
|
+
const rows = [row({ id: 'a' }), row({ id: 'b' })];
|
|
40
|
+
expect(filterBridgeRowsByTrash(rows)).toEqual(rows);
|
|
41
|
+
});
|
|
42
|
+
it('removes the @Trash folder itself plus its descendants', () => {
|
|
43
|
+
const rows = [
|
|
44
|
+
row({ id: 'space', is_dir: 1, title: 'My Space' }),
|
|
45
|
+
row({ id: 'trash', is_dir: 1, title: '@Trash', parent: 'space' }),
|
|
46
|
+
row({ id: 'note-in-trash', parent: 'trash' }),
|
|
47
|
+
row({ id: 'note-in-trash-subfolder', parent: 'sub-trash-folder' }),
|
|
48
|
+
row({ id: 'sub-trash-folder', is_dir: 1, title: 'Inner', parent: 'trash' }),
|
|
49
|
+
row({ id: 'kept-note', parent: 'space' }),
|
|
50
|
+
];
|
|
51
|
+
const result = filterBridgeRowsByTrash(rows);
|
|
52
|
+
const ids = result.map((r) => r.id).sort();
|
|
53
|
+
expect(ids).toEqual(['kept-note', 'space']);
|
|
54
|
+
});
|
|
55
|
+
it('handles MULTIPLE @Trash folders (one per teamspace)', () => {
|
|
56
|
+
// Real-world scenario: each teamspace has its own @Trash folder.
|
|
57
|
+
// Both subtrees must be filtered out.
|
|
58
|
+
const rows = [
|
|
59
|
+
row({ id: 'space-a', is_dir: 1, title: 'A' }),
|
|
60
|
+
row({ id: 'trash-a', is_dir: 1, title: '@Trash', parent: 'space-a' }),
|
|
61
|
+
row({ id: 'note-a-trashed', parent: 'trash-a' }),
|
|
62
|
+
row({ id: 'note-a-kept', parent: 'space-a' }),
|
|
63
|
+
row({ id: 'space-b', is_dir: 1, title: 'B' }),
|
|
64
|
+
row({ id: 'trash-b', is_dir: 1, title: '@Trash', parent: 'space-b' }),
|
|
65
|
+
row({ id: 'note-b-trashed', parent: 'trash-b' }),
|
|
66
|
+
row({ id: 'note-b-kept', parent: 'space-b' }),
|
|
67
|
+
];
|
|
68
|
+
const visible = filterBridgeRowsByTrash(rows).map((r) => r.id).sort();
|
|
69
|
+
expect(visible).toEqual(['note-a-kept', 'note-b-kept', 'space-a', 'space-b']);
|
|
70
|
+
});
|
|
71
|
+
it('does not infinite-loop on a parent-chain cycle inside @Trash', () => {
|
|
72
|
+
// a -> b -> a (corrupt data); both reachable from @Trash root.
|
|
73
|
+
const rows = [
|
|
74
|
+
row({ id: 'trash', is_dir: 1, title: '@Trash' }),
|
|
75
|
+
row({ id: 'a', is_dir: 1, title: 'A', parent: 'trash' }),
|
|
76
|
+
// The bridge graph itself shouldn't have cycles, but be defensive.
|
|
77
|
+
row({ id: 'b', is_dir: 1, title: 'B', parent: 'a' }),
|
|
78
|
+
// Children-by-parent map is built by iterating once over rows, so
|
|
79
|
+
// the dedupe `seen` set inside the BFS is what saves us.
|
|
80
|
+
row({ id: 'note', parent: 'b' }),
|
|
81
|
+
];
|
|
82
|
+
// Should complete in well under a second; vitest's default 5s timeout
|
|
83
|
+
// catches a real infinite loop.
|
|
84
|
+
const visible = filterBridgeRowsByTrash(rows).map((r) => r.id);
|
|
85
|
+
expect(visible).toEqual([]);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
describe('findRootSpaceIdFromRows', () => {
|
|
89
|
+
it('returns undefined for a top-level note with no parent', () => {
|
|
90
|
+
const rows = [row({ id: 'orphan' })];
|
|
91
|
+
expect(findRootSpaceIdFromRows('orphan', rows)).toBeUndefined();
|
|
92
|
+
});
|
|
93
|
+
it('walks the chain to the teamspace root', () => {
|
|
94
|
+
const rows = [
|
|
95
|
+
row({ id: 'space', is_dir: 1, note_type: SQLITE_NOTE_TYPES.TEAMSPACE, title: 'Engineering' }),
|
|
96
|
+
row({ id: 'folder', is_dir: 1, parent: 'space', title: 'Subfolder' }),
|
|
97
|
+
row({ id: 'note', parent: 'folder' }),
|
|
98
|
+
];
|
|
99
|
+
expect(findRootSpaceIdFromRows('note', rows)).toBe('space');
|
|
100
|
+
});
|
|
101
|
+
it('returns undefined when the chain breaks before hitting a teamspace', () => {
|
|
102
|
+
const rows = [
|
|
103
|
+
row({ id: 'note', parent: 'missing-parent' }),
|
|
104
|
+
];
|
|
105
|
+
expect(findRootSpaceIdFromRows('note', rows)).toBeUndefined();
|
|
106
|
+
});
|
|
107
|
+
it('does NOT infinite-loop on a self-referential parent', () => {
|
|
108
|
+
// Self-loop: row's parent points at itself. Bug regression — the
|
|
109
|
+
// previous implementation hung indefinitely.
|
|
110
|
+
const rows = [row({ id: 'note', parent: 'note' })];
|
|
111
|
+
expect(findRootSpaceIdFromRows('note', rows)).toBeUndefined();
|
|
112
|
+
});
|
|
113
|
+
it('does NOT infinite-loop on a longer parent cycle', () => {
|
|
114
|
+
// a -> b -> a
|
|
115
|
+
const rows = [
|
|
116
|
+
row({ id: 'a', parent: 'b' }),
|
|
117
|
+
row({ id: 'b', parent: 'a' }),
|
|
118
|
+
];
|
|
119
|
+
expect(findRootSpaceIdFromRows('a', rows)).toBeUndefined();
|
|
120
|
+
expect(findRootSpaceIdFromRows('b', rows)).toBeUndefined();
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
//# sourceMappingURL=space-row-utils.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"space-row-utils.test.js","sourceRoot":"","sources":["../../src/noteplan/space-row-utils.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,32 +12,20 @@ export declare function getDatabasePath(): string | null;
|
|
|
12
12
|
* Close the database connection
|
|
13
13
|
*/
|
|
14
14
|
export declare function closeDatabase(): void;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
*/
|
|
18
|
-
export declare function listSpaces(): Space[];
|
|
19
|
-
/**
|
|
20
|
-
* Count notes and subfolders under a space folder (recursive)
|
|
21
|
-
*/
|
|
22
|
-
export declare function countSpaceFolderContents(folderId: string): {
|
|
15
|
+
export declare function listSpaces(): Promise<Space[]>;
|
|
16
|
+
export declare function countSpaceFolderContents(folderId: string): Promise<{
|
|
23
17
|
noteCount: number;
|
|
24
18
|
folderCount: number;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* List notes in a teamspace
|
|
28
|
-
*/
|
|
19
|
+
}>;
|
|
29
20
|
export declare function listSpaceNotes(spaceIdOrOptions?: string | {
|
|
30
21
|
spaceId?: string;
|
|
31
22
|
includeTrash?: boolean;
|
|
32
|
-
}): Note[]
|
|
33
|
-
|
|
34
|
-
* Get a specific teamspace note by ID or filename
|
|
35
|
-
*/
|
|
36
|
-
export declare function getSpaceNote(identifier: string): Note | null;
|
|
23
|
+
}): Promise<Note[]>;
|
|
24
|
+
export declare function getSpaceNote(identifier: string): Promise<Note | null>;
|
|
37
25
|
/**
|
|
38
26
|
* Get a teamspace note by title
|
|
39
27
|
*/
|
|
40
|
-
export declare function getSpaceNoteByTitle(title: string, spaceId?: string, includeTrash?: boolean): Note | null
|
|
28
|
+
export declare function getSpaceNoteByTitle(title: string, spaceId?: string, includeTrash?: boolean): Promise<Note | null>;
|
|
41
29
|
/**
|
|
42
30
|
* Search teamspace notes using LIKE pattern (fallback)
|
|
43
31
|
*/
|
|
@@ -54,24 +42,21 @@ export declare function searchSpaceNotesFTS(query: string, options?: {
|
|
|
54
42
|
spaceId?: string;
|
|
55
43
|
limit?: number;
|
|
56
44
|
includeTrash?: boolean;
|
|
57
|
-
}): Note[]
|
|
45
|
+
}): Promise<Note[]>;
|
|
58
46
|
/**
|
|
59
47
|
* List folders in teamspace
|
|
60
48
|
*/
|
|
61
49
|
export declare function listSpaceFolders(spaceIdOrOptions?: string | {
|
|
62
50
|
spaceId?: string;
|
|
63
51
|
includeTrash?: boolean;
|
|
64
|
-
}): Folder[]
|
|
52
|
+
}): Promise<Folder[]>;
|
|
65
53
|
export declare function resolveSpaceFolder(spaceId: string, identifier: string, options?: {
|
|
66
54
|
includeTrash?: boolean;
|
|
67
|
-
}): Folder | null
|
|
68
|
-
export declare function isSpaceNoteInTrash(identifier: string): boolean
|
|
55
|
+
}): Promise<Folder | null>;
|
|
56
|
+
export declare function isSpaceNoteInTrash(identifier: string): Promise<boolean>;
|
|
69
57
|
/**
|
|
70
58
|
* Extract all unique tags from teamspace notes
|
|
71
59
|
*/
|
|
72
|
-
export declare function extractSpaceTags(spaceId?: string): string[]
|
|
73
|
-
|
|
74
|
-
* Get calendar note from teamspace by date
|
|
75
|
-
*/
|
|
76
|
-
export declare function getSpaceCalendarNote(dateStr: string, spaceId: string): Note | null;
|
|
60
|
+
export declare function extractSpaceTags(spaceId?: string): Promise<string[]>;
|
|
61
|
+
export declare function getSpaceCalendarNote(dateStr: string, spaceId: string): Promise<Note | null>;
|
|
77
62
|
//# sourceMappingURL=sqlite-reader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite-reader.d.ts","sourceRoot":"","sources":["../../src/noteplan/sqlite-reader.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAoC,MAAM,YAAY,CAAC;AAEnF,OAAO,EAAqB,cAAc,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"sqlite-reader.d.ts","sourceRoot":"","sources":["../../src/noteplan/sqlite-reader.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAoC,MAAM,YAAY,CAAC;AAEnF,OAAO,EAAqB,cAAc,EAAE,MAAM,oBAAoB,CAAC;AA4CvE;;GAEG;AACH,wBAAgB,WAAW,IAAI,cAAc,GAAG,IAAI,CAgCnD;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAI/C;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAKpC;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC,CAgDnD;AA2BD,wBAAsB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CAiCpH;AA6ID,wBAAsB,cAAc,CAClC,gBAAgB,CAAC,EAAE,MAAM,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,GACvE,OAAO,CAAC,IAAI,EAAE,CAAC,CAuCjB;AAED,wBAAsB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CA+B3E;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,MAAM,EAChB,YAAY,UAAQ,GACnB,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CA4CtB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;IACP,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,OAAO,CAAC;CACnB,GACL,IAAI,EAAE,CAyCR;AAWD;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAAO,GACzE,OAAO,CAAC,IAAI,EAAE,CAAC,CAyDjB;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,gBAAgB,CAAC,EAAE,MAAM,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,GACvE,OAAO,CAAC,MAAM,EAAE,CAAC,CAoDnB;AAED,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAO,GACvC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAkBxB;AAED,wBAAsB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CA0C7E;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAW1E;AAED,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CA0CjG"}
|