@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.
Files changed (134) hide show
  1. package/README.md +245 -0
  2. package/dist/commands/database/create.d.ts +8 -0
  3. package/dist/commands/database/create.d.ts.map +1 -0
  4. package/dist/commands/database/create.js +71 -0
  5. package/dist/commands/database/create.js.map +1 -0
  6. package/dist/commands/database/delete.d.ts +10 -0
  7. package/dist/commands/database/delete.d.ts.map +1 -0
  8. package/dist/commands/database/delete.js +83 -0
  9. package/dist/commands/database/delete.js.map +1 -0
  10. package/dist/commands/database/export.d.ts +11 -0
  11. package/dist/commands/database/export.d.ts.map +1 -0
  12. package/dist/commands/database/export.js +74 -0
  13. package/dist/commands/database/export.js.map +1 -0
  14. package/dist/commands/database/insert.d.ts +11 -0
  15. package/dist/commands/database/insert.d.ts.map +1 -0
  16. package/dist/commands/database/insert.js +93 -0
  17. package/dist/commands/database/insert.js.map +1 -0
  18. package/dist/commands/database/list.d.ts +10 -0
  19. package/dist/commands/database/list.d.ts.map +1 -0
  20. package/dist/commands/database/list.js +80 -0
  21. package/dist/commands/database/list.js.map +1 -0
  22. package/dist/commands/database/query.d.ts +10 -0
  23. package/dist/commands/database/query.d.ts.map +1 -0
  24. package/dist/commands/database/query.js +77 -0
  25. package/dist/commands/database/query.js.map +1 -0
  26. package/dist/commands/database/schema.d.ts +11 -0
  27. package/dist/commands/database/schema.d.ts.map +1 -0
  28. package/dist/commands/database/schema.js +76 -0
  29. package/dist/commands/database/schema.js.map +1 -0
  30. package/dist/commands/database/update.d.ts +11 -0
  31. package/dist/commands/database/update.d.ts.map +1 -0
  32. package/dist/commands/database/update.js +105 -0
  33. package/dist/commands/database/update.js.map +1 -0
  34. package/dist/commands/page/create.d.ts +11 -0
  35. package/dist/commands/page/create.d.ts.map +1 -0
  36. package/dist/commands/page/create.js +102 -0
  37. package/dist/commands/page/create.js.map +1 -0
  38. package/dist/commands/page/list.d.ts +10 -0
  39. package/dist/commands/page/list.d.ts.map +1 -0
  40. package/dist/commands/page/list.js +87 -0
  41. package/dist/commands/page/list.js.map +1 -0
  42. package/dist/commands/page/patch.d.ts +21 -0
  43. package/dist/commands/page/patch.d.ts.map +1 -0
  44. package/dist/commands/page/patch.js +156 -0
  45. package/dist/commands/page/patch.js.map +1 -0
  46. package/dist/commands/page/read.d.ts +10 -0
  47. package/dist/commands/page/read.d.ts.map +1 -0
  48. package/dist/commands/page/read.js +86 -0
  49. package/dist/commands/page/read.js.map +1 -0
  50. package/dist/commands/page/write-properties.d.ts +15 -0
  51. package/dist/commands/page/write-properties.d.ts.map +1 -0
  52. package/dist/commands/page/write-properties.js +128 -0
  53. package/dist/commands/page/write-properties.js.map +1 -0
  54. package/dist/commands/page/write.d.ts +14 -0
  55. package/dist/commands/page/write.d.ts.map +1 -0
  56. package/dist/commands/page/write.js +109 -0
  57. package/dist/commands/page/write.js.map +1 -0
  58. package/dist/commands/search.d.ts +18 -0
  59. package/dist/commands/search.d.ts.map +1 -0
  60. package/dist/commands/search.js +129 -0
  61. package/dist/commands/search.js.map +1 -0
  62. package/dist/index.d.ts +37 -0
  63. package/dist/index.d.ts.map +1 -0
  64. package/dist/index.js +121 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/lib/block-patch.d.ts +61 -0
  67. package/dist/lib/block-patch.d.ts.map +1 -0
  68. package/dist/lib/block-patch.js +181 -0
  69. package/dist/lib/block-patch.js.map +1 -0
  70. package/dist/lib/client.d.ts +17 -0
  71. package/dist/lib/client.d.ts.map +1 -0
  72. package/dist/lib/client.js +63 -0
  73. package/dist/lib/client.js.map +1 -0
  74. package/dist/lib/config.d.ts +19 -0
  75. package/dist/lib/config.d.ts.map +1 -0
  76. package/dist/lib/config.js +65 -0
  77. package/dist/lib/config.js.map +1 -0
  78. package/dist/lib/csv.d.ts +45 -0
  79. package/dist/lib/csv.d.ts.map +1 -0
  80. package/dist/lib/csv.js +262 -0
  81. package/dist/lib/csv.js.map +1 -0
  82. package/dist/lib/db-properties.d.ts +11 -0
  83. package/dist/lib/db-properties.d.ts.map +1 -0
  84. package/dist/lib/db-properties.js +25 -0
  85. package/dist/lib/db-properties.js.map +1 -0
  86. package/dist/lib/errors.d.ts +34 -0
  87. package/dist/lib/errors.d.ts.map +1 -0
  88. package/dist/lib/errors.js +86 -0
  89. package/dist/lib/errors.js.map +1 -0
  90. package/dist/lib/file-upload.d.ts +25 -0
  91. package/dist/lib/file-upload.d.ts.map +1 -0
  92. package/dist/lib/file-upload.js +90 -0
  93. package/dist/lib/file-upload.js.map +1 -0
  94. package/dist/lib/markdown.d.ts +79 -0
  95. package/dist/lib/markdown.d.ts.map +1 -0
  96. package/dist/lib/markdown.js +320 -0
  97. package/dist/lib/markdown.js.map +1 -0
  98. package/dist/lib/output.d.ts +20 -0
  99. package/dist/lib/output.d.ts.map +1 -0
  100. package/dist/lib/output.js +67 -0
  101. package/dist/lib/output.js.map +1 -0
  102. package/dist/lib/patch.d.ts +23 -0
  103. package/dist/lib/patch.d.ts.map +1 -0
  104. package/dist/lib/patch.js +72 -0
  105. package/dist/lib/patch.js.map +1 -0
  106. package/dist/lib/rate-limit.d.ts +9 -0
  107. package/dist/lib/rate-limit.d.ts.map +1 -0
  108. package/dist/lib/rate-limit.js +67 -0
  109. package/dist/lib/rate-limit.js.map +1 -0
  110. package/dist/lib/safety.d.ts +17 -0
  111. package/dist/lib/safety.d.ts.map +1 -0
  112. package/dist/lib/safety.js +60 -0
  113. package/dist/lib/safety.js.map +1 -0
  114. package/dist/lib/types.d.ts +138 -0
  115. package/dist/lib/types.d.ts.map +1 -0
  116. package/dist/lib/types.js +13 -0
  117. package/dist/lib/types.js.map +1 -0
  118. package/dist/lib/validator.d.ts +33 -0
  119. package/dist/lib/validator.d.ts.map +1 -0
  120. package/dist/lib/validator.js +68 -0
  121. package/dist/lib/validator.js.map +1 -0
  122. package/dist/utils/id.d.ts +14 -0
  123. package/dist/utils/id.d.ts.map +1 -0
  124. package/dist/utils/id.js +33 -0
  125. package/dist/utils/id.js.map +1 -0
  126. package/dist/utils/logger.d.ts +20 -0
  127. package/dist/utils/logger.d.ts.map +1 -0
  128. package/dist/utils/logger.js +43 -0
  129. package/dist/utils/logger.js.map +1 -0
  130. package/dist/utils/string.d.ts +14 -0
  131. package/dist/utils/string.d.ts.map +1 -0
  132. package/dist/utils/string.js +37 -0
  133. package/dist/utils/string.js.map +1 -0
  134. package/package.json +64 -0
@@ -0,0 +1,109 @@
1
+ /**
2
+ * notion-cli page write <page-id> --file <path>
3
+ *
4
+ * Replace a Notion page's content with Markdown from a file or stdin.
5
+ * Uses @tryfabric/martian to convert Markdown → Notion blocks.
6
+ *
7
+ * WARNING: This replaces ALL existing content on the page.
8
+ * Use `page patch` for partial edits.
9
+ *
10
+ * This command is NOT idempotent (replaces content).
11
+ */
12
+ import {} from 'commander';
13
+ import { readFileSync } from 'node:fs';
14
+ import { getClient } from '../../lib/client.js';
15
+ import { markdownToNotionBlocks, processImageUploads } from '../../lib/markdown.js';
16
+ import { printSuccess, printError, isJsonMode } from '../../lib/output.js';
17
+ import { isDryRun } from '../../lib/safety.js';
18
+ import { withRateLimit } from '../../lib/rate-limit.js';
19
+ import { parseNotionId } from '../../utils/id.js';
20
+ import { unescapeString } from '../../utils/string.js';
21
+ import {} from '../../lib/types.js';
22
+ import { toCliError } from '../../lib/errors.js';
23
+ import { ValidationError } from '../../lib/errors.js';
24
+ import * as logger from '../../utils/logger.js';
25
+ export function registerPageWriteCommand(page) {
26
+ page
27
+ .command('write')
28
+ .description('Replace a Notion page content with Markdown. Reads from --file or stdin.')
29
+ .argument('<page-id>', 'Notion page ID or URL')
30
+ .option('-f, --file <path>', 'Path to Markdown file')
31
+ .option('--content <markdown>', 'Inline Markdown content')
32
+ .action(async (rawId, cmdOpts) => {
33
+ try {
34
+ const opts = page.optsWithGlobals();
35
+ const pageId = parseNotionId(rawId);
36
+ const client = getClient(opts.token);
37
+ // Get markdown content from file, --content, or stdin
38
+ const markdown = await resolveContent(cmdOpts.file, cmdOpts.content);
39
+ // Convert to Notion blocks
40
+ let blocks = markdownToNotionBlocks(markdown);
41
+ // Process and upload file:// images
42
+ blocks = await processImageUploads(client, blocks);
43
+ logger.debug(`Will replace page content with ${String(blocks.length)} blocks.`);
44
+ // Dry run check
45
+ if (isDryRun(opts.dryRun)) {
46
+ if (isJsonMode()) {
47
+ printSuccess({
48
+ pageId,
49
+ blocksWritten: blocks.length,
50
+ dryRun: true,
51
+ });
52
+ }
53
+ return;
54
+ }
55
+ // Clear existing content using erase_content: true
56
+ await withRateLimit(() => client.pages.update({
57
+ page_id: pageId,
58
+ erase_content: true,
59
+ }), 'pages.update (erase_content)');
60
+ // Append new blocks (in chunks of 100 — Notion API limit)
61
+ let totalWritten = 0;
62
+ for (let i = 0; i < blocks.length; i += 100) {
63
+ const chunk = blocks.slice(i, i + 100);
64
+ await withRateLimit(() => client.blocks.children.append({
65
+ block_id: pageId,
66
+ children: chunk,
67
+ }), 'blocks.children.append');
68
+ totalWritten += chunk.length;
69
+ }
70
+ const result = {
71
+ pageId,
72
+ blocksWritten: totalWritten,
73
+ };
74
+ if (isJsonMode()) {
75
+ printSuccess(result);
76
+ }
77
+ }
78
+ catch (err) {
79
+ const cliErr = toCliError(err);
80
+ printError(cliErr.code, cliErr.message);
81
+ process.exitCode = cliErr.exitCode;
82
+ }
83
+ });
84
+ }
85
+ /**
86
+ * Resolve Markdown content from file, inline, or stdin.
87
+ */
88
+ async function resolveContent(filePath, inlineContent) {
89
+ if (filePath !== undefined) {
90
+ return readFileSync(filePath, 'utf-8');
91
+ }
92
+ if (inlineContent !== undefined) {
93
+ return unescapeString(inlineContent);
94
+ }
95
+ // Read from stdin
96
+ if (!process.stdin.isTTY) {
97
+ return readStdin();
98
+ }
99
+ throw new ValidationError('No content provided. Use --file, --content, or pipe via stdin.');
100
+ }
101
+ function readStdin() {
102
+ return new Promise((resolve, reject) => {
103
+ const chunks = [];
104
+ process.stdin.on('data', (chunk) => chunks.push(chunk));
105
+ process.stdin.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));
106
+ process.stdin.on('error', reject);
107
+ });
108
+ }
109
+ //# sourceMappingURL=write.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write.js","sourceRoot":"","sources":["../../../src/commands/page/write.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * notion-cli search <query>
3
+ *
4
+ * Unified search across all pages and databases accessible to the integration.
5
+ * Returns IDs, titles, URLs, and types — perfect for AI agents to discover
6
+ * content before reading/patching.
7
+ *
8
+ * Options:
9
+ * --type page|database Filter by object type
10
+ * --sort last_edited Sort by last edited time
11
+ * --limit N Max results (default 10)
12
+ * --cursor <cursor> Pagination cursor
13
+ *
14
+ * This command is idempotent and read-only.
15
+ */
16
+ import { type Command } from 'commander';
17
+ export declare function registerSearchCommand(program: Command): void;
18
+ //# sourceMappingURL=search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAQzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAyH5D"}
@@ -0,0 +1,129 @@
1
+ /**
2
+ * notion-cli search <query>
3
+ *
4
+ * Unified search across all pages and databases accessible to the integration.
5
+ * Returns IDs, titles, URLs, and types — perfect for AI agents to discover
6
+ * content before reading/patching.
7
+ *
8
+ * Options:
9
+ * --type page|database Filter by object type
10
+ * --sort last_edited Sort by last edited time
11
+ * --limit N Max results (default 10)
12
+ * --cursor <cursor> Pagination cursor
13
+ *
14
+ * This command is idempotent and read-only.
15
+ */
16
+ import {} from 'commander';
17
+ import { getClient } from '../lib/client.js';
18
+ import { printSuccess, printError, formatTable, isJsonMode } from '../lib/output.js';
19
+ import { withRateLimit } from '../lib/rate-limit.js';
20
+ import {} from '../lib/types.js';
21
+ import { toCliError, ValidationError } from '../lib/errors.js';
22
+ import * as logger from '../utils/logger.js';
23
+ export function registerSearchCommand(program) {
24
+ program
25
+ .command('search')
26
+ .description('Search across all Notion pages and databases.')
27
+ .argument('<query>', 'Search query text')
28
+ .option('--type <type>', 'Filter by type: page or database')
29
+ .option('--sort <direction>', 'Sort by last_edited_time: ascending or descending', 'descending')
30
+ .option('-l, --limit <n>', 'Maximum results to return', '10')
31
+ .option('--cursor <cursor>', 'Pagination cursor from a previous response')
32
+ .action(async (query, cmdOpts) => {
33
+ try {
34
+ const opts = program.optsWithGlobals();
35
+ const client = getClient(opts.token);
36
+ const limit = parseInt(cmdOpts.limit ?? '10', 10);
37
+ // Validate type filter
38
+ if (cmdOpts.type !== undefined && cmdOpts.type !== 'page' && cmdOpts.type !== 'database') {
39
+ throw new ValidationError('--type must be "page" or "database".');
40
+ }
41
+ // Build search params
42
+ const searchParams = {
43
+ query,
44
+ page_size: Math.min(limit, 100),
45
+ start_cursor: cmdOpts.cursor,
46
+ };
47
+ if (cmdOpts.type !== undefined) {
48
+ searchParams['filter'] = { value: cmdOpts.type, property: 'object' };
49
+ }
50
+ if (cmdOpts.sort !== undefined) {
51
+ searchParams['sort'] = {
52
+ direction: cmdOpts.sort,
53
+ timestamp: 'last_edited_time',
54
+ };
55
+ }
56
+ const response = await withRateLimit(() => client.search(searchParams), 'search');
57
+ const results = response.results.map((item) => {
58
+ const obj = item;
59
+ const objectType = obj['object'];
60
+ let title = 'Untitled';
61
+ if (objectType === 'page') {
62
+ const props = obj['properties'];
63
+ if (props !== undefined) {
64
+ for (const prop of Object.values(props)) {
65
+ if (prop['type'] === 'title') {
66
+ const titleArr = prop['title'];
67
+ if (titleArr !== undefined && titleArr.length > 0) {
68
+ title = titleArr[0]?.['plain_text'] ?? 'Untitled';
69
+ }
70
+ break;
71
+ }
72
+ }
73
+ }
74
+ }
75
+ else if (objectType === 'database') {
76
+ const titleArr = obj['title'];
77
+ if (titleArr !== undefined && titleArr.length > 0) {
78
+ title = titleArr[0]?.['plain_text'] ?? 'Untitled';
79
+ }
80
+ }
81
+ return {
82
+ id: item.id,
83
+ type: objectType,
84
+ title,
85
+ url: obj['url'] ?? '',
86
+ lastEditedTime: obj['last_edited_time'] ?? '',
87
+ };
88
+ });
89
+ const searchResults = {
90
+ results,
91
+ hasMore: response.has_more,
92
+ nextCursor: response.next_cursor ?? undefined,
93
+ };
94
+ if (isJsonMode()) {
95
+ printSuccess(searchResults, {
96
+ hasMore: response.has_more,
97
+ cursor: response.next_cursor ?? undefined,
98
+ totalCount: results.length,
99
+ });
100
+ }
101
+ else {
102
+ if (results.length === 0) {
103
+ logger.info('No results found.');
104
+ }
105
+ else {
106
+ for (const r of results) {
107
+ const table = formatTable([
108
+ ['ID', r.id],
109
+ ['Type', r.type],
110
+ ['Title', r.title],
111
+ ['URL', r.url],
112
+ ['Last edited', r.lastEditedTime],
113
+ ]);
114
+ process.stdout.write(`${table}\n\n`);
115
+ }
116
+ if (searchResults.hasMore) {
117
+ logger.info(`More results available. Use --cursor ${searchResults.nextCursor ?? ''}`);
118
+ }
119
+ }
120
+ }
121
+ }
122
+ catch (err) {
123
+ const cliErr = toCliError(err);
124
+ printError(cliErr.code, cliErr.message);
125
+ process.exitCode = cliErr.exitCode;
126
+ }
127
+ });
128
+ }
129
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * notion-cli — Read and edit Notion pages, databases, and blocks
4
+ * through Markdown and CSV. Designed for AI agent workflows.
5
+ *
6
+ * Usage:
7
+ * notion-cli search <query> Search pages & databases
8
+ * notion-cli page read <id> Read page as Markdown
9
+ * notion-cli page create --parent <id> --file <path> Create page from Markdown
10
+ * notion-cli page write <id> [--file <path>] Replace page content
11
+ * notion-cli page write-properties <id> --file <f> Update page properties from CSV
12
+ * notion-cli page list [--query <text>] List pages
13
+ * notion-cli db query <id> [--filter <json>] Query database → CSV
14
+ * notion-cli db export <id> --out <file.csv> Export database → CSV
15
+ * notion-cli db insert <id> --file <file.csv> Insert CSV rows as new pages
16
+ * notion-cli db update <id> --file <file.csv> Update existing pages from CSV
17
+ * notion-cli db delete <id> --ids <id1,id2> Archive (delete) pages by ID
18
+ * notion-cli db list List databases
19
+ * notion-cli db schema <id> Show DB schema
20
+ *
21
+ * Global flags:
22
+ * --json Structured JSON output (for AI agents)
23
+ * --token Override Notion API token
24
+ * --dry-run Preview changes without executing
25
+ * --verbose Debug output to stderr
26
+ * --no-color Disable colored output
27
+ *
28
+ * Authentication:
29
+ * Set NOTION_TOKEN env var, or use --token, or create ~/.notion-cli.json
30
+ *
31
+ * AI Agent Usage:
32
+ * All commands support --json for parseable output.
33
+ * Data goes to stdout; status/progress goes to stderr.
34
+ * Exit codes: 0=success, 1=error, 2=validation, 3=auth, 4=not_found, 5=rate_limited
35
+ */
36
+ export {};
37
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG"}
package/dist/index.js ADDED
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * notion-cli — Read and edit Notion pages, databases, and blocks
4
+ * through Markdown and CSV. Designed for AI agent workflows.
5
+ *
6
+ * Usage:
7
+ * notion-cli search <query> Search pages & databases
8
+ * notion-cli page read <id> Read page as Markdown
9
+ * notion-cli page create --parent <id> --file <path> Create page from Markdown
10
+ * notion-cli page write <id> [--file <path>] Replace page content
11
+ * notion-cli page write-properties <id> --file <f> Update page properties from CSV
12
+ * notion-cli page list [--query <text>] List pages
13
+ * notion-cli db query <id> [--filter <json>] Query database → CSV
14
+ * notion-cli db export <id> --out <file.csv> Export database → CSV
15
+ * notion-cli db insert <id> --file <file.csv> Insert CSV rows as new pages
16
+ * notion-cli db update <id> --file <file.csv> Update existing pages from CSV
17
+ * notion-cli db delete <id> --ids <id1,id2> Archive (delete) pages by ID
18
+ * notion-cli db list List databases
19
+ * notion-cli db schema <id> Show DB schema
20
+ *
21
+ * Global flags:
22
+ * --json Structured JSON output (for AI agents)
23
+ * --token Override Notion API token
24
+ * --dry-run Preview changes without executing
25
+ * --verbose Debug output to stderr
26
+ * --no-color Disable colored output
27
+ *
28
+ * Authentication:
29
+ * Set NOTION_TOKEN env var, or use --token, or create ~/.notion-cli.json
30
+ *
31
+ * AI Agent Usage:
32
+ * All commands support --json for parseable output.
33
+ * Data goes to stdout; status/progress goes to stderr.
34
+ * Exit codes: 0=success, 1=error, 2=validation, 3=auth, 4=not_found, 5=rate_limited
35
+ */
36
+ import { Command } from 'commander';
37
+ import { setJsonMode } from './lib/output.js';
38
+ import { setVerbose } from './utils/logger.js';
39
+ import { printError } from './lib/output.js';
40
+ import { toCliError } from './lib/errors.js';
41
+ // Page commands
42
+ import { registerPageReadCommand } from './commands/page/read.js';
43
+ import { registerPageCreateCommand } from './commands/page/create.js';
44
+ import { registerPageWriteCommand } from './commands/page/write.js';
45
+ import { registerPageWritePropertiesCommand } from './commands/page/write-properties.js';
46
+ import { registerPagePatchCommand } from './commands/page/patch.js';
47
+ import { registerPageListCommand } from './commands/page/list.js';
48
+ // Database commands
49
+ import { registerDbQueryCommand } from './commands/database/query.js';
50
+ import { registerDbExportCommand } from './commands/database/export.js';
51
+ import { registerDbInsertCommand } from './commands/database/insert.js';
52
+ import { registerDbUpdateCommand } from './commands/database/update.js';
53
+ import { registerDbDeleteCommand } from './commands/database/delete.js';
54
+ import { registerDbListCommand } from './commands/database/list.js';
55
+ import { registerDbCreateCommand } from './commands/database/create.js';
56
+ import { registerDbSchemaCommand } from './commands/database/schema.js';
57
+ // Search command
58
+ import { registerSearchCommand } from './commands/search.js';
59
+ const program = new Command();
60
+ program
61
+ .name('notion-cli')
62
+ .version('1.0.0')
63
+ .description('CLI for reading and editing Notion entries through Markdown and CSV. AI agent friendly.')
64
+ .option('--json', 'Output as structured JSON (for AI agents)')
65
+ .option('--token <token>', 'Notion API integration token')
66
+ .option('--dry-run', 'Preview changes without executing writes')
67
+ .option('-v, --verbose', 'Enable verbose/debug output')
68
+ .option('--no-color', 'Disable colored output')
69
+ .hook('preAction', (_thisCommand, actionCommand) => {
70
+ const opts = actionCommand.optsWithGlobals();
71
+ if (opts.json === true) {
72
+ setJsonMode(true);
73
+ }
74
+ if (opts.verbose === true) {
75
+ setVerbose(true);
76
+ }
77
+ });
78
+ // ── Page subcommand group ──────────────────────────────────────────
79
+ const page = program
80
+ .command('page')
81
+ .description('Read, write, and create Notion pages.');
82
+ registerPageReadCommand(page);
83
+ registerPageCreateCommand(page);
84
+ registerPageWriteCommand(page);
85
+ registerPageWritePropertiesCommand(page);
86
+ registerPagePatchCommand(page);
87
+ registerPageListCommand(page);
88
+ // ── Database subcommand group ──────────────────────────────────────
89
+ const db = program
90
+ .command('db')
91
+ .description('Query, export, import, and inspect Notion databases.');
92
+ registerDbQueryCommand(db);
93
+ registerDbExportCommand(db);
94
+ registerDbInsertCommand(db);
95
+ registerDbUpdateCommand(db);
96
+ registerDbDeleteCommand(db);
97
+ registerDbListCommand(db);
98
+ registerDbCreateCommand(db);
99
+ registerDbSchemaCommand(db);
100
+ // ── Search command (top-level) ─────────────────────────────────────
101
+ registerSearchCommand(program);
102
+ // ── Global error handler ───────────────────────────────────────────
103
+ program.exitOverride();
104
+ async function main() {
105
+ try {
106
+ await program.parseAsync(process.argv);
107
+ }
108
+ catch (err) {
109
+ // Commander throws for --help and --version, don't treat as errors
110
+ const commanderErr = err;
111
+ if (commanderErr.code === 'commander.helpDisplayed' ||
112
+ commanderErr.code === 'commander.version') {
113
+ return;
114
+ }
115
+ const cliErr = toCliError(err);
116
+ printError(cliErr.code, cliErr.message);
117
+ process.exitCode = cliErr.exitCode;
118
+ }
119
+ }
120
+ void main();
121
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Surgical block-level patching.
3
+ *
4
+ * Instead of deleting all blocks and recreating them, this module
5
+ * enables targeted edits by tracking which markdown lines correspond
6
+ * to which Notion blocks.
7
+ *
8
+ * Key concepts:
9
+ * - BlockLineMapping: Maps a block ID to its line range in the markdown
10
+ * - PatchPlan: Describes which blocks to delete and what to insert
11
+ *
12
+ * The flow:
13
+ * 1. Fetch MdBlocks from Notion (via notion-to-md)
14
+ * 2. Build line mapping via mdBlocksToMarkdown (unified converter in markdown.ts)
15
+ * 3. Given a line range edit, compute which blocks are affected
16
+ * 4. Execute the plan: delete affected blocks, insert new content
17
+ */
18
+ import { type BlockLineMapping, type PatchPlan } from './types.js';
19
+ export { mdBlocksToMarkdown as buildBlockLineMap } from './markdown.js';
20
+ /**
21
+ * Compute a patch plan given block mappings and a line range to replace.
22
+ *
23
+ * Determines which blocks need to be deleted and where to insert new content.
24
+ *
25
+ * Rules:
26
+ * - Blocks fully contained in [startLine, endLine] are deleted
27
+ * - Blocks that partially overlap are also deleted (they need to be reconstructed)
28
+ * - New content is inserted after the last unaffected block before the range
29
+ *
30
+ * @param mappings - Block-to-line mappings from buildBlockLineMap
31
+ * @param startLine - 1-indexed start line of the edit (inclusive)
32
+ * @param endLine - 1-indexed end line of the edit (inclusive)
33
+ * @param newContent - The replacement markdown content
34
+ * @returns A plan describing deletions and insertions
35
+ */
36
+ export declare function computePatchPlan(mappings: readonly BlockLineMapping[], startLine: number, endLine: number, newContent: string): PatchPlan;
37
+ /**
38
+ * Find a block mapping by line number.
39
+ *
40
+ * @param mappings - Block mappings to search
41
+ * @param line - The line number to find
42
+ * @returns The block containing this line, or undefined
43
+ */
44
+ export declare function findBlockAtLine(mappings: readonly BlockLineMapping[], line: number): BlockLineMapping | undefined;
45
+ /**
46
+ * Get content that should be preserved from partially affected blocks.
47
+ *
48
+ * When a block partially overlaps with the edit range, we need to keep
49
+ * the lines that are outside the edit range.
50
+ *
51
+ * @param mapping - The block mapping
52
+ * @param markdown - Full markdown content
53
+ * @param startLine - Edit start line
54
+ * @param endLine - Edit end line
55
+ * @returns Lines to preserve (before and after the edit range)
56
+ */
57
+ export declare function getPreservedContent(mapping: BlockLineMapping, markdown: string, startLine: number, endLine: number): {
58
+ before: string;
59
+ after: string;
60
+ };
61
+ //# sourceMappingURL=block-patch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"block-patch.d.ts","sourceRoot":"","sources":["../../src/lib/block-patch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,SAAS,EAEf,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,kBAAkB,IAAI,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAExE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,SAAS,gBAAgB,EAAE,EACrC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,SAAS,CAsCX;AA0FD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,SAAS,gBAAgB,EAAE,EACrC,IAAI,EAAE,MAAM,GACX,gBAAgB,GAAG,SAAS,CAY9B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,gBAAgB,EACzB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAmBnC"}