safe-notion 0.1.3 → 0.2.0
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 +14 -14
- package/dist/commands/search.d.ts +2 -0
- package/dist/index.js +96 -6
- package/dist/notion-client.d.ts +14 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ export NOTION_TOKEN="your-notion-integration-token"
|
|
|
28
28
|
設定ファイルを初期化:
|
|
29
29
|
|
|
30
30
|
```bash
|
|
31
|
-
notion
|
|
31
|
+
safe-notion config init
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
設定ファイルの場所: `~/.config/safe-notion/config.jsonc`
|
|
@@ -85,34 +85,34 @@ notion-safe config init
|
|
|
85
85
|
### ページ操作
|
|
86
86
|
|
|
87
87
|
```bash
|
|
88
|
-
notion
|
|
89
|
-
notion
|
|
90
|
-
notion
|
|
88
|
+
safe-notion page get <page-id>
|
|
89
|
+
safe-notion page create --parent <parent-id> --title "タイトル"
|
|
90
|
+
safe-notion page update <page-id>
|
|
91
91
|
```
|
|
92
92
|
|
|
93
93
|
### データベース操作
|
|
94
94
|
|
|
95
95
|
```bash
|
|
96
|
-
notion
|
|
97
|
-
notion
|
|
98
|
-
notion
|
|
96
|
+
safe-notion db get <database-id>
|
|
97
|
+
safe-notion db query <database-id>
|
|
98
|
+
safe-notion db create-page <database-id>
|
|
99
99
|
```
|
|
100
100
|
|
|
101
101
|
### ブロック操作
|
|
102
102
|
|
|
103
103
|
```bash
|
|
104
|
-
notion
|
|
105
|
-
notion
|
|
106
|
-
notion
|
|
107
|
-
notion
|
|
104
|
+
safe-notion block get <block-id>
|
|
105
|
+
safe-notion block children <block-id>
|
|
106
|
+
safe-notion block append <block-id> --children '<json>'
|
|
107
|
+
safe-notion block delete <block-id>
|
|
108
108
|
```
|
|
109
109
|
|
|
110
110
|
### 設定管理
|
|
111
111
|
|
|
112
112
|
```bash
|
|
113
|
-
notion
|
|
114
|
-
notion
|
|
115
|
-
notion
|
|
113
|
+
safe-notion config init # 設定ファイルを初期化
|
|
114
|
+
safe-notion config validate # 設定を検証
|
|
115
|
+
safe-notion config path # 設定ファイルのパスを表示
|
|
116
116
|
```
|
|
117
117
|
|
|
118
118
|
## 開発
|
package/dist/index.js
CHANGED
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
// @bun
|
|
3
3
|
|
|
4
4
|
// src/index.ts
|
|
5
|
-
import { Command as
|
|
5
|
+
import { Command as Command6 } from "commander";
|
|
6
6
|
|
|
7
7
|
// src/commands/page.ts
|
|
8
8
|
import { Command } from "commander";
|
|
9
9
|
|
|
10
10
|
// src/notion-client.ts
|
|
11
11
|
import { Client } from "@notionhq/client";
|
|
12
|
+
import { LogLevel } from "@notionhq/client/build/src/logging";
|
|
12
13
|
|
|
13
14
|
// src/config.ts
|
|
14
15
|
import { readFileSync, existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
@@ -356,12 +357,16 @@ function clearCache() {
|
|
|
356
357
|
}
|
|
357
358
|
|
|
358
359
|
// src/notion-client.ts
|
|
360
|
+
var debugMode = false;
|
|
359
361
|
class NotionSafeClient {
|
|
360
362
|
client;
|
|
361
363
|
config;
|
|
362
364
|
constructor() {
|
|
363
365
|
const token = getNotionToken();
|
|
364
|
-
this.client = new Client({
|
|
366
|
+
this.client = new Client({
|
|
367
|
+
auth: token,
|
|
368
|
+
logLevel: debugMode ? LogLevel.WARN : LogLevel.ERROR
|
|
369
|
+
});
|
|
365
370
|
this.config = loadConfig();
|
|
366
371
|
}
|
|
367
372
|
async ensurePermission(resourceId, operation, pageIdForCondition) {
|
|
@@ -400,8 +405,18 @@ class NotionSafeClient {
|
|
|
400
405
|
}
|
|
401
406
|
async queryDatabase(databaseId, params) {
|
|
402
407
|
await this.ensurePermission(databaseId, "database:query");
|
|
403
|
-
|
|
404
|
-
database_id: databaseId
|
|
408
|
+
const database = await this.client.databases.retrieve({
|
|
409
|
+
database_id: databaseId
|
|
410
|
+
});
|
|
411
|
+
const dataSourceId = database.data_sources?.[0]?.id;
|
|
412
|
+
if (!dataSourceId) {
|
|
413
|
+
throw {
|
|
414
|
+
error: "Database has no data source",
|
|
415
|
+
code: "NO_DATA_SOURCE"
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
return this.client.dataSources.query({
|
|
419
|
+
data_source_id: dataSourceId,
|
|
405
420
|
...params
|
|
406
421
|
});
|
|
407
422
|
}
|
|
@@ -435,6 +450,17 @@ class NotionSafeClient {
|
|
|
435
450
|
await this.ensurePermission(blockId, "block:delete");
|
|
436
451
|
return this.client.blocks.delete({ block_id: blockId });
|
|
437
452
|
}
|
|
453
|
+
async search(params) {
|
|
454
|
+
const hasReadPermission = this.config.defaultPermission === "read" || this.config.rules.some((rule) => rule.permissions.some((p) => ["page:read", "database:read", "block:read"].includes(p)));
|
|
455
|
+
if (!hasReadPermission) {
|
|
456
|
+
const error = {
|
|
457
|
+
error: "Search not allowed: no read permissions configured",
|
|
458
|
+
code: "PERMISSION_DENIED"
|
|
459
|
+
};
|
|
460
|
+
throw error;
|
|
461
|
+
}
|
|
462
|
+
return this.client.search(params);
|
|
463
|
+
}
|
|
438
464
|
clearCache() {
|
|
439
465
|
clearCache();
|
|
440
466
|
}
|
|
@@ -680,11 +706,75 @@ function createConfigCommand() {
|
|
|
680
706
|
return config;
|
|
681
707
|
}
|
|
682
708
|
|
|
709
|
+
// src/commands/search.ts
|
|
710
|
+
import { Command as Command5 } from "commander";
|
|
711
|
+
function createSearchCommand() {
|
|
712
|
+
const search = new Command5("search").description("Search pages and databases");
|
|
713
|
+
search.argument("[query]", "Search query string").option("--filter <type>", "Filter by object type: page or database").option("--sort <direction>", "Sort by last_edited_time: ascending or descending").option("--start-cursor <cursor>", "Pagination cursor").option("--page-size <size>", "Number of results per page", "100").action(async (query, options) => {
|
|
714
|
+
try {
|
|
715
|
+
const client = getClient();
|
|
716
|
+
const params = {};
|
|
717
|
+
if (query) {
|
|
718
|
+
params.query = query;
|
|
719
|
+
}
|
|
720
|
+
if (options.filter) {
|
|
721
|
+
const filterValue = options.filter === "database" ? "data_source" : options.filter;
|
|
722
|
+
if (filterValue !== "page" && filterValue !== "data_source") {
|
|
723
|
+
throw {
|
|
724
|
+
error: "Invalid filter value. Must be 'page' or 'database'",
|
|
725
|
+
code: "INVALID_ARGUMENT"
|
|
726
|
+
};
|
|
727
|
+
}
|
|
728
|
+
params.filter = { property: "object", value: filterValue };
|
|
729
|
+
}
|
|
730
|
+
if (options.sort) {
|
|
731
|
+
if (options.sort !== "ascending" && options.sort !== "descending") {
|
|
732
|
+
throw {
|
|
733
|
+
error: "Invalid sort value. Must be 'ascending' or 'descending'",
|
|
734
|
+
code: "INVALID_ARGUMENT"
|
|
735
|
+
};
|
|
736
|
+
}
|
|
737
|
+
params.sort = {
|
|
738
|
+
direction: options.sort,
|
|
739
|
+
timestamp: "last_edited_time"
|
|
740
|
+
};
|
|
741
|
+
}
|
|
742
|
+
if (options.startCursor) {
|
|
743
|
+
params.start_cursor = options.startCursor;
|
|
744
|
+
}
|
|
745
|
+
if (options.pageSize) {
|
|
746
|
+
params.page_size = parseInt(options.pageSize, 10);
|
|
747
|
+
}
|
|
748
|
+
const result = await client.search(params);
|
|
749
|
+
outputJson(result);
|
|
750
|
+
} catch (error) {
|
|
751
|
+
handleError(error);
|
|
752
|
+
}
|
|
753
|
+
});
|
|
754
|
+
return search;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
// src/notion-client.ts
|
|
758
|
+
import { Client as Client2 } from "@notionhq/client";
|
|
759
|
+
import { LogLevel as LogLevel2 } from "@notionhq/client/build/src/logging";
|
|
760
|
+
var debugMode2 = false;
|
|
761
|
+
function setDebugMode(enabled) {
|
|
762
|
+
debugMode2 = enabled;
|
|
763
|
+
clientInstance2 = null;
|
|
764
|
+
}
|
|
765
|
+
var clientInstance2 = null;
|
|
766
|
+
|
|
683
767
|
// src/index.ts
|
|
684
|
-
var program = new
|
|
685
|
-
program.name("notion-safe").description("A safe Notion API wrapper CLI for AI agents").version("0.1.0")
|
|
768
|
+
var program = new Command6;
|
|
769
|
+
program.name("notion-safe").description("A safe Notion API wrapper CLI for AI agents").version("0.1.0").option("--debug", "Enable debug output including API warnings").hook("preAction", () => {
|
|
770
|
+
const opts = program.opts();
|
|
771
|
+
if (opts.debug) {
|
|
772
|
+
setDebugMode(true);
|
|
773
|
+
}
|
|
774
|
+
});
|
|
686
775
|
program.addCommand(createPageCommand());
|
|
687
776
|
program.addCommand(createDbCommand());
|
|
688
777
|
program.addCommand(createBlockCommand());
|
|
689
778
|
program.addCommand(createConfigCommand());
|
|
779
|
+
program.addCommand(createSearchCommand());
|
|
690
780
|
program.parse();
|
package/dist/notion-client.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Client } from "@notionhq/client";
|
|
2
|
+
export declare function setDebugMode(enabled: boolean): void;
|
|
2
3
|
type CreatePageParams = Parameters<Client["pages"]["create"]>[0];
|
|
3
4
|
type UpdatePageParams = Parameters<Client["pages"]["update"]>[0];
|
|
4
5
|
type AppendBlockChildrenParams = Parameters<Client["blocks"]["children"]["append"]>[0];
|
|
@@ -23,6 +24,19 @@ export declare class NotionSafeClient {
|
|
|
23
24
|
getBlockChildren(blockId: string, startCursor?: string, pageSize?: number): Promise<unknown>;
|
|
24
25
|
appendBlockChildren(blockId: string, children: AppendBlockChildrenParams["children"]): Promise<unknown>;
|
|
25
26
|
deleteBlock(blockId: string): Promise<unknown>;
|
|
27
|
+
search(params: {
|
|
28
|
+
query?: string;
|
|
29
|
+
filter?: {
|
|
30
|
+
property: "object";
|
|
31
|
+
value: "page" | "data_source";
|
|
32
|
+
};
|
|
33
|
+
sort?: {
|
|
34
|
+
direction: "ascending" | "descending";
|
|
35
|
+
timestamp: "last_edited_time";
|
|
36
|
+
};
|
|
37
|
+
start_cursor?: string;
|
|
38
|
+
page_size?: number;
|
|
39
|
+
}): Promise<unknown>;
|
|
26
40
|
clearCache(): void;
|
|
27
41
|
}
|
|
28
42
|
export declare function getClient(): NotionSafeClient;
|