@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.
Files changed (164) hide show
  1. package/README.md +7 -0
  2. package/dist/index.js +6 -0
  3. package/dist/index.js.map +1 -1
  4. package/dist/noteplan/attachments-paths.d.ts +13 -0
  5. package/dist/noteplan/attachments-paths.d.ts.map +1 -0
  6. package/dist/noteplan/attachments-paths.js +27 -0
  7. package/dist/noteplan/attachments-paths.js.map +1 -0
  8. package/dist/noteplan/embeddings.js +1 -1
  9. package/dist/noteplan/embeddings.js.map +1 -1
  10. package/dist/noteplan/file-reader.d.ts +37 -46
  11. package/dist/noteplan/file-reader.d.ts.map +1 -1
  12. package/dist/noteplan/file-reader.js +200 -202
  13. package/dist/noteplan/file-reader.js.map +1 -1
  14. package/dist/noteplan/file-reader.test.d.ts +2 -0
  15. package/dist/noteplan/file-reader.test.d.ts.map +1 -0
  16. package/dist/noteplan/file-reader.test.js +67 -0
  17. package/dist/noteplan/file-reader.test.js.map +1 -0
  18. package/dist/noteplan/file-writer.d.ts +35 -31
  19. package/dist/noteplan/file-writer.d.ts.map +1 -1
  20. package/dist/noteplan/file-writer.js +280 -164
  21. package/dist/noteplan/file-writer.js.map +1 -1
  22. package/dist/noteplan/file-writer.test.js +704 -191
  23. package/dist/noteplan/file-writer.test.js.map +1 -1
  24. package/dist/noteplan/filter-store.d.ts +5 -5
  25. package/dist/noteplan/filter-store.d.ts.map +1 -1
  26. package/dist/noteplan/filter-store.js +94 -79
  27. package/dist/noteplan/filter-store.js.map +1 -1
  28. package/dist/noteplan/ripgrep-search.d.ts +25 -2
  29. package/dist/noteplan/ripgrep-search.d.ts.map +1 -1
  30. package/dist/noteplan/ripgrep-search.js +75 -2
  31. package/dist/noteplan/ripgrep-search.js.map +1 -1
  32. package/dist/noteplan/space-row-utils.d.ts +20 -0
  33. package/dist/noteplan/space-row-utils.d.ts.map +1 -0
  34. package/dist/noteplan/space-row-utils.js +78 -0
  35. package/dist/noteplan/space-row-utils.js.map +1 -0
  36. package/dist/noteplan/space-row-utils.test.d.ts +2 -0
  37. package/dist/noteplan/space-row-utils.test.d.ts.map +1 -0
  38. package/dist/noteplan/space-row-utils.test.js +123 -0
  39. package/dist/noteplan/space-row-utils.test.js.map +1 -0
  40. package/dist/noteplan/sqlite-reader.d.ts +12 -27
  41. package/dist/noteplan/sqlite-reader.d.ts.map +1 -1
  42. package/dist/noteplan/sqlite-reader.js +315 -221
  43. package/dist/noteplan/sqlite-reader.js.map +1 -1
  44. package/dist/noteplan/sqlite-writer.d.ts +1 -1
  45. package/dist/noteplan/sqlite-writer.d.ts.map +1 -1
  46. package/dist/noteplan/sqlite-writer.js +2 -2
  47. package/dist/noteplan/sqlite-writer.js.map +1 -1
  48. package/dist/noteplan/unified-store.d.ts +41 -30
  49. package/dist/noteplan/unified-store.d.ts.map +1 -1
  50. package/dist/noteplan/unified-store.js +257 -159
  51. package/dist/noteplan/unified-store.js.map +1 -1
  52. package/dist/server.d.ts.map +1 -1
  53. package/dist/server.js +142 -61
  54. package/dist/server.js.map +1 -1
  55. package/dist/tools/attachments.d.ts +9 -9
  56. package/dist/tools/attachments.d.ts.map +1 -1
  57. package/dist/tools/attachments.js +74 -83
  58. package/dist/tools/attachments.js.map +1 -1
  59. package/dist/tools/attachments.test.js +170 -129
  60. package/dist/tools/attachments.test.js.map +1 -1
  61. package/dist/tools/calendar.d.ts +16 -13
  62. package/dist/tools/calendar.d.ts.map +1 -1
  63. package/dist/tools/calendar.js +17 -16
  64. package/dist/tools/calendar.js.map +1 -1
  65. package/dist/tools/embeddings.d.ts +6 -6
  66. package/dist/tools/embeddings.d.ts.map +1 -1
  67. package/dist/tools/embeddings.js +6 -6
  68. package/dist/tools/embeddings.js.map +1 -1
  69. package/dist/tools/events.d.ts +7 -3
  70. package/dist/tools/events.d.ts.map +1 -1
  71. package/dist/tools/events.js +51 -16
  72. package/dist/tools/events.js.map +1 -1
  73. package/dist/tools/filters.d.ts +28 -33
  74. package/dist/tools/filters.d.ts.map +1 -1
  75. package/dist/tools/filters.js +42 -105
  76. package/dist/tools/filters.js.map +1 -1
  77. package/dist/tools/notes.d.ts +80 -218
  78. package/dist/tools/notes.d.ts.map +1 -1
  79. package/dist/tools/notes.js +180 -177
  80. package/dist/tools/notes.js.map +1 -1
  81. package/dist/tools/notes.test.js +242 -21
  82. package/dist/tools/notes.test.js.map +1 -1
  83. package/dist/tools/search.d.ts +4 -3
  84. package/dist/tools/search.d.ts.map +1 -1
  85. package/dist/tools/search.js +9 -5
  86. package/dist/tools/search.js.map +1 -1
  87. package/dist/tools/search.test.d.ts +2 -0
  88. package/dist/tools/search.test.d.ts.map +1 -0
  89. package/dist/tools/search.test.js +37 -0
  90. package/dist/tools/search.test.js.map +1 -0
  91. package/dist/tools/spaces.d.ts +20 -20
  92. package/dist/tools/spaces.d.ts.map +1 -1
  93. package/dist/tools/spaces.js +28 -28
  94. package/dist/tools/spaces.js.map +1 -1
  95. package/dist/tools/tasks.d.ts +22 -22
  96. package/dist/tools/tasks.d.ts.map +1 -1
  97. package/dist/tools/tasks.js +22 -22
  98. package/dist/tools/tasks.js.map +1 -1
  99. package/dist/tools/templates.d.ts +7 -7
  100. package/dist/tools/templates.d.ts.map +1 -1
  101. package/dist/tools/templates.js +4 -4
  102. package/dist/tools/templates.js.map +1 -1
  103. package/dist/tools/themes.js +1 -1
  104. package/dist/tools/themes.js.map +1 -1
  105. package/dist/transport/bridge-availability.d.ts +5 -0
  106. package/dist/transport/bridge-availability.d.ts.map +1 -0
  107. package/dist/transport/bridge-availability.js +92 -0
  108. package/dist/transport/bridge-availability.js.map +1 -0
  109. package/dist/transport/bridge-cascade.d.ts +18 -0
  110. package/dist/transport/bridge-cascade.d.ts.map +1 -0
  111. package/dist/transport/bridge-cascade.js +78 -0
  112. package/dist/transport/bridge-cascade.js.map +1 -0
  113. package/dist/transport/bridge-cascade.test.d.ts +2 -0
  114. package/dist/transport/bridge-cascade.test.d.ts.map +1 -0
  115. package/dist/transport/bridge-cascade.test.js +160 -0
  116. package/dist/transport/bridge-cascade.test.js.map +1 -0
  117. package/dist/transport/bridge-client.d.ts +197 -0
  118. package/dist/transport/bridge-client.d.ts.map +1 -0
  119. package/dist/transport/bridge-client.js +288 -0
  120. package/dist/transport/bridge-client.js.map +1 -0
  121. package/dist/transport/bridge-client.test.d.ts +2 -0
  122. package/dist/transport/bridge-client.test.d.ts.map +1 -0
  123. package/dist/transport/bridge-client.test.js +384 -0
  124. package/dist/transport/bridge-client.test.js.map +1 -0
  125. package/dist/transport/bridge-context.d.ts +10 -0
  126. package/dist/transport/bridge-context.d.ts.map +1 -0
  127. package/dist/transport/bridge-context.js +18 -0
  128. package/dist/transport/bridge-context.js.map +1 -0
  129. package/dist/transport/bridge-fs.d.ts +25 -0
  130. package/dist/transport/bridge-fs.d.ts.map +1 -0
  131. package/dist/transport/bridge-fs.js +129 -0
  132. package/dist/transport/bridge-fs.js.map +1 -0
  133. package/dist/utils/date-utils.d.ts +24 -0
  134. package/dist/utils/date-utils.d.ts.map +1 -1
  135. package/dist/utils/date-utils.js +55 -0
  136. package/dist/utils/date-utils.js.map +1 -1
  137. package/dist/utils/date-utils.test.d.ts +2 -0
  138. package/dist/utils/date-utils.test.d.ts.map +1 -0
  139. package/dist/utils/date-utils.test.js +109 -0
  140. package/dist/utils/date-utils.test.js.map +1 -0
  141. package/dist/utils/folder-access.d.ts +23 -0
  142. package/dist/utils/folder-access.d.ts.map +1 -0
  143. package/dist/utils/folder-access.js +131 -0
  144. package/dist/utils/folder-access.js.map +1 -0
  145. package/dist/utils/folder-access.test.d.ts +2 -0
  146. package/dist/utils/folder-access.test.d.ts.map +1 -0
  147. package/dist/utils/folder-access.test.js +182 -0
  148. package/dist/utils/folder-access.test.js.map +1 -0
  149. package/dist/utils/folder-matcher.d.ts.map +1 -1
  150. package/dist/utils/folder-matcher.js +16 -0
  151. package/dist/utils/folder-matcher.js.map +1 -1
  152. package/dist/utils/folder-matcher.test.js +42 -0
  153. package/dist/utils/folder-matcher.test.js.map +1 -1
  154. package/dist/utils/server-config.d.ts +10 -2
  155. package/dist/utils/server-config.d.ts.map +1 -1
  156. package/dist/utils/server-config.js +16 -2
  157. package/dist/utils/server-config.js.map +1 -1
  158. package/dist/utils/version.d.ts +2 -0
  159. package/dist/utils/version.d.ts.map +1 -1
  160. package/dist/utils/version.js +5 -1
  161. package/dist/utils/version.js.map +1 -1
  162. package/package.json +4 -3
  163. package/scripts/calendar-helper +0 -0
  164. package/scripts/reminders-helper +0 -0
@@ -76,6 +76,30 @@ export declare function isCalendarNoteFilename(filename: string): boolean;
76
76
  * Extract date from calendar note filename
77
77
  */
78
78
  export declare function extractDateFromFilename(filename: string): string | null;
79
+ /**
80
+ * Normalize a periodic-note title to NotePlan's on-disk filename form.
81
+ *
82
+ * Returns the normalized identifier (e.g. `2026-W04`, `2026-05`,
83
+ * `2026-Q2`, `20260411`, `2026`) or `null` if `input` doesn't look
84
+ * like a periodic note. Sloppy inputs are quietly canonicalized:
85
+ * - `2026-W4` → `2026-W04`
86
+ * - `2026-w16` → `2026-W16`
87
+ * - `2026-5` → `2026-05`
88
+ * - `2026-q2` → `2026-Q2`
89
+ * - `2026-04-11` → `20260411`
90
+ * NotePlan only recognizes the canonical forms; anything else creates
91
+ * a file the app can't open as a periodic note.
92
+ */
93
+ export declare function normalizePeriodicTitle(input: string): string | null;
94
+ /** True if `input` looks like any periodic-note identifier. */
95
+ export declare function isPeriodicCalendarTitle(input: string): boolean;
96
+ /**
97
+ * True only when `input` is *already* in NotePlan's canonical periodic
98
+ * form — i.e. `normalizePeriodicTitle` returns it unchanged. Used to
99
+ * distinguish unambiguous calendar intent (`title: "2026-W16"`) from
100
+ * sloppy variants (`title: "2026-W4"`) that need an explicit signal.
101
+ */
102
+ export declare function isCanonicalPeriodicTitle(input: string): boolean;
79
103
  /**
80
104
  * Calendar note types
81
105
  */
@@ -1 +1 @@
1
- {"version":3,"file":"date-utils.d.ts","sourceRoot":"","sources":["../../src/utils/date-utils.ts"],"names":[],"mappings":"AAkBA;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAG3C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAKnD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAM5D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAG3D;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAKpD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAMhD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAKjD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAKrE;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,IAAI,EACV,cAAc,EAAE,MAAM,GACrB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAmDhC;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,IAAI,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAGtF;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiCvD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAU5D;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAGhE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAsBvE;AAED;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;AAEvF;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAO7E;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,iBAAiB,GAAE,OAAc,GAAG,MAAM,CAKxF;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,EAAE,iBAAiB,GAAE,OAAc,GAAG,MAAM,CAK1F;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,iBAAiB,GAAE,OAAc,GAAG,MAAM,CAIvF;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,OAAO,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,GAAG,YAAY,GAAG,YAAY,GAAG,MAAM,EAChG,WAAW,CAAC,EAAE,MAAM,EACpB,SAAS,CAAC,EAAE,MAAM,GACjB;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,IAAI,CAAA;CAAE,CAsD5B;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,GAAG,IAAI,EAAE,CAU9D"}
1
+ {"version":3,"file":"date-utils.d.ts","sourceRoot":"","sources":["../../src/utils/date-utils.ts"],"names":[],"mappings":"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"}
@@ -230,6 +230,61 @@ export function extractDateFromFilename(filename) {
230
230
  return yearlyMatch[1];
231
231
  return null;
232
232
  }
233
+ /**
234
+ * Normalize a periodic-note title to NotePlan's on-disk filename form.
235
+ *
236
+ * Returns the normalized identifier (e.g. `2026-W04`, `2026-05`,
237
+ * `2026-Q2`, `20260411`, `2026`) or `null` if `input` doesn't look
238
+ * like a periodic note. Sloppy inputs are quietly canonicalized:
239
+ * - `2026-W4` → `2026-W04`
240
+ * - `2026-w16` → `2026-W16`
241
+ * - `2026-5` → `2026-05`
242
+ * - `2026-q2` → `2026-Q2`
243
+ * - `2026-04-11` → `20260411`
244
+ * NotePlan only recognizes the canonical forms; anything else creates
245
+ * a file the app can't open as a periodic note.
246
+ */
247
+ export function normalizePeriodicTitle(input) {
248
+ const trimmed = input.trim();
249
+ if (!trimmed)
250
+ return null;
251
+ // Daily: YYYYMMDD
252
+ if (/^\d{8}$/.test(trimmed))
253
+ return trimmed;
254
+ // Daily: YYYY-MM-DD → YYYYMMDD
255
+ const isoDaily = trimmed.match(/^(\d{4})-(\d{2})-(\d{2})$/);
256
+ if (isoDaily)
257
+ return `${isoDaily[1]}${isoDaily[2]}${isoDaily[3]}`;
258
+ // Weekly: YYYY-Www (1–2 digit week, any case)
259
+ const weekly = trimmed.match(/^(\d{4})-[Ww](\d{1,2})$/);
260
+ if (weekly)
261
+ return `${weekly[1]}-W${weekly[2].padStart(2, '0')}`;
262
+ // Monthly: YYYY-M or YYYY-MM
263
+ const monthly = trimmed.match(/^(\d{4})-(\d{1,2})$/);
264
+ if (monthly)
265
+ return `${monthly[1]}-${monthly[2].padStart(2, '0')}`;
266
+ // Quarterly: YYYY-Qn (1–4)
267
+ const quarterly = trimmed.match(/^(\d{4})-[Qq]([1-4])$/);
268
+ if (quarterly)
269
+ return `${quarterly[1]}-Q${quarterly[2]}`;
270
+ // Yearly: YYYY
271
+ if (/^\d{4}$/.test(trimmed))
272
+ return trimmed;
273
+ return null;
274
+ }
275
+ /** True if `input` looks like any periodic-note identifier. */
276
+ export function isPeriodicCalendarTitle(input) {
277
+ return normalizePeriodicTitle(input) !== null;
278
+ }
279
+ /**
280
+ * True only when `input` is *already* in NotePlan's canonical periodic
281
+ * form — i.e. `normalizePeriodicTitle` returns it unchanged. Used to
282
+ * distinguish unambiguous calendar intent (`title: "2026-W16"`) from
283
+ * sloppy variants (`title: "2026-W4"`) that need an explicit signal.
284
+ */
285
+ export function isCanonicalPeriodicTitle(input) {
286
+ return normalizePeriodicTitle(input) === input;
287
+ }
233
288
  /**
234
289
  * Get the type of calendar note from its filename
235
290
  */
@@ -1 +1 @@
1
- {"version":3,"file":"date-utils.js","sourceRoot":"","sources":["../../src/utils/date-utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"date-utils.js","sourceRoot":"","sources":["../../src/utils/date-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=date-utils.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date-utils.test.d.ts","sourceRoot":"","sources":["../../src/utils/date-utils.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,109 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { normalizePeriodicTitle, isPeriodicCalendarTitle, isCanonicalPeriodicTitle } from './date-utils.js';
3
+ describe('normalizePeriodicTitle', () => {
4
+ describe('daily', () => {
5
+ it('keeps already-canonical YYYYMMDD as-is', () => {
6
+ expect(normalizePeriodicTitle('20260507')).toBe('20260507');
7
+ });
8
+ it('normalizes YYYY-MM-DD to YYYYMMDD', () => {
9
+ expect(normalizePeriodicTitle('2026-05-07')).toBe('20260507');
10
+ });
11
+ it('rejects sloppy daily formats (would clobber other matches)', () => {
12
+ // 2026-5-7 is ambiguous (could be partial monthly + day suffix). Reject
13
+ // to keep the rule "either YYYY-MM-DD or YYYYMMDD" predictable.
14
+ expect(normalizePeriodicTitle('2026-5-7')).toBeNull();
15
+ });
16
+ });
17
+ describe('weekly', () => {
18
+ it('zero-pads single-digit weeks', () => {
19
+ expect(normalizePeriodicTitle('2026-W4')).toBe('2026-W04');
20
+ });
21
+ it('uppercases lowercase w', () => {
22
+ expect(normalizePeriodicTitle('2026-w16')).toBe('2026-W16');
23
+ });
24
+ it('keeps double-digit weeks intact', () => {
25
+ expect(normalizePeriodicTitle('2026-W16')).toBe('2026-W16');
26
+ });
27
+ });
28
+ describe('monthly', () => {
29
+ it('zero-pads single-digit months', () => {
30
+ expect(normalizePeriodicTitle('2026-5')).toBe('2026-05');
31
+ });
32
+ it('keeps double-digit months intact', () => {
33
+ expect(normalizePeriodicTitle('2026-05')).toBe('2026-05');
34
+ });
35
+ });
36
+ describe('quarterly', () => {
37
+ it('uppercases lowercase q', () => {
38
+ expect(normalizePeriodicTitle('2026-q2')).toBe('2026-Q2');
39
+ });
40
+ it('keeps Q2 intact', () => {
41
+ expect(normalizePeriodicTitle('2026-Q2')).toBe('2026-Q2');
42
+ });
43
+ it('rejects out-of-range quarters', () => {
44
+ expect(normalizePeriodicTitle('2026-Q5')).toBeNull();
45
+ expect(normalizePeriodicTitle('2026-Q0')).toBeNull();
46
+ });
47
+ });
48
+ describe('yearly', () => {
49
+ it('keeps YYYY as-is', () => {
50
+ expect(normalizePeriodicTitle('2026')).toBe('2026');
51
+ });
52
+ });
53
+ describe('non-periodic', () => {
54
+ it('returns null for project-note titles', () => {
55
+ expect(normalizePeriodicTitle('My Plan for Q2')).toBeNull();
56
+ expect(normalizePeriodicTitle('Untitled')).toBeNull();
57
+ });
58
+ it('returns null for empty / whitespace', () => {
59
+ expect(normalizePeriodicTitle('')).toBeNull();
60
+ expect(normalizePeriodicTitle(' ')).toBeNull();
61
+ });
62
+ it('returns null for short year-like strings', () => {
63
+ expect(normalizePeriodicTitle('202')).toBeNull();
64
+ });
65
+ });
66
+ describe('whitespace tolerance', () => {
67
+ it('trims surrounding whitespace before matching', () => {
68
+ expect(normalizePeriodicTitle(' 2026-W4 ')).toBe('2026-W04');
69
+ });
70
+ });
71
+ });
72
+ describe('isPeriodicCalendarTitle', () => {
73
+ it('matches every canonical form', () => {
74
+ expect(isPeriodicCalendarTitle('20260507')).toBe(true);
75
+ expect(isPeriodicCalendarTitle('2026-05-07')).toBe(true);
76
+ expect(isPeriodicCalendarTitle('2026-W04')).toBe(true);
77
+ expect(isPeriodicCalendarTitle('2026-05')).toBe(true);
78
+ expect(isPeriodicCalendarTitle('2026-Q2')).toBe(true);
79
+ expect(isPeriodicCalendarTitle('2026')).toBe(true);
80
+ });
81
+ it('matches sloppy variants too', () => {
82
+ expect(isPeriodicCalendarTitle('2026-W4')).toBe(true);
83
+ expect(isPeriodicCalendarTitle('2026-q2')).toBe(true);
84
+ expect(isPeriodicCalendarTitle('2026-5')).toBe(true);
85
+ });
86
+ it('rejects project-note titles', () => {
87
+ expect(isPeriodicCalendarTitle('My Project')).toBe(false);
88
+ });
89
+ });
90
+ describe('isCanonicalPeriodicTitle', () => {
91
+ it('returns true only for already-canonical forms', () => {
92
+ expect(isCanonicalPeriodicTitle('2026-W16')).toBe(true);
93
+ expect(isCanonicalPeriodicTitle('20260507')).toBe(true);
94
+ expect(isCanonicalPeriodicTitle('2026-05')).toBe(true);
95
+ expect(isCanonicalPeriodicTitle('2026-Q2')).toBe(true);
96
+ expect(isCanonicalPeriodicTitle('2026')).toBe(true);
97
+ });
98
+ it('returns false for sloppy variants — these need an explicit calendar signal', () => {
99
+ expect(isCanonicalPeriodicTitle('2026-W4')).toBe(false);
100
+ expect(isCanonicalPeriodicTitle('2026-q2')).toBe(false);
101
+ expect(isCanonicalPeriodicTitle('2026-5')).toBe(false);
102
+ expect(isCanonicalPeriodicTitle('2026-05-07')).toBe(false); // normalizes to YYYYMMDD
103
+ });
104
+ it('returns false for non-periodic strings', () => {
105
+ expect(isCanonicalPeriodicTitle('My Project')).toBe(false);
106
+ expect(isCanonicalPeriodicTitle('')).toBe(false);
107
+ });
108
+ });
109
+ //# sourceMappingURL=date-utils.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date-utils.test.js","sourceRoot":"","sources":["../../src/utils/date-utils.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /** Test-only: drop the cache so a subsequent call re-reads `process.env`. */
2
+ export declare function __resetFolderAccessConfigForTests(): void;
3
+ /**
4
+ * True when configured allow/deny rules permit access to `relativePath`.
5
+ * Folder or file path; same prefix logic. With no rules configured this
6
+ * always returns true so callers can use it unconditionally.
7
+ */
8
+ export declare function isFolderAllowed(relativePath: string): boolean;
9
+ /**
10
+ * True when ANY allow/deny rule is configured. Lets aggregating callers
11
+ * (e.g. `listTags`, which has no per-file path to filter on) pick a fast
12
+ * unfiltered path when no rules are set and a slower per-note walk when
13
+ * they are.
14
+ */
15
+ export declare function hasFolderAccessRules(): boolean;
16
+ /**
17
+ * Throw a clear error when a write operation targets a blocked folder.
18
+ * Use at the top of mutating store / file-writer entry points so agents
19
+ * see a diagnostic instead of an opaque permission error or, worse, a
20
+ * silent half-completed write.
21
+ */
22
+ export declare function assertFolderAllowed(relativePath: string, action: string): void;
23
+ //# sourceMappingURL=folder-access.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folder-access.d.ts","sourceRoot":"","sources":["../../src/utils/folder-access.ts"],"names":[],"mappings":"AAuEA,6EAA6E;AAC7E,wBAAgB,iCAAiC,IAAI,IAAI,CAExD;AAoCD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAG9C;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAO9E"}
@@ -0,0 +1,131 @@
1
+ // Folder-level access control for the MCP server.
2
+ //
3
+ // Two env vars, each comma-separated, configured by the user in their MCP
4
+ // client's JSON config. Both default to empty → no filtering, fully
5
+ // backwards-compatible.
6
+ //
7
+ // NOTEPLAN_ALLOWED_FOLDERS Allowlist. When set, a path must sit
8
+ // inside one of the listed prefixes to be
9
+ // accessible.
10
+ // NOTEPLAN_DENIED_FOLDERS Denylist. Any path inside one of the
11
+ // listed prefixes is blocked outright,
12
+ // even if it also matches the allowlist.
13
+ //
14
+ // Matching is by path-prefix on the relative path inside the NotePlan
15
+ // storage root (e.g. `Notes/Personal/Finance` matches the file
16
+ // `Notes/Personal/Finance/2026.txt` and the folder itself, but NOT
17
+ // `Notes/PersonalRecords.txt`). The denylist always wins.
18
+ //
19
+ // Read operations (list, get, search) filter denied paths out of the
20
+ // response. Write operations (create, update, delete, move, rename,
21
+ // restore) reject with a clear error so the agent knows it hit a
22
+ // configured boundary instead of silently misbehaving.
23
+ const ALLOWED_ENV_KEY = 'NOTEPLAN_ALLOWED_FOLDERS';
24
+ const DENIED_ENV_KEY = 'NOTEPLAN_DENIED_FOLDERS';
25
+ let cached = null;
26
+ function parseList(raw) {
27
+ if (!raw)
28
+ return [];
29
+ return raw
30
+ .split(',')
31
+ .map((entry) => applyTopLevelSugar(normalizePathInput(entry)))
32
+ .filter((entry) => entry.length > 0);
33
+ }
34
+ function normalizePathInput(input) {
35
+ // Strip surrounding whitespace, collapse backslashes to slashes, and
36
+ // trim leading / trailing slashes so users can be sloppy with how
37
+ // they write the prefixes (`Notes/Foo`, `/Notes/Foo/`, `Notes\Foo`).
38
+ return input.trim().replace(/\\/g, '/').replace(/^\/+|\/+$/g, '');
39
+ }
40
+ /**
41
+ * Treat a bare entry like `Personal` as sugar for `Notes/Personal` — the
42
+ * filesystem layout puts every project note under `Notes/`, and most
43
+ * users won't think to type that prefix. `Notes/...` and the reserved
44
+ * top-level `Calendar` are passed through unchanged. Applied at config
45
+ * parse time so the rest of the matcher stays oblivious.
46
+ */
47
+ function applyTopLevelSugar(entry) {
48
+ if (!entry)
49
+ return entry;
50
+ if (entry === 'Notes' || entry.startsWith('Notes/'))
51
+ return entry;
52
+ if (entry === 'Calendar' || entry.startsWith('Calendar/'))
53
+ return entry;
54
+ return `Notes/${entry}`;
55
+ }
56
+ function loadConfig() {
57
+ if (cached)
58
+ return cached;
59
+ cached = {
60
+ allowed: parseList(process.env[ALLOWED_ENV_KEY]),
61
+ denied: parseList(process.env[DENIED_ENV_KEY]),
62
+ };
63
+ return cached;
64
+ }
65
+ /** Test-only: drop the cache so a subsequent call re-reads `process.env`. */
66
+ export function __resetFolderAccessConfigForTests() {
67
+ cached = null;
68
+ }
69
+ /**
70
+ * True when `prefix` and `candidate` denote the same path or `candidate`
71
+ * sits strictly inside `prefix`. Boundary-aware so `Notes/Foo` does NOT
72
+ * match `Notes/FooBar`.
73
+ */
74
+ function pathStartsWithPrefix(prefix, candidate) {
75
+ if (candidate === prefix)
76
+ return true;
77
+ return candidate.startsWith(`${prefix}/`);
78
+ }
79
+ /**
80
+ * Single evaluation pass that powers both `isFolderAllowed` (boolean) and
81
+ * `assertFolderAllowed` (throws with a categorized reason). Short-circuits
82
+ * before normalization when no rules are configured, so the no-rules case
83
+ * pays nothing and callers don't need a separate "rules enabled?" guard.
84
+ */
85
+ function evaluateFolderAccess(relativePath) {
86
+ const { allowed, denied } = loadConfig();
87
+ if (allowed.length === 0 && denied.length === 0)
88
+ return { allowed: true };
89
+ const normalized = normalizePathInput(relativePath);
90
+ if (denied.some((prefix) => pathStartsWithPrefix(prefix, normalized))) {
91
+ return { allowed: false, reason: 'denied' };
92
+ }
93
+ if (allowed.length > 0 && !allowed.some((prefix) => pathStartsWithPrefix(prefix, normalized))) {
94
+ return { allowed: false, reason: 'not-allowed' };
95
+ }
96
+ return { allowed: true };
97
+ }
98
+ /**
99
+ * True when configured allow/deny rules permit access to `relativePath`.
100
+ * Folder or file path; same prefix logic. With no rules configured this
101
+ * always returns true so callers can use it unconditionally.
102
+ */
103
+ export function isFolderAllowed(relativePath) {
104
+ return evaluateFolderAccess(relativePath).allowed;
105
+ }
106
+ /**
107
+ * True when ANY allow/deny rule is configured. Lets aggregating callers
108
+ * (e.g. `listTags`, which has no per-file path to filter on) pick a fast
109
+ * unfiltered path when no rules are set and a slower per-note walk when
110
+ * they are.
111
+ */
112
+ export function hasFolderAccessRules() {
113
+ const { allowed, denied } = loadConfig();
114
+ return allowed.length > 0 || denied.length > 0;
115
+ }
116
+ /**
117
+ * Throw a clear error when a write operation targets a blocked folder.
118
+ * Use at the top of mutating store / file-writer entry points so agents
119
+ * see a diagnostic instead of an opaque permission error or, worse, a
120
+ * silent half-completed write.
121
+ */
122
+ export function assertFolderAllowed(relativePath, action) {
123
+ const verdict = evaluateFolderAccess(relativePath);
124
+ if (verdict.allowed)
125
+ return;
126
+ const reason = verdict.reason === 'denied'
127
+ ? `it is inside a folder listed in ${DENIED_ENV_KEY}`
128
+ : `it is not inside any folder listed in ${ALLOWED_ENV_KEY}`;
129
+ throw new Error(`Cannot ${action} "${relativePath}": ${reason}.`);
130
+ }
131
+ //# sourceMappingURL=folder-access.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folder-access.js","sourceRoot":"","sources":["../../src/utils/folder-access.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=folder-access.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folder-access.test.d.ts","sourceRoot":"","sources":["../../src/utils/folder-access.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,182 @@
1
+ import { describe, expect, it, beforeEach, afterEach } from 'vitest';
2
+ import { isFolderAllowed, assertFolderAllowed, __resetFolderAccessConfigForTests, } from './folder-access.js';
3
+ const ALLOWED = 'NOTEPLAN_ALLOWED_FOLDERS';
4
+ const DENIED = 'NOTEPLAN_DENIED_FOLDERS';
5
+ function withEnv(env, fn) {
6
+ const before = {};
7
+ for (const key of Object.keys(env))
8
+ before[key] = process.env[key];
9
+ for (const [key, value] of Object.entries(env)) {
10
+ if (value === undefined)
11
+ delete process.env[key];
12
+ else
13
+ process.env[key] = value;
14
+ }
15
+ __resetFolderAccessConfigForTests();
16
+ try {
17
+ fn();
18
+ }
19
+ finally {
20
+ for (const [key, prev] of Object.entries(before)) {
21
+ if (prev === undefined)
22
+ delete process.env[key];
23
+ else
24
+ process.env[key] = prev;
25
+ }
26
+ __resetFolderAccessConfigForTests();
27
+ }
28
+ }
29
+ beforeEach(() => {
30
+ delete process.env[ALLOWED];
31
+ delete process.env[DENIED];
32
+ __resetFolderAccessConfigForTests();
33
+ });
34
+ afterEach(() => {
35
+ delete process.env[ALLOWED];
36
+ delete process.env[DENIED];
37
+ __resetFolderAccessConfigForTests();
38
+ });
39
+ describe('isFolderAllowed — defaults', () => {
40
+ it('allows everything when neither env var is set (back-compat)', () => {
41
+ expect(isFolderAllowed('Notes/Personal/Diary.md')).toBe(true);
42
+ expect(isFolderAllowed('Calendar/20260507.txt')).toBe(true);
43
+ expect(isFolderAllowed('')).toBe(true);
44
+ });
45
+ // No-rules guarantee: the helpers must short-circuit BEFORE any normalization,
46
+ // sugaring, or other work runs. Unsetting the vars again restores the no-op
47
+ // behavior — the cached config is keyed off env-var presence.
48
+ it('assertFolderAllowed never throws when no rules are configured', () => {
49
+ expect(() => assertFolderAllowed('Notes/Personal/Diary.md', 'create')).not.toThrow();
50
+ expect(() => assertFolderAllowed('Calendar/20260507.txt', 'delete')).not.toThrow();
51
+ expect(() => assertFolderAllowed('Anything/At/All.md', 'move')).not.toThrow();
52
+ });
53
+ });
54
+ describe('isFolderAllowed — denylist', () => {
55
+ it('blocks files inside a denied folder', () => {
56
+ withEnv({ [DENIED]: 'Notes/Personal' }, () => {
57
+ expect(isFolderAllowed('Notes/Personal/Diary.md')).toBe(false);
58
+ expect(isFolderAllowed('Notes/Personal')).toBe(false);
59
+ });
60
+ });
61
+ it('allows siblings outside the denied folder', () => {
62
+ withEnv({ [DENIED]: 'Notes/Personal' }, () => {
63
+ expect(isFolderAllowed('Notes/Work/Plan.md')).toBe(true);
64
+ expect(isFolderAllowed('Calendar/20260507.txt')).toBe(true);
65
+ });
66
+ });
67
+ it('does NOT match folder names that share a prefix without a path boundary', () => {
68
+ // Notes/Personal must not match Notes/PersonalRecords.
69
+ withEnv({ [DENIED]: 'Notes/Personal' }, () => {
70
+ expect(isFolderAllowed('Notes/PersonalRecords/index.md')).toBe(true);
71
+ expect(isFolderAllowed('Notes/PersonalRecords.md')).toBe(true);
72
+ });
73
+ });
74
+ it('supports multiple denied folders', () => {
75
+ withEnv({ [DENIED]: 'Notes/Personal, Notes/Finance, Calendar' }, () => {
76
+ expect(isFolderAllowed('Notes/Personal/Diary.md')).toBe(false);
77
+ expect(isFolderAllowed('Notes/Finance/Budget.md')).toBe(false);
78
+ expect(isFolderAllowed('Calendar/20260507.txt')).toBe(false);
79
+ expect(isFolderAllowed('Notes/Work/Plan.md')).toBe(true);
80
+ });
81
+ });
82
+ it('tolerates sloppy whitespace, slashes, and backslashes in the env value', () => {
83
+ withEnv({ [DENIED]: ' /Notes/Personal/ ,\\Notes\\Finance\\ ' }, () => {
84
+ expect(isFolderAllowed('Notes/Personal/Diary.md')).toBe(false);
85
+ expect(isFolderAllowed('Notes/Finance/Budget.md')).toBe(false);
86
+ });
87
+ });
88
+ });
89
+ describe('isFolderAllowed — allowlist', () => {
90
+ it('blocks paths outside the allowlist', () => {
91
+ withEnv({ [ALLOWED]: 'Notes/Work' }, () => {
92
+ expect(isFolderAllowed('Notes/Work/Plan.md')).toBe(true);
93
+ expect(isFolderAllowed('Notes/Personal/Diary.md')).toBe(false);
94
+ expect(isFolderAllowed('Calendar/20260507.txt')).toBe(false);
95
+ });
96
+ });
97
+ it('allows the listed root folder itself', () => {
98
+ withEnv({ [ALLOWED]: 'Notes/Work' }, () => {
99
+ expect(isFolderAllowed('Notes/Work')).toBe(true);
100
+ });
101
+ });
102
+ it('supports multiple allowed prefixes', () => {
103
+ withEnv({ [ALLOWED]: 'Notes/Work, Calendar' }, () => {
104
+ expect(isFolderAllowed('Notes/Work/Plan.md')).toBe(true);
105
+ expect(isFolderAllowed('Calendar/20260507.txt')).toBe(true);
106
+ expect(isFolderAllowed('Notes/Other/x.md')).toBe(false);
107
+ });
108
+ });
109
+ });
110
+ describe('isFolderAllowed — both lists', () => {
111
+ it('denylist wins over allowlist for overlapping paths', () => {
112
+ withEnv({ [ALLOWED]: 'Notes', [DENIED]: 'Notes/Personal' }, () => {
113
+ expect(isFolderAllowed('Notes/Work/Plan.md')).toBe(true);
114
+ expect(isFolderAllowed('Notes/Personal/Diary.md')).toBe(false);
115
+ });
116
+ });
117
+ });
118
+ describe('isFolderAllowed — top-level prefix sugar', () => {
119
+ // Most users don't think to type the `Notes/` prefix when configuring
120
+ // the env vars. A bare entry is treated as if it lived under `Notes/`.
121
+ // `Calendar` (and `Calendar/...`) are reserved top-levels and stay as-is.
122
+ it('treats a bare entry as Notes/<entry>', () => {
123
+ withEnv({ [DENIED]: 'Personal' }, () => {
124
+ expect(isFolderAllowed('Notes/Personal/Diary.md')).toBe(false);
125
+ expect(isFolderAllowed('Notes/Personal')).toBe(false);
126
+ expect(isFolderAllowed('Notes/Work/Plan.md')).toBe(true);
127
+ });
128
+ });
129
+ it('still respects the path-boundary rule after sugaring', () => {
130
+ withEnv({ [DENIED]: 'Personal' }, () => {
131
+ expect(isFolderAllowed('Notes/PersonalRecords.md')).toBe(true);
132
+ });
133
+ });
134
+ it('keeps Calendar as a reserved top-level (not sugared)', () => {
135
+ withEnv({ [DENIED]: 'Calendar' }, () => {
136
+ expect(isFolderAllowed('Calendar/20260507.txt')).toBe(false);
137
+ expect(isFolderAllowed('Notes/Calendar/note.md')).toBe(true);
138
+ });
139
+ });
140
+ it('mixes sugared and explicit entries in the same list', () => {
141
+ // `Calendar/2026` targets a yearFolders-mode subtree (NotePlan stores
142
+ // calendar files under year folders when that preference is enabled).
143
+ // The path-boundary rule means it matches `Calendar/2026/...` but not
144
+ // a flat `Calendar/20260507.txt`.
145
+ withEnv({ [DENIED]: 'Personal, Notes/Finance, Calendar/2026' }, () => {
146
+ expect(isFolderAllowed('Notes/Personal/Diary.md')).toBe(false);
147
+ expect(isFolderAllowed('Notes/Finance/Budget.md')).toBe(false);
148
+ expect(isFolderAllowed('Calendar/2026/20260507.txt')).toBe(false);
149
+ expect(isFolderAllowed('Calendar/2025/20250507.txt')).toBe(true);
150
+ expect(isFolderAllowed('Notes/Work/Plan.md')).toBe(true);
151
+ });
152
+ });
153
+ it('applies sugar to the allowlist too', () => {
154
+ withEnv({ [ALLOWED]: 'Work' }, () => {
155
+ expect(isFolderAllowed('Notes/Work/Plan.md')).toBe(true);
156
+ expect(isFolderAllowed('Notes/Personal/Diary.md')).toBe(false);
157
+ // Calendar is NOT allowed because the sugared allow rule is `Notes/Work`.
158
+ expect(isFolderAllowed('Calendar/20260507.txt')).toBe(false);
159
+ });
160
+ });
161
+ });
162
+ describe('assertFolderAllowed', () => {
163
+ it('returns silently when access is allowed', () => {
164
+ expect(() => assertFolderAllowed('Notes/Work/Plan.md', 'create')).not.toThrow();
165
+ });
166
+ it('throws with the deny env var name when blocked by the denylist', () => {
167
+ withEnv({ [DENIED]: 'Notes/Personal' }, () => {
168
+ expect(() => assertFolderAllowed('Notes/Personal/Diary.md', 'delete')).toThrowError(/NOTEPLAN_DENIED_FOLDERS/);
169
+ });
170
+ });
171
+ it('throws with the allow env var name when blocked by the allowlist', () => {
172
+ withEnv({ [ALLOWED]: 'Notes/Work' }, () => {
173
+ expect(() => assertFolderAllowed('Notes/Other/x.md', 'create')).toThrowError(/NOTEPLAN_ALLOWED_FOLDERS/);
174
+ });
175
+ });
176
+ it('mentions the action and the path in the error message', () => {
177
+ withEnv({ [DENIED]: 'Notes/Personal' }, () => {
178
+ expect(() => assertFolderAllowed('Notes/Personal/Diary.md', 'delete')).toThrowError(/Cannot delete "Notes\/Personal\/Diary\.md"/);
179
+ });
180
+ });
181
+ });
182
+ //# sourceMappingURL=folder-access.test.js.map