@atikk-co-jp/notion-mcp-server 0.1.0 → 0.2.1

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 (97) hide show
  1. package/README.ja.md +97 -6
  2. package/README.md +97 -6
  3. package/dist/bin/cli.js +10 -10
  4. package/dist/src/converters/__tests__/block-to-markdown.test.d.ts +2 -0
  5. package/dist/src/converters/__tests__/block-to-markdown.test.d.ts.map +1 -0
  6. package/dist/src/converters/__tests__/block-to-markdown.test.js +611 -0
  7. package/dist/src/converters/__tests__/page-to-markdown.test.d.ts +2 -0
  8. package/dist/src/converters/__tests__/page-to-markdown.test.d.ts.map +1 -0
  9. package/dist/src/converters/__tests__/page-to-markdown.test.js +567 -0
  10. package/dist/src/converters/__tests__/rich-text-to-markdown.test.d.ts +2 -0
  11. package/dist/src/converters/__tests__/rich-text-to-markdown.test.d.ts.map +1 -0
  12. package/dist/src/converters/__tests__/rich-text-to-markdown.test.js +353 -0
  13. package/dist/src/converters/block-to-markdown.d.ts +38 -0
  14. package/dist/src/converters/block-to-markdown.d.ts.map +1 -0
  15. package/dist/src/converters/block-to-markdown.js +484 -0
  16. package/dist/src/converters/index.d.ts +9 -0
  17. package/dist/src/converters/index.d.ts.map +1 -0
  18. package/dist/src/converters/index.js +11 -0
  19. package/dist/src/converters/page-to-markdown.d.ts +64 -0
  20. package/dist/src/converters/page-to-markdown.d.ts.map +1 -0
  21. package/dist/src/converters/page-to-markdown.js +189 -0
  22. package/dist/src/converters/rich-text-to-markdown.d.ts +61 -0
  23. package/dist/src/converters/rich-text-to-markdown.d.ts.map +1 -0
  24. package/dist/src/converters/rich-text-to-markdown.js +95 -0
  25. package/dist/src/index.d.ts +6 -6
  26. package/dist/src/index.d.ts.map +1 -1
  27. package/dist/src/index.js +5 -5
  28. package/dist/src/notion-client.d.ts +58 -15
  29. package/dist/src/notion-client.d.ts.map +1 -1
  30. package/dist/src/notion-client.js +23 -13
  31. package/dist/src/schemas/block.d.ts +2158 -622
  32. package/dist/src/schemas/block.d.ts.map +1 -1
  33. package/dist/src/schemas/block.js +283 -76
  34. package/dist/src/schemas/common.d.ts +518 -6
  35. package/dist/src/schemas/common.d.ts.map +1 -1
  36. package/dist/src/schemas/common.js +120 -42
  37. package/dist/src/schemas/database.d.ts +687 -0
  38. package/dist/src/schemas/database.d.ts.map +1 -0
  39. package/dist/src/schemas/database.js +264 -0
  40. package/dist/src/schemas/filter.d.ts +509 -3
  41. package/dist/src/schemas/filter.d.ts.map +1 -1
  42. package/dist/src/schemas/filter.js +110 -13
  43. package/dist/src/schemas/index.d.ts +5 -4
  44. package/dist/src/schemas/index.d.ts.map +1 -1
  45. package/dist/src/schemas/index.js +7 -5
  46. package/dist/src/schemas/page.d.ts +2152 -19
  47. package/dist/src/schemas/page.d.ts.map +1 -1
  48. package/dist/src/schemas/page.js +216 -22
  49. package/dist/src/schemas/schemas.test.d.ts +2 -0
  50. package/dist/src/schemas/schemas.test.d.ts.map +1 -0
  51. package/dist/src/schemas/schemas.test.js +418 -0
  52. package/dist/src/server.d.ts +2 -2
  53. package/dist/src/server.d.ts.map +1 -1
  54. package/dist/src/server.js +6 -6
  55. package/dist/src/tools/append-block-children.d.ts +2 -2
  56. package/dist/src/tools/append-block-children.d.ts.map +1 -1
  57. package/dist/src/tools/append-block-children.js +16 -10
  58. package/dist/src/tools/create-comment.d.ts +2 -2
  59. package/dist/src/tools/create-comment.d.ts.map +1 -1
  60. package/dist/src/tools/create-comment.js +15 -9
  61. package/dist/src/tools/create-database.d.ts +4 -0
  62. package/dist/src/tools/create-database.d.ts.map +1 -0
  63. package/dist/src/tools/create-database.js +57 -0
  64. package/dist/src/tools/create-page.d.ts +2 -2
  65. package/dist/src/tools/create-page.d.ts.map +1 -1
  66. package/dist/src/tools/create-page.js +22 -24
  67. package/dist/src/tools/get-block-children.d.ts +2 -2
  68. package/dist/src/tools/get-block-children.d.ts.map +1 -1
  69. package/dist/src/tools/get-block-children.js +39 -6
  70. package/dist/src/tools/index.d.ts +13 -11
  71. package/dist/src/tools/index.d.ts.map +1 -1
  72. package/dist/src/tools/index.js +13 -9
  73. package/dist/src/tools/query-database.d.ts +2 -2
  74. package/dist/src/tools/query-database.d.ts.map +1 -1
  75. package/dist/src/tools/query-database.js +27 -18
  76. package/dist/src/tools/retrieve-page.d.ts +2 -2
  77. package/dist/src/tools/retrieve-page.d.ts.map +1 -1
  78. package/dist/src/tools/retrieve-page.js +44 -4
  79. package/dist/src/tools/search.d.ts +2 -2
  80. package/dist/src/tools/search.d.ts.map +1 -1
  81. package/dist/src/tools/search.js +18 -12
  82. package/dist/src/tools/update-database.d.ts +4 -0
  83. package/dist/src/tools/update-database.d.ts.map +1 -0
  84. package/dist/src/tools/update-database.js +74 -0
  85. package/dist/src/tools/update-page.d.ts +2 -2
  86. package/dist/src/tools/update-page.d.ts.map +1 -1
  87. package/dist/src/tools/update-page.js +23 -18
  88. package/dist/src/utils/error-handler.d.ts +1 -1
  89. package/dist/src/utils/error-handler.d.ts.map +1 -1
  90. package/dist/src/utils/error-handler.js +14 -14
  91. package/dist/src/utils/index.d.ts +2 -2
  92. package/dist/src/utils/index.d.ts.map +1 -1
  93. package/dist/src/utils/index.js +2 -2
  94. package/dist/src/utils/response-formatter.d.ts +13 -1
  95. package/dist/src/utils/response-formatter.d.ts.map +1 -1
  96. package/dist/src/utils/response-formatter.js +46 -3
  97. package/package.json +11 -2
@@ -0,0 +1,353 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { richTextToMarkdown, richTextToPlain } from '../rich-text-to-markdown.js';
3
+ describe('richTextToMarkdown', () => {
4
+ describe('basic text conversion', () => {
5
+ it('converts plain text', () => {
6
+ const input = [
7
+ {
8
+ type: 'text',
9
+ text: { content: 'Hello World' },
10
+ plain_text: 'Hello World',
11
+ },
12
+ ];
13
+ expect(richTextToMarkdown(input)).toBe('Hello World');
14
+ });
15
+ it('handles empty array', () => {
16
+ expect(richTextToMarkdown([])).toBe('');
17
+ });
18
+ it('handles undefined input', () => {
19
+ expect(richTextToMarkdown(undefined)).toBe('');
20
+ });
21
+ it('handles null input', () => {
22
+ expect(richTextToMarkdown(null)).toBe('');
23
+ });
24
+ it('concatenates multiple text items', () => {
25
+ const input = [
26
+ { type: 'text', text: { content: 'Hello ' }, plain_text: 'Hello ' },
27
+ { type: 'text', text: { content: 'World' }, plain_text: 'World' },
28
+ ];
29
+ expect(richTextToMarkdown(input)).toBe('Hello World');
30
+ });
31
+ });
32
+ describe('annotations', () => {
33
+ it('converts bold text', () => {
34
+ const input = [
35
+ {
36
+ type: 'text',
37
+ text: { content: 'bold' },
38
+ annotations: { bold: true },
39
+ plain_text: 'bold',
40
+ },
41
+ ];
42
+ expect(richTextToMarkdown(input)).toBe('**bold**');
43
+ });
44
+ it('converts italic text', () => {
45
+ const input = [
46
+ {
47
+ type: 'text',
48
+ text: { content: 'italic' },
49
+ annotations: { italic: true },
50
+ plain_text: 'italic',
51
+ },
52
+ ];
53
+ expect(richTextToMarkdown(input)).toBe('*italic*');
54
+ });
55
+ it('converts strikethrough text', () => {
56
+ const input = [
57
+ {
58
+ type: 'text',
59
+ text: { content: 'strikethrough' },
60
+ annotations: { strikethrough: true },
61
+ plain_text: 'strikethrough',
62
+ },
63
+ ];
64
+ expect(richTextToMarkdown(input)).toBe('~~strikethrough~~');
65
+ });
66
+ it('converts code text', () => {
67
+ const input = [
68
+ {
69
+ type: 'text',
70
+ text: { content: 'code' },
71
+ annotations: { code: true },
72
+ plain_text: 'code',
73
+ },
74
+ ];
75
+ expect(richTextToMarkdown(input)).toBe('`code`');
76
+ });
77
+ it('converts underline text with HTML tag', () => {
78
+ const input = [
79
+ {
80
+ type: 'text',
81
+ text: { content: 'underline' },
82
+ annotations: { underline: true },
83
+ plain_text: 'underline',
84
+ },
85
+ ];
86
+ expect(richTextToMarkdown(input)).toBe('<u>underline</u>');
87
+ });
88
+ it('handles nested annotations (bold + italic)', () => {
89
+ const input = [
90
+ {
91
+ type: 'text',
92
+ text: { content: 'bold italic' },
93
+ annotations: { bold: true, italic: true },
94
+ plain_text: 'bold italic',
95
+ },
96
+ ];
97
+ expect(richTextToMarkdown(input)).toBe('***bold italic***');
98
+ });
99
+ it('handles all annotations combined', () => {
100
+ const input = [
101
+ {
102
+ type: 'text',
103
+ text: { content: 'all' },
104
+ annotations: {
105
+ bold: true,
106
+ italic: true,
107
+ strikethrough: true,
108
+ code: true,
109
+ },
110
+ plain_text: 'all',
111
+ },
112
+ ];
113
+ // code -> strikethrough -> italic -> bold の順で適用
114
+ // bold + italic が *** として結合される
115
+ expect(richTextToMarkdown(input)).toBe('***~~`all`~~***');
116
+ });
117
+ });
118
+ describe('links', () => {
119
+ it('converts text with link (text.link)', () => {
120
+ const input = [
121
+ {
122
+ type: 'text',
123
+ text: {
124
+ content: 'link text',
125
+ link: { url: 'https://example.com' },
126
+ },
127
+ plain_text: 'link text',
128
+ },
129
+ ];
130
+ expect(richTextToMarkdown(input)).toBe('[link text](https://example.com)');
131
+ });
132
+ it('converts text with link (href)', () => {
133
+ const input = [
134
+ {
135
+ type: 'text',
136
+ text: { content: 'link text' },
137
+ href: 'https://example.com',
138
+ plain_text: 'link text',
139
+ },
140
+ ];
141
+ expect(richTextToMarkdown(input)).toBe('[link text](https://example.com)');
142
+ });
143
+ it('handles code annotation with link (ignores link)', () => {
144
+ const input = [
145
+ {
146
+ type: 'text',
147
+ text: {
148
+ content: 'code',
149
+ link: { url: 'https://example.com' },
150
+ },
151
+ annotations: { code: true },
152
+ plain_text: 'code',
153
+ },
154
+ ];
155
+ // コード内のリンクは無視される
156
+ expect(richTextToMarkdown(input)).toBe('`code`');
157
+ });
158
+ it('handles bold link', () => {
159
+ const input = [
160
+ {
161
+ type: 'text',
162
+ text: {
163
+ content: 'bold link',
164
+ link: { url: 'https://example.com' },
165
+ },
166
+ annotations: { bold: true },
167
+ plain_text: 'bold link',
168
+ },
169
+ ];
170
+ expect(richTextToMarkdown(input)).toBe('[**bold link**](https://example.com)');
171
+ });
172
+ });
173
+ describe('mention types', () => {
174
+ it('converts user mention', () => {
175
+ const input = [
176
+ {
177
+ type: 'mention',
178
+ mention: {
179
+ type: 'user',
180
+ user: { id: 'user-123', name: 'John Doe' },
181
+ },
182
+ plain_text: '@John Doe',
183
+ },
184
+ ];
185
+ expect(richTextToMarkdown(input)).toBe('@John Doe');
186
+ });
187
+ it('converts page mention', () => {
188
+ const input = [
189
+ {
190
+ type: 'mention',
191
+ mention: {
192
+ type: 'page',
193
+ page: { id: 'page-123' },
194
+ },
195
+ plain_text: 'My Page',
196
+ },
197
+ ];
198
+ expect(richTextToMarkdown(input)).toBe('My Page');
199
+ });
200
+ it('converts date mention', () => {
201
+ const input = [
202
+ {
203
+ type: 'mention',
204
+ mention: {
205
+ type: 'date',
206
+ date: { start: '2024-01-01' },
207
+ },
208
+ plain_text: '@January 1, 2024',
209
+ },
210
+ ];
211
+ expect(richTextToMarkdown(input)).toBe('2024-01-01');
212
+ });
213
+ it('converts date range mention', () => {
214
+ const input = [
215
+ {
216
+ type: 'mention',
217
+ mention: {
218
+ type: 'date',
219
+ date: { start: '2024-01-01', end: '2024-01-31' },
220
+ },
221
+ plain_text: '@January 1, 2024 → January 31, 2024',
222
+ },
223
+ ];
224
+ expect(richTextToMarkdown(input)).toBe('2024-01-01 → 2024-01-31');
225
+ });
226
+ });
227
+ describe('equation types', () => {
228
+ it('converts equation', () => {
229
+ const input = [
230
+ {
231
+ type: 'equation',
232
+ equation: { expression: 'E = mc^2' },
233
+ plain_text: 'E = mc^2',
234
+ },
235
+ ];
236
+ expect(richTextToMarkdown(input)).toBe('$E = mc^2$');
237
+ });
238
+ });
239
+ describe('mixed content', () => {
240
+ it('handles mixed plain and formatted text', () => {
241
+ const input = [
242
+ { type: 'text', text: { content: 'This is ' }, plain_text: 'This is ' },
243
+ {
244
+ type: 'text',
245
+ text: { content: 'bold' },
246
+ annotations: { bold: true },
247
+ plain_text: 'bold',
248
+ },
249
+ { type: 'text', text: { content: ' and ' }, plain_text: ' and ' },
250
+ {
251
+ type: 'text',
252
+ text: { content: 'italic' },
253
+ annotations: { italic: true },
254
+ plain_text: 'italic',
255
+ },
256
+ { type: 'text', text: { content: ' text.' }, plain_text: ' text.' },
257
+ ];
258
+ expect(richTextToMarkdown(input)).toBe('This is **bold** and *italic* text.');
259
+ });
260
+ it('handles real-world Notion data', () => {
261
+ // 実際のNotionから取得したデータ形式
262
+ const input = [
263
+ {
264
+ type: 'text',
265
+ text: { content: '以下のパッケージで ', link: null },
266
+ annotations: {
267
+ bold: false,
268
+ italic: false,
269
+ strikethrough: false,
270
+ underline: false,
271
+ code: false,
272
+ color: 'default',
273
+ },
274
+ plain_text: '以下のパッケージで ',
275
+ href: null,
276
+ },
277
+ {
278
+ type: 'text',
279
+ text: { content: 'exports', link: null },
280
+ annotations: {
281
+ bold: false,
282
+ italic: false,
283
+ strikethrough: false,
284
+ underline: false,
285
+ code: true,
286
+ color: 'default',
287
+ },
288
+ plain_text: 'exports',
289
+ href: null,
290
+ },
291
+ {
292
+ type: 'text',
293
+ text: { content: ' と ', link: null },
294
+ annotations: {
295
+ bold: false,
296
+ italic: false,
297
+ strikethrough: false,
298
+ underline: false,
299
+ code: false,
300
+ color: 'default',
301
+ },
302
+ plain_text: ' と ',
303
+ href: null,
304
+ },
305
+ {
306
+ type: 'text',
307
+ text: { content: 'main', link: null },
308
+ annotations: {
309
+ bold: false,
310
+ italic: false,
311
+ strikethrough: false,
312
+ underline: false,
313
+ code: true,
314
+ color: 'default',
315
+ },
316
+ plain_text: 'main',
317
+ href: null,
318
+ },
319
+ ];
320
+ expect(richTextToMarkdown(input)).toBe('以下のパッケージで `exports` と `main`');
321
+ });
322
+ });
323
+ });
324
+ describe('richTextToPlain', () => {
325
+ it('extracts plain text', () => {
326
+ const input = [
327
+ {
328
+ type: 'text',
329
+ text: { content: 'Hello' },
330
+ annotations: { bold: true },
331
+ plain_text: 'Hello',
332
+ },
333
+ { type: 'text', text: { content: ' World' }, plain_text: ' World' },
334
+ ];
335
+ expect(richTextToPlain(input)).toBe('Hello World');
336
+ });
337
+ it('handles empty array', () => {
338
+ expect(richTextToPlain([])).toBe('');
339
+ });
340
+ it('handles undefined input', () => {
341
+ expect(richTextToPlain(undefined)).toBe('');
342
+ });
343
+ it('prefers plain_text over text.content', () => {
344
+ const input = [
345
+ {
346
+ type: 'text',
347
+ text: { content: 'content' },
348
+ plain_text: 'plain',
349
+ },
350
+ ];
351
+ expect(richTextToPlain(input)).toBe('plain');
352
+ });
353
+ });
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Notionブロックをマークダウン文字列に変換するモジュール
3
+ */
4
+ /**
5
+ * Notionブロックの基本型
6
+ */
7
+ export interface NotionBlock {
8
+ object?: string;
9
+ id?: string;
10
+ type: string;
11
+ has_children?: boolean;
12
+ [key: string]: unknown;
13
+ }
14
+ /**
15
+ * ブロック変換オプション
16
+ */
17
+ export interface ConvertOptions {
18
+ /** インデントレベル(ネストされたブロック用) */
19
+ indentLevel?: number;
20
+ /** 番号付きリストのインデックス */
21
+ listIndex?: number;
22
+ /** 子ブロック取得関数(ネストされたブロックの再帰的取得用) */
23
+ fetchChildren?: (blockId: string) => Promise<NotionBlock[]>;
24
+ }
25
+ /**
26
+ * ブロック配列をマークダウン文字列に変換
27
+ * @param blocks - Notion APIから取得したブロック配列
28
+ * @param options - 変換オプション
29
+ * @returns マークダウン文字列
30
+ */
31
+ export declare function blocksToMarkdown(blocks: NotionBlock[], options?: ConvertOptions): Promise<string>;
32
+ /**
33
+ * ブロック配列をマークダウン文字列に変換(同期版、子ブロック取得なし)
34
+ * @param blocks - Notion APIから取得したブロック配列
35
+ * @returns マークダウン文字列
36
+ */
37
+ export declare function blocksToMarkdownSync(blocks: NotionBlock[]): string;
38
+ //# sourceMappingURL=block-to-markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"block-to-markdown.d.ts","sourceRoot":"","sources":["../../../src/converters/block-to-markdown.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,4BAA4B;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,qBAAqB;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,mCAAmC;IACnC,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,CAAA;CAC5D;AA2UD;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,WAAW,EAAE,EACrB,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,MAAM,CAAC,CAgCjB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,CAsMlE"}