@lpenguin/notion-cli 1.0.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 +245 -0
- package/dist/commands/database/create.d.ts +8 -0
- package/dist/commands/database/create.d.ts.map +1 -0
- package/dist/commands/database/create.js +71 -0
- package/dist/commands/database/create.js.map +1 -0
- package/dist/commands/database/delete.d.ts +10 -0
- package/dist/commands/database/delete.d.ts.map +1 -0
- package/dist/commands/database/delete.js +83 -0
- package/dist/commands/database/delete.js.map +1 -0
- package/dist/commands/database/export.d.ts +11 -0
- package/dist/commands/database/export.d.ts.map +1 -0
- package/dist/commands/database/export.js +74 -0
- package/dist/commands/database/export.js.map +1 -0
- package/dist/commands/database/insert.d.ts +11 -0
- package/dist/commands/database/insert.d.ts.map +1 -0
- package/dist/commands/database/insert.js +93 -0
- package/dist/commands/database/insert.js.map +1 -0
- package/dist/commands/database/list.d.ts +10 -0
- package/dist/commands/database/list.d.ts.map +1 -0
- package/dist/commands/database/list.js +80 -0
- package/dist/commands/database/list.js.map +1 -0
- package/dist/commands/database/query.d.ts +10 -0
- package/dist/commands/database/query.d.ts.map +1 -0
- package/dist/commands/database/query.js +77 -0
- package/dist/commands/database/query.js.map +1 -0
- package/dist/commands/database/schema.d.ts +11 -0
- package/dist/commands/database/schema.d.ts.map +1 -0
- package/dist/commands/database/schema.js +76 -0
- package/dist/commands/database/schema.js.map +1 -0
- package/dist/commands/database/update.d.ts +11 -0
- package/dist/commands/database/update.d.ts.map +1 -0
- package/dist/commands/database/update.js +105 -0
- package/dist/commands/database/update.js.map +1 -0
- package/dist/commands/page/create.d.ts +11 -0
- package/dist/commands/page/create.d.ts.map +1 -0
- package/dist/commands/page/create.js +102 -0
- package/dist/commands/page/create.js.map +1 -0
- package/dist/commands/page/list.d.ts +10 -0
- package/dist/commands/page/list.d.ts.map +1 -0
- package/dist/commands/page/list.js +87 -0
- package/dist/commands/page/list.js.map +1 -0
- package/dist/commands/page/patch.d.ts +21 -0
- package/dist/commands/page/patch.d.ts.map +1 -0
- package/dist/commands/page/patch.js +156 -0
- package/dist/commands/page/patch.js.map +1 -0
- package/dist/commands/page/read.d.ts +10 -0
- package/dist/commands/page/read.d.ts.map +1 -0
- package/dist/commands/page/read.js +86 -0
- package/dist/commands/page/read.js.map +1 -0
- package/dist/commands/page/write-properties.d.ts +15 -0
- package/dist/commands/page/write-properties.d.ts.map +1 -0
- package/dist/commands/page/write-properties.js +128 -0
- package/dist/commands/page/write-properties.js.map +1 -0
- package/dist/commands/page/write.d.ts +14 -0
- package/dist/commands/page/write.d.ts.map +1 -0
- package/dist/commands/page/write.js +109 -0
- package/dist/commands/page/write.js.map +1 -0
- package/dist/commands/search.d.ts +18 -0
- package/dist/commands/search.d.ts.map +1 -0
- package/dist/commands/search.js +129 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +121 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/block-patch.d.ts +61 -0
- package/dist/lib/block-patch.d.ts.map +1 -0
- package/dist/lib/block-patch.js +181 -0
- package/dist/lib/block-patch.js.map +1 -0
- package/dist/lib/client.d.ts +17 -0
- package/dist/lib/client.d.ts.map +1 -0
- package/dist/lib/client.js +63 -0
- package/dist/lib/client.js.map +1 -0
- package/dist/lib/config.d.ts +19 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +65 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/csv.d.ts +45 -0
- package/dist/lib/csv.d.ts.map +1 -0
- package/dist/lib/csv.js +262 -0
- package/dist/lib/csv.js.map +1 -0
- package/dist/lib/db-properties.d.ts +11 -0
- package/dist/lib/db-properties.d.ts.map +1 -0
- package/dist/lib/db-properties.js +25 -0
- package/dist/lib/db-properties.js.map +1 -0
- package/dist/lib/errors.d.ts +34 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +86 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/file-upload.d.ts +25 -0
- package/dist/lib/file-upload.d.ts.map +1 -0
- package/dist/lib/file-upload.js +90 -0
- package/dist/lib/file-upload.js.map +1 -0
- package/dist/lib/markdown.d.ts +79 -0
- package/dist/lib/markdown.d.ts.map +1 -0
- package/dist/lib/markdown.js +320 -0
- package/dist/lib/markdown.js.map +1 -0
- package/dist/lib/output.d.ts +20 -0
- package/dist/lib/output.d.ts.map +1 -0
- package/dist/lib/output.js +67 -0
- package/dist/lib/output.js.map +1 -0
- package/dist/lib/patch.d.ts +23 -0
- package/dist/lib/patch.d.ts.map +1 -0
- package/dist/lib/patch.js +72 -0
- package/dist/lib/patch.js.map +1 -0
- package/dist/lib/rate-limit.d.ts +9 -0
- package/dist/lib/rate-limit.d.ts.map +1 -0
- package/dist/lib/rate-limit.js +67 -0
- package/dist/lib/rate-limit.js.map +1 -0
- package/dist/lib/safety.d.ts +17 -0
- package/dist/lib/safety.d.ts.map +1 -0
- package/dist/lib/safety.js +60 -0
- package/dist/lib/safety.js.map +1 -0
- package/dist/lib/types.d.ts +138 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +13 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/lib/validator.d.ts +33 -0
- package/dist/lib/validator.d.ts.map +1 -0
- package/dist/lib/validator.js +68 -0
- package/dist/lib/validator.js.map +1 -0
- package/dist/utils/id.d.ts +14 -0
- package/dist/utils/id.d.ts.map +1 -0
- package/dist/utils/id.js +33 -0
- package/dist/utils/id.js.map +1 -0
- package/dist/utils/logger.d.ts +20 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +43 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/string.d.ts +14 -0
- package/dist/utils/string.d.ts.map +1 -0
- package/dist/utils/string.js +37 -0
- package/dist/utils/string.js.map +1 -0
- package/package.json +64 -0
package/README.md
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# notion-cli
|
|
2
|
+
|
|
3
|
+
CLI tool for reading and editing Notion entries through Markdown and CSV. AI agent friendly.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Run directly with npx
|
|
9
|
+
npx notion-cli page read <page-id>
|
|
10
|
+
|
|
11
|
+
# Or install globally
|
|
12
|
+
npm install -g notion-cli
|
|
13
|
+
notion-cli page read <page-id>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Configuration
|
|
17
|
+
|
|
18
|
+
Set your Notion Integration Token:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
export NOTION_TOKEN=ntn_xxx
|
|
22
|
+
|
|
23
|
+
# Or pass directly
|
|
24
|
+
notion-cli --token ntn_xxx page read <page-id>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
You can also create a `~/.notion-cli.json` config file:
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"token": "ntn_xxx"
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Global Options
|
|
36
|
+
|
|
37
|
+
| Flag | Description |
|
|
38
|
+
|------|-------------|
|
|
39
|
+
| `--token <token>` | Notion API integration token (overrides env/config) |
|
|
40
|
+
| `--json` | Structured JSON output for machine consumption |
|
|
41
|
+
| `--dry-run` | Preview changes without executing writes |
|
|
42
|
+
| `-v, --verbose` | Enable debug output to stderr |
|
|
43
|
+
| `--no-color` | Disable colored output |
|
|
44
|
+
|
|
45
|
+
## Commands
|
|
46
|
+
|
|
47
|
+
### `page read` — Read a Notion Page as Markdown
|
|
48
|
+
|
|
49
|
+
Fetch a Notion page and output its content as Markdown. This command is idempotent and read-only.
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
notion-cli page read <page-id>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Examples:**
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Read page content
|
|
59
|
+
notion-cli page read abc123def456
|
|
60
|
+
|
|
61
|
+
# Read as JSON (for scripting)
|
|
62
|
+
notion-cli page read abc123def456 --json
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
When `--json` is enabled, the output includes `pageId`, `title`, and `markdown` fields. Status messages are always written to stderr, and the markdown content goes to stdout, so you can pipe it safely: `notion-cli page read <id> > page.md`.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
### `page create` — Create a New Page
|
|
70
|
+
|
|
71
|
+
Create a new Notion page from Markdown content.
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
notion-cli page create --parent <page-id> --file content.md
|
|
75
|
+
notion-cli page create --parent <page-id> --title "My Page" --content "# Hello"
|
|
76
|
+
notion-cli page create --parent <db-id> --db --file entry.md
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
| Option | Description |
|
|
80
|
+
|--------|-------------|
|
|
81
|
+
| `--parent <id>` | **Required.** Parent page or database ID |
|
|
82
|
+
| `-f, --file <path>` | Path to Markdown file |
|
|
83
|
+
| `--content <markdown>` | Inline Markdown content |
|
|
84
|
+
| `--title <title>` | Page title (overrides H1 in content) |
|
|
85
|
+
| `--db` | Create as a database entry instead of a sub-page |
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
### `page write` — Replace Page Content
|
|
90
|
+
|
|
91
|
+
Replace a Notion page's content with new Markdown content. This is a destructive operation that replaces ALL existing content on the page.
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
notion-cli page write <page-id> --file content.md
|
|
95
|
+
notion-cli page write <page-id> --content "# New Content"
|
|
96
|
+
cat content.md | notion-cli page write <page-id>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
| Option | Description |
|
|
100
|
+
|--------|-------------|
|
|
101
|
+
| `-f, --file <path>` | Path to Markdown file |
|
|
102
|
+
| `--content <markdown>` | Inline Markdown content |
|
|
103
|
+
|
|
104
|
+
**Image Upload Support:**
|
|
105
|
+
|
|
106
|
+
When using `page write`, images with `file://` URLs will be automatically uploaded to Notion's file storage:
|
|
107
|
+
|
|
108
|
+
```markdown
|
|
109
|
+
# My Page
|
|
110
|
+
|
|
111
|
+

|
|
112
|
+

|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
- Local images with `file://` URLs are uploaded to Notion
|
|
116
|
+
- External URLs (http/https) remain as external references
|
|
117
|
+
- Supports common formats: PNG, JPG, GIF, WebP, SVG, BMP, TIFF
|
|
118
|
+
- Works with both Unix and Windows paths
|
|
119
|
+
- Handles URL-encoded paths with special characters
|
|
120
|
+
|
|
121
|
+
**Examples:**
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
# Replace page content from file
|
|
125
|
+
notion-cli page write abc123def456 --file mypage.md
|
|
126
|
+
|
|
127
|
+
# Replace with inline content
|
|
128
|
+
notion-cli page write abc123def456 --content "# Hello\n\nNew content"
|
|
129
|
+
|
|
130
|
+
# Replace from stdin
|
|
131
|
+
echo "# Updated\n\nNew content" | notion-cli page write abc123def456
|
|
132
|
+
|
|
133
|
+
# Dry run to preview changes
|
|
134
|
+
notion-cli page write abc123def456 --file mypage.md --dry-run
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
> ⚠️ **Warning:** This command replaces ALL existing content. For partial edits, use `page patch` instead.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
### `page list` — List Pages
|
|
142
|
+
|
|
143
|
+
List or search Notion pages accessible to the integration.
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
notion-cli page list
|
|
147
|
+
notion-cli page list --query "search term" --limit 20
|
|
148
|
+
notion-cli page list --cursor <cursor>
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
### Databases
|
|
154
|
+
|
|
155
|
+
Query, export, import, and inspect Notion databases.
|
|
156
|
+
|
|
157
|
+
#### `db list` — List databases
|
|
158
|
+
|
|
159
|
+
List accessible Notion databases.
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
notion-cli db list
|
|
163
|
+
notion-cli db list --query "Projects" --limit 10
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
#### `db query` — Query Database
|
|
167
|
+
|
|
168
|
+
Query a Notion database. Outputs CSV by default, JSON with `--json`.
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
notion-cli db query <database-id>
|
|
172
|
+
notion-cli db query <database-id> --filter '{"property":"Status","select":{"equals":"Done"}}'
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
#### `db export` — Export to CSV
|
|
176
|
+
|
|
177
|
+
Export full Notion database to CSV.
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
notion-cli db export <database-id> --out data.csv
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
#### `db import` — Import from CSV
|
|
184
|
+
|
|
185
|
+
Import CSV rows into a Notion database.
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
notion-cli db import <database-id> --file data.csv
|
|
189
|
+
notion-cli db import <database-id> --file data.csv --sync
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
| Option | Description |
|
|
193
|
+
|--------|-------------|
|
|
194
|
+
| `-f, --file <path>` | **Required.** Path to CSV file |
|
|
195
|
+
| `--sync` | **Synchronize mode.** Pages in Notion that are NOT in the CSV will be **archived** (sent to Trash). |
|
|
196
|
+
|
|
197
|
+
> ⚠️ **Warning on --sync:** This mode is destructive. It ensures the database in Notion exactly matches your CSV. If a row exists in Notion but its `_notion_id` is missing from your CSV, it will be deleted from the database.
|
|
198
|
+
|
|
199
|
+
#### `db create` — Create Database
|
|
200
|
+
|
|
201
|
+
Create a new Notion database in a parent page.
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
notion-cli db create --parent <page-id> --title "My Database"
|
|
205
|
+
notion-cli db create --parent <page-id> --title "Tasks" --schema '{"Status": {"select": {}}}'
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
| Option | Description |
|
|
209
|
+
|--------|-------------|
|
|
210
|
+
| `-p, --parent <id>` | **Required.** Parent page ID |
|
|
211
|
+
| `-t, --title <text>`| **Required.** Database title |
|
|
212
|
+
| `-s, --schema <json>`| Database schema (Notion properties JSON) |
|
|
213
|
+
|
|
214
|
+
#### `db schema` — Show Schema
|
|
215
|
+
|
|
216
|
+
Show database property schema.
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
notion-cli db schema <database-id>
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
### Search
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
notion-cli search "query"
|
|
228
|
+
notion-cli search "query" --type page
|
|
229
|
+
notion-cli search "query" --type database
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Exit Codes
|
|
233
|
+
|
|
234
|
+
| Code | Meaning |
|
|
235
|
+
|------|---------|
|
|
236
|
+
| `0` | Success |
|
|
237
|
+
| `1` | General error |
|
|
238
|
+
| `2` | Validation error (bad arguments) |
|
|
239
|
+
| `3` | Authentication error |
|
|
240
|
+
| `4` | Not found |
|
|
241
|
+
| `5` | Rate limited |
|
|
242
|
+
|
|
243
|
+
## License
|
|
244
|
+
|
|
245
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/commands/database/create.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAazC,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,CAiEzD"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* notion-cli db create
|
|
3
|
+
*
|
|
4
|
+
* Create a new Notion database in a parent page.
|
|
5
|
+
*/
|
|
6
|
+
import {} from 'commander';
|
|
7
|
+
import { getClient } from '../../lib/client.js';
|
|
8
|
+
import { printSuccess, printError, isJsonMode } from '../../lib/output.js';
|
|
9
|
+
import { withRateLimit } from '../../lib/rate-limit.js';
|
|
10
|
+
import { parseNotionId } from '../../utils/id.js';
|
|
11
|
+
import {} from '../../lib/types.js';
|
|
12
|
+
import { toCliError } from '../../lib/errors.js';
|
|
13
|
+
import * as logger from '../../utils/logger.js';
|
|
14
|
+
export function registerDbCreateCommand(db) {
|
|
15
|
+
db.command('create')
|
|
16
|
+
.description('Create a new database.')
|
|
17
|
+
.requiredOption('-p, --parent <id>', 'Parent page ID')
|
|
18
|
+
.requiredOption('-t, --title <text>', 'Database title')
|
|
19
|
+
.option('-s, --schema <json>', 'Database schema (Notion properties JSON)', '{"Name": {"title": {}}}')
|
|
20
|
+
.action(async (cmdOpts) => {
|
|
21
|
+
try {
|
|
22
|
+
const opts = db.optsWithGlobals();
|
|
23
|
+
const parentId = parseNotionId(cmdOpts.parent);
|
|
24
|
+
const client = getClient(opts.token);
|
|
25
|
+
let properties;
|
|
26
|
+
try {
|
|
27
|
+
properties = JSON.parse(cmdOpts.schema);
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
throw new Error(`Invalid schema JSON: ${err.message}`);
|
|
31
|
+
}
|
|
32
|
+
if (opts.dryRun === true) {
|
|
33
|
+
logger.info(`[Dry Run] Would create database "${cmdOpts.title}" in page ${parentId}`);
|
|
34
|
+
if (isJsonMode()) {
|
|
35
|
+
printSuccess({ dryRun: true, parentId, title: cmdOpts.title, properties });
|
|
36
|
+
}
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const response = (await withRateLimit(() => client.databases.create({
|
|
40
|
+
parent: {
|
|
41
|
+
type: 'page_id',
|
|
42
|
+
page_id: parentId,
|
|
43
|
+
},
|
|
44
|
+
title: [
|
|
45
|
+
{
|
|
46
|
+
type: 'text',
|
|
47
|
+
text: {
|
|
48
|
+
content: cmdOpts.title,
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
initial_data_source: {
|
|
53
|
+
properties: properties,
|
|
54
|
+
},
|
|
55
|
+
}), 'databases.create'));
|
|
56
|
+
if (isJsonMode()) {
|
|
57
|
+
printSuccess(response);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
logger.info(`Database created successfully: ${response.id}`);
|
|
61
|
+
process.stdout.write(`URL: ${response.url}\n`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
const cliErr = toCliError(err);
|
|
66
|
+
printError(cliErr.code, cliErr.message);
|
|
67
|
+
process.exitCode = cliErr.exitCode;
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=create.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../../src/commands/database/create.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* notion-cli db delete <db-id> --ids <id1,id2,...>
|
|
3
|
+
*
|
|
4
|
+
* Archive (soft-delete) pages in a Notion database by their page IDs.
|
|
5
|
+
*
|
|
6
|
+
* This command is NOT idempotent (archives pages each run).
|
|
7
|
+
*/
|
|
8
|
+
import { type Command } from 'commander';
|
|
9
|
+
export declare function registerDbDeleteCommand(db: Command): void;
|
|
10
|
+
//# sourceMappingURL=delete.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["../../../src/commands/database/delete.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAUzC,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,CAkFzD"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* notion-cli db delete <db-id> --ids <id1,id2,...>
|
|
3
|
+
*
|
|
4
|
+
* Archive (soft-delete) pages in a Notion database by their page IDs.
|
|
5
|
+
*
|
|
6
|
+
* This command is NOT idempotent (archives pages each run).
|
|
7
|
+
*/
|
|
8
|
+
import {} from 'commander';
|
|
9
|
+
import { getClient, resolveDataSourceId } from '../../lib/client.js';
|
|
10
|
+
import { printSuccess, printError, isJsonMode } from '../../lib/output.js';
|
|
11
|
+
import { isDryRun } from '../../lib/safety.js';
|
|
12
|
+
import { withRateLimit } from '../../lib/rate-limit.js';
|
|
13
|
+
import { parseNotionId } from '../../utils/id.js';
|
|
14
|
+
import {} from '../../lib/types.js';
|
|
15
|
+
import { toCliError, ValidationError } from '../../lib/errors.js';
|
|
16
|
+
import * as logger from '../../utils/logger.js';
|
|
17
|
+
export function registerDbDeleteCommand(db) {
|
|
18
|
+
db.command('delete')
|
|
19
|
+
.description('Archive (delete) pages from a Notion database by page IDs.')
|
|
20
|
+
.argument('<db-id>', 'Notion database ID or URL')
|
|
21
|
+
.requiredOption('--ids <ids>', 'Comma-separated list of page IDs or URLs to archive')
|
|
22
|
+
.action(async (rawId, cmdOpts) => {
|
|
23
|
+
try {
|
|
24
|
+
const opts = db.optsWithGlobals();
|
|
25
|
+
const rawIdParsed = parseNotionId(rawId);
|
|
26
|
+
const client = getClient(opts.token);
|
|
27
|
+
const dbId = await resolveDataSourceId(client, rawIdParsed);
|
|
28
|
+
const pageIds = cmdOpts.ids
|
|
29
|
+
.split(',')
|
|
30
|
+
.map((id) => id.trim())
|
|
31
|
+
.filter((id) => id.length > 0)
|
|
32
|
+
.map(parseNotionId);
|
|
33
|
+
if (pageIds.length === 0) {
|
|
34
|
+
throw new ValidationError('No page IDs provided. Use --ids <id1,id2,...>.');
|
|
35
|
+
}
|
|
36
|
+
logger.info(`Delete: ${String(pageIds.length)} pages to archive.`);
|
|
37
|
+
if (isDryRun(opts.dryRun)) {
|
|
38
|
+
if (isJsonMode()) {
|
|
39
|
+
printSuccess({
|
|
40
|
+
databaseId: dbId,
|
|
41
|
+
toArchive: pageIds.length,
|
|
42
|
+
pageIds,
|
|
43
|
+
dryRun: true,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
logger.info(`Dry run: Would archive ${String(pageIds.length)} pages from database ${dbId}.`);
|
|
48
|
+
}
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
let archived = 0;
|
|
52
|
+
let failed = 0;
|
|
53
|
+
await Promise.all(pageIds.map(async (pageId) => {
|
|
54
|
+
try {
|
|
55
|
+
await withRateLimit(() => client.pages.update({ page_id: pageId, archived: true }), 'pages.update (archive)');
|
|
56
|
+
archived++;
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
failed++;
|
|
60
|
+
logger.warn(`Failed to archive page ${pageId}: ${String(err)}`);
|
|
61
|
+
}
|
|
62
|
+
}));
|
|
63
|
+
const result = {
|
|
64
|
+
databaseId: dbId,
|
|
65
|
+
archived,
|
|
66
|
+
failed,
|
|
67
|
+
total: pageIds.length,
|
|
68
|
+
};
|
|
69
|
+
if (isJsonMode()) {
|
|
70
|
+
printSuccess(result);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
logger.success(`Delete complete: ${String(archived)} archived, ${String(failed)} failed.`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
const cliErr = toCliError(err);
|
|
78
|
+
printError(cliErr.code, cliErr.message);
|
|
79
|
+
process.exitCode = cliErr.exitCode;
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=delete.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete.js","sourceRoot":"","sources":["../../../src/commands/database/delete.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* notion-cli db export <db-id> --out <file.csv>
|
|
3
|
+
*
|
|
4
|
+
* Export an entire Notion database to a CSV file.
|
|
5
|
+
* Fetches all pages with pagination and writes to file or stdout.
|
|
6
|
+
*
|
|
7
|
+
* This command is idempotent and read-only.
|
|
8
|
+
*/
|
|
9
|
+
import { type Command } from 'commander';
|
|
10
|
+
export declare function registerDbExportCommand(db: Command): void;
|
|
11
|
+
//# sourceMappingURL=export.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../../src/commands/database/export.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAYzC,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,CAoEzD"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* notion-cli db export <db-id> --out <file.csv>
|
|
3
|
+
*
|
|
4
|
+
* Export an entire Notion database to a CSV file.
|
|
5
|
+
* Fetches all pages with pagination and writes to file or stdout.
|
|
6
|
+
*
|
|
7
|
+
* This command is idempotent and read-only.
|
|
8
|
+
*/
|
|
9
|
+
import {} from 'commander';
|
|
10
|
+
import { writeFileSync } from 'node:fs';
|
|
11
|
+
import { getClient, resolveDataSourceId } from '../../lib/client.js';
|
|
12
|
+
import { rowsToCsv } from '../../lib/csv.js';
|
|
13
|
+
import { printSuccess, printError } from '../../lib/output.js';
|
|
14
|
+
import { withRateLimit } from '../../lib/rate-limit.js';
|
|
15
|
+
import { parseNotionId } from '../../utils/id.js';
|
|
16
|
+
import {} from '../../lib/types.js';
|
|
17
|
+
import { toCliError } from '../../lib/errors.js';
|
|
18
|
+
import * as logger from '../../utils/logger.js';
|
|
19
|
+
export function registerDbExportCommand(db) {
|
|
20
|
+
db.command('export')
|
|
21
|
+
.description('Export full Notion database to CSV.')
|
|
22
|
+
.argument('<db-id>', 'Notion database ID or URL')
|
|
23
|
+
.option('-o, --out <file>', 'Output CSV file path (stdout if omitted)')
|
|
24
|
+
.action(async (rawId, cmdOpts) => {
|
|
25
|
+
try {
|
|
26
|
+
const opts = db.optsWithGlobals();
|
|
27
|
+
const rawIdParsed = parseNotionId(rawId);
|
|
28
|
+
const client = getClient(opts.token);
|
|
29
|
+
// Resolve db ID to data source ID
|
|
30
|
+
const dbId = await resolveDataSourceId(client, rawIdParsed);
|
|
31
|
+
// Fetch all rows with pagination
|
|
32
|
+
const allResults = [];
|
|
33
|
+
let cursor;
|
|
34
|
+
let hasMore = true;
|
|
35
|
+
while (hasMore) {
|
|
36
|
+
const response = await withRateLimit(() => client.dataSources.query({
|
|
37
|
+
data_source_id: dbId,
|
|
38
|
+
page_size: 100,
|
|
39
|
+
start_cursor: cursor,
|
|
40
|
+
}), 'dataSources.query');
|
|
41
|
+
allResults.push(...response.results);
|
|
42
|
+
hasMore = response.has_more;
|
|
43
|
+
cursor = response.next_cursor ?? undefined;
|
|
44
|
+
logger.debug(`Fetched ${String(allResults.length)} rows so far...`);
|
|
45
|
+
}
|
|
46
|
+
// Extract property names
|
|
47
|
+
const propertyNames = allResults.length > 0
|
|
48
|
+
? Object.keys(allResults[0]?.['properties'] ?? {})
|
|
49
|
+
: [];
|
|
50
|
+
// Generate CSV
|
|
51
|
+
const csv = rowsToCsv(allResults, propertyNames);
|
|
52
|
+
// Write output
|
|
53
|
+
if (cmdOpts.out !== undefined) {
|
|
54
|
+
writeFileSync(cmdOpts.out, csv, 'utf-8');
|
|
55
|
+
printSuccess({
|
|
56
|
+
databaseId: dbId,
|
|
57
|
+
file: cmdOpts.out,
|
|
58
|
+
rowCount: allResults.length,
|
|
59
|
+
columns: propertyNames,
|
|
60
|
+
});
|
|
61
|
+
logger.success(`Exported ${String(allResults.length)} rows to ${cmdOpts.out}`);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
process.stdout.write(csv);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
const cliErr = toCliError(err);
|
|
69
|
+
printError(cliErr.code, cliErr.message);
|
|
70
|
+
process.exitCode = cliErr.exitCode;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=export.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export.js","sourceRoot":"","sources":["../../../src/commands/database/export.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* notion-cli db insert <db-id> --file <file.csv>
|
|
3
|
+
*
|
|
4
|
+
* Insert CSV rows as new pages in a Notion database.
|
|
5
|
+
* All rows must NOT have a _notion_id column value.
|
|
6
|
+
*
|
|
7
|
+
* This command is NOT idempotent (creates new pages each run).
|
|
8
|
+
*/
|
|
9
|
+
import { type Command } from 'commander';
|
|
10
|
+
export declare function registerDbInsertCommand(db: Command): void;
|
|
11
|
+
//# sourceMappingURL=insert.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"insert.d.ts","sourceRoot":"","sources":["../../../src/commands/database/insert.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAczC,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,CA6FzD"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* notion-cli db insert <db-id> --file <file.csv>
|
|
3
|
+
*
|
|
4
|
+
* Insert CSV rows as new pages in a Notion database.
|
|
5
|
+
* All rows must NOT have a _notion_id column value.
|
|
6
|
+
*
|
|
7
|
+
* This command is NOT idempotent (creates new pages each run).
|
|
8
|
+
*/
|
|
9
|
+
import {} from 'commander';
|
|
10
|
+
import { readFileSync } from 'node:fs';
|
|
11
|
+
import { getClient, resolveDataSourceId } from '../../lib/client.js';
|
|
12
|
+
import { csvToRows } from '../../lib/csv.js';
|
|
13
|
+
import { buildNotionProperties } from '../../lib/db-properties.js';
|
|
14
|
+
import { printSuccess, printError, isJsonMode } from '../../lib/output.js';
|
|
15
|
+
import { isDryRun } from '../../lib/safety.js';
|
|
16
|
+
import { withRateLimit } from '../../lib/rate-limit.js';
|
|
17
|
+
import { parseNotionId } from '../../utils/id.js';
|
|
18
|
+
import {} from '../../lib/types.js';
|
|
19
|
+
import { toCliError, ValidationError } from '../../lib/errors.js';
|
|
20
|
+
import * as logger from '../../utils/logger.js';
|
|
21
|
+
export function registerDbInsertCommand(db) {
|
|
22
|
+
db.command('insert')
|
|
23
|
+
.description('Insert CSV rows as new pages into a Notion database.')
|
|
24
|
+
.argument('<db-id>', 'Notion database ID or URL')
|
|
25
|
+
.requiredOption('-f, --file <path>', 'Path to CSV file')
|
|
26
|
+
.action(async (rawId, cmdOpts) => {
|
|
27
|
+
try {
|
|
28
|
+
const opts = db.optsWithGlobals();
|
|
29
|
+
const rawIdParsed = parseNotionId(rawId);
|
|
30
|
+
const client = getClient(opts.token);
|
|
31
|
+
const dbId = await resolveDataSourceId(client, rawIdParsed);
|
|
32
|
+
const csvContent = readFileSync(cmdOpts.file, 'utf-8');
|
|
33
|
+
const rows = csvToRows(csvContent);
|
|
34
|
+
if (rows.length === 0) {
|
|
35
|
+
throw new ValidationError('CSV file contains no data rows.');
|
|
36
|
+
}
|
|
37
|
+
const rowsWithId = rows.filter((r) => r.id !== undefined);
|
|
38
|
+
if (rowsWithId.length > 0) {
|
|
39
|
+
throw new ValidationError(`All rows must be new (no _notion_id). Found ${String(rowsWithId.length)} row(s) with _notion_id. Use "db update" for existing rows.`);
|
|
40
|
+
}
|
|
41
|
+
const dataSource = await withRateLimit(() => client.dataSources.retrieve({ data_source_id: dbId }), 'dataSources.retrieve');
|
|
42
|
+
const schemaProps = dataSource.properties;
|
|
43
|
+
logger.info(`Insert: ${String(rows.length)} new rows to create.`);
|
|
44
|
+
if (isDryRun(opts.dryRun)) {
|
|
45
|
+
if (isJsonMode()) {
|
|
46
|
+
printSuccess({
|
|
47
|
+
databaseId: dbId,
|
|
48
|
+
toCreate: rows.length,
|
|
49
|
+
dryRun: true,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
logger.info(`Dry run: Would insert ${String(rows.length)} new rows into database ${dbId}.`);
|
|
54
|
+
}
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
let created = 0;
|
|
58
|
+
let failed = 0;
|
|
59
|
+
await Promise.all(rows.map(async (row) => {
|
|
60
|
+
try {
|
|
61
|
+
const properties = buildNotionProperties(row.properties, schemaProps);
|
|
62
|
+
await withRateLimit(() => client.pages.create({
|
|
63
|
+
parent: { database_id: rawIdParsed },
|
|
64
|
+
properties: properties,
|
|
65
|
+
}), 'pages.create');
|
|
66
|
+
created++;
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
failed++;
|
|
70
|
+
logger.warn(`Failed to create row: ${String(err)}`);
|
|
71
|
+
}
|
|
72
|
+
}));
|
|
73
|
+
const result = {
|
|
74
|
+
databaseId: dbId,
|
|
75
|
+
created,
|
|
76
|
+
failed,
|
|
77
|
+
total: rows.length,
|
|
78
|
+
};
|
|
79
|
+
if (isJsonMode()) {
|
|
80
|
+
printSuccess(result);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
logger.success(`Insert complete: ${String(created)} created, ${String(failed)} failed.`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
const cliErr = toCliError(err);
|
|
88
|
+
printError(cliErr.code, cliErr.message);
|
|
89
|
+
process.exitCode = cliErr.exitCode;
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=insert.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"insert.js","sourceRoot":"","sources":["../../../src/commands/database/insert.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* notion-cli db list
|
|
3
|
+
*
|
|
4
|
+
* List all Notion databases accessible to the integration.
|
|
5
|
+
*
|
|
6
|
+
* This command is idempotent and read-only.
|
|
7
|
+
*/
|
|
8
|
+
import { type Command } from 'commander';
|
|
9
|
+
export declare function registerDbListCommand(db: Command): void;
|
|
10
|
+
//# sourceMappingURL=list.d.ts.map
|