@catafal/notion-cli 5.9.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 (162) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +552 -0
  3. package/bin/dev +17 -0
  4. package/bin/dev.cmd +3 -0
  5. package/bin/run +14 -0
  6. package/bin/run.cmd +3 -0
  7. package/dist/base-command.d.ts +73 -0
  8. package/dist/base-command.js +179 -0
  9. package/dist/base-flags.d.ts +14 -0
  10. package/dist/base-flags.js +59 -0
  11. package/dist/cache.d.ts +84 -0
  12. package/dist/cache.js +351 -0
  13. package/dist/commands/append.d.ts +37 -0
  14. package/dist/commands/append.js +120 -0
  15. package/dist/commands/batch/delete.d.ts +42 -0
  16. package/dist/commands/batch/delete.js +199 -0
  17. package/dist/commands/batch/retrieve.d.ts +43 -0
  18. package/dist/commands/batch/retrieve.js +272 -0
  19. package/dist/commands/block/append.d.ts +42 -0
  20. package/dist/commands/block/append.js +219 -0
  21. package/dist/commands/block/delete.d.ts +30 -0
  22. package/dist/commands/block/delete.js +97 -0
  23. package/dist/commands/block/retrieve/children.d.ts +31 -0
  24. package/dist/commands/block/retrieve/children.js +177 -0
  25. package/dist/commands/block/retrieve.d.ts +30 -0
  26. package/dist/commands/block/retrieve.js +101 -0
  27. package/dist/commands/block/update.d.ts +45 -0
  28. package/dist/commands/block/update.js +242 -0
  29. package/dist/commands/bookmark/list.d.ts +30 -0
  30. package/dist/commands/bookmark/list.js +60 -0
  31. package/dist/commands/bookmark/remove.d.ts +26 -0
  32. package/dist/commands/bookmark/remove.js +47 -0
  33. package/dist/commands/bookmark/set.d.ts +29 -0
  34. package/dist/commands/bookmark/set.js +96 -0
  35. package/dist/commands/browse.d.ts +13 -0
  36. package/dist/commands/browse.js +44 -0
  37. package/dist/commands/cache/info.d.ts +19 -0
  38. package/dist/commands/cache/info.js +145 -0
  39. package/dist/commands/config/set-token.d.ts +22 -0
  40. package/dist/commands/config/set-token.js +137 -0
  41. package/dist/commands/daily/index.d.ts +32 -0
  42. package/dist/commands/daily/index.js +135 -0
  43. package/dist/commands/daily/setup.d.ts +42 -0
  44. package/dist/commands/daily/setup.js +149 -0
  45. package/dist/commands/db/create.d.ts +31 -0
  46. package/dist/commands/db/create.js +124 -0
  47. package/dist/commands/db/query.d.ts +41 -0
  48. package/dist/commands/db/query.js +360 -0
  49. package/dist/commands/db/retrieve.d.ts +33 -0
  50. package/dist/commands/db/retrieve.js +134 -0
  51. package/dist/commands/db/schema.d.ts +32 -0
  52. package/dist/commands/db/schema.js +308 -0
  53. package/dist/commands/db/update.d.ts +31 -0
  54. package/dist/commands/db/update.js +117 -0
  55. package/dist/commands/doctor.d.ts +50 -0
  56. package/dist/commands/doctor.js +420 -0
  57. package/dist/commands/init.d.ts +65 -0
  58. package/dist/commands/init.js +479 -0
  59. package/dist/commands/list.d.ts +29 -0
  60. package/dist/commands/list.js +219 -0
  61. package/dist/commands/open.d.ts +29 -0
  62. package/dist/commands/open.js +100 -0
  63. package/dist/commands/page/create.d.ts +33 -0
  64. package/dist/commands/page/create.js +261 -0
  65. package/dist/commands/page/delete.d.ts +36 -0
  66. package/dist/commands/page/delete.js +107 -0
  67. package/dist/commands/page/export.d.ts +38 -0
  68. package/dist/commands/page/export.js +120 -0
  69. package/dist/commands/page/retrieve/property_item.d.ts +24 -0
  70. package/dist/commands/page/retrieve/property_item.js +75 -0
  71. package/dist/commands/page/retrieve.d.ts +36 -0
  72. package/dist/commands/page/retrieve.js +244 -0
  73. package/dist/commands/page/update.d.ts +34 -0
  74. package/dist/commands/page/update.js +184 -0
  75. package/dist/commands/quick.d.ts +35 -0
  76. package/dist/commands/quick.js +168 -0
  77. package/dist/commands/search.d.ts +43 -0
  78. package/dist/commands/search.js +361 -0
  79. package/dist/commands/stats.d.ts +35 -0
  80. package/dist/commands/stats.js +274 -0
  81. package/dist/commands/sync.d.ts +24 -0
  82. package/dist/commands/sync.js +183 -0
  83. package/dist/commands/template/get.d.ts +28 -0
  84. package/dist/commands/template/get.js +59 -0
  85. package/dist/commands/template/list.d.ts +32 -0
  86. package/dist/commands/template/list.js +62 -0
  87. package/dist/commands/template/remove.d.ts +27 -0
  88. package/dist/commands/template/remove.js +48 -0
  89. package/dist/commands/template/save.d.ts +32 -0
  90. package/dist/commands/template/save.js +92 -0
  91. package/dist/commands/template/use.d.ts +34 -0
  92. package/dist/commands/template/use.js +142 -0
  93. package/dist/commands/user/list.d.ts +27 -0
  94. package/dist/commands/user/list.js +99 -0
  95. package/dist/commands/user/retrieve/bot.d.ts +28 -0
  96. package/dist/commands/user/retrieve/bot.js +96 -0
  97. package/dist/commands/user/retrieve.d.ts +30 -0
  98. package/dist/commands/user/retrieve.js +103 -0
  99. package/dist/commands/whoami.d.ts +19 -0
  100. package/dist/commands/whoami.js +175 -0
  101. package/dist/deduplication.d.ts +41 -0
  102. package/dist/deduplication.js +71 -0
  103. package/dist/envelope.d.ts +169 -0
  104. package/dist/envelope.js +257 -0
  105. package/dist/errors/enhanced-errors.d.ts +168 -0
  106. package/dist/errors/enhanced-errors.js +567 -0
  107. package/dist/errors/index.d.ts +18 -0
  108. package/dist/errors/index.js +33 -0
  109. package/dist/examples/cache-retry-examples.d.ts +64 -0
  110. package/dist/examples/cache-retry-examples.js +375 -0
  111. package/dist/helper.d.ts +102 -0
  112. package/dist/helper.js +885 -0
  113. package/dist/http-agent.d.ts +38 -0
  114. package/dist/http-agent.js +60 -0
  115. package/dist/index.d.ts +1 -0
  116. package/dist/index.js +4 -0
  117. package/dist/interface.d.ts +4 -0
  118. package/dist/interface.js +2 -0
  119. package/dist/notion.d.ts +144 -0
  120. package/dist/notion.js +547 -0
  121. package/dist/retry.d.ts +72 -0
  122. package/dist/retry.js +381 -0
  123. package/dist/utils/bookmarks.d.ts +32 -0
  124. package/dist/utils/bookmarks.js +98 -0
  125. package/dist/utils/daily-config.d.ts +22 -0
  126. package/dist/utils/daily-config.js +60 -0
  127. package/dist/utils/disk-cache.d.ts +80 -0
  128. package/dist/utils/disk-cache.js +291 -0
  129. package/dist/utils/fuzzy.d.ts +36 -0
  130. package/dist/utils/fuzzy.js +69 -0
  131. package/dist/utils/interactive-navigator.d.ts +63 -0
  132. package/dist/utils/interactive-navigator.js +123 -0
  133. package/dist/utils/markdown-to-blocks.d.ts +21 -0
  134. package/dist/utils/markdown-to-blocks.js +333 -0
  135. package/dist/utils/notion-resolver.d.ts +49 -0
  136. package/dist/utils/notion-resolver.js +278 -0
  137. package/dist/utils/notion-url-parser.d.ts +48 -0
  138. package/dist/utils/notion-url-parser.js +121 -0
  139. package/dist/utils/property-expander.d.ts +45 -0
  140. package/dist/utils/property-expander.js +323 -0
  141. package/dist/utils/schema-examples.d.ts +40 -0
  142. package/dist/utils/schema-examples.js +359 -0
  143. package/dist/utils/schema-extractor.d.ts +65 -0
  144. package/dist/utils/schema-extractor.js +235 -0
  145. package/dist/utils/shell-config.d.ts +30 -0
  146. package/dist/utils/shell-config.js +84 -0
  147. package/dist/utils/table-formatter.d.ts +36 -0
  148. package/dist/utils/table-formatter.js +125 -0
  149. package/dist/utils/templates.d.ts +30 -0
  150. package/dist/utils/templates.js +82 -0
  151. package/dist/utils/terminal-banner.d.ts +24 -0
  152. package/dist/utils/terminal-banner.js +34 -0
  153. package/dist/utils/token-validator.d.ts +42 -0
  154. package/dist/utils/token-validator.js +66 -0
  155. package/dist/utils/update-notifier.d.ts +26 -0
  156. package/dist/utils/update-notifier.js +54 -0
  157. package/dist/utils/workspace-cache.d.ts +58 -0
  158. package/dist/utils/workspace-cache.js +185 -0
  159. package/oclif.manifest.json +6471 -0
  160. package/package.json +118 -0
  161. package/scripts/banner.js +38 -0
  162. package/scripts/postinstall.js +44 -0
@@ -0,0 +1,272 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const table_formatter_1 = require("../../utils/table-formatter");
5
+ const notion = require("../../notion");
6
+ const helper_1 = require("../../helper");
7
+ const base_flags_1 = require("../../base-flags");
8
+ const errors_1 = require("../../errors");
9
+ const client_1 = require("@notionhq/client");
10
+ const readline = require("readline");
11
+ const notion_resolver_1 = require("../../utils/notion-resolver");
12
+ class BatchRetrieve extends core_1.Command {
13
+ /**
14
+ * Read IDs from stdin
15
+ */
16
+ async readStdin() {
17
+ return new Promise((resolve, reject) => {
18
+ const ids = [];
19
+ const rl = readline.createInterface({
20
+ input: process.stdin,
21
+ output: process.stdout,
22
+ terminal: false,
23
+ });
24
+ rl.on('line', (line) => {
25
+ const trimmed = line.trim();
26
+ if (trimmed) {
27
+ ids.push(trimmed);
28
+ }
29
+ });
30
+ rl.on('close', () => {
31
+ resolve(ids);
32
+ });
33
+ rl.on('error', (err) => {
34
+ reject(err);
35
+ });
36
+ // Timeout after 5 seconds if no input
37
+ setTimeout(() => {
38
+ rl.close();
39
+ resolve(ids);
40
+ }, 5000);
41
+ });
42
+ }
43
+ /**
44
+ * Retrieve a single resource and handle errors
45
+ */
46
+ async retrieveResource(id, type) {
47
+ try {
48
+ // Resolve URL/name/ID to clean Notion ID before API call
49
+ const resolvedId = await (0, notion_resolver_1.resolveNotionId)(id, type === 'database' ? 'database' : 'page');
50
+ let data;
51
+ switch (type) {
52
+ case 'page': {
53
+ const pageResponse = await notion.retrievePage({ page_id: resolvedId });
54
+ if (!(0, client_1.isFullPage)(pageResponse)) {
55
+ throw new errors_1.NotionCLIError(errors_1.NotionCLIErrorCode.API_ERROR, 'Received partial page response instead of full page', [], { attemptedId: id });
56
+ }
57
+ data = pageResponse;
58
+ break;
59
+ }
60
+ case 'block': {
61
+ const blockResponse = await notion.retrieveBlock(resolvedId);
62
+ if (!(0, client_1.isFullBlock)(blockResponse)) {
63
+ throw new errors_1.NotionCLIError(errors_1.NotionCLIErrorCode.API_ERROR, 'Received partial block response instead of full block', [], { attemptedId: id });
64
+ }
65
+ data = blockResponse;
66
+ break;
67
+ }
68
+ case 'database':
69
+ data = await notion.retrieveDataSource(resolvedId);
70
+ break;
71
+ default:
72
+ throw new errors_1.NotionCLIError(errors_1.NotionCLIErrorCode.VALIDATION_ERROR, `Invalid resource type: ${type}`, [], { userInput: type, resourceType: type });
73
+ }
74
+ return {
75
+ id,
76
+ success: true,
77
+ data,
78
+ };
79
+ }
80
+ catch (error) {
81
+ const cliError = error instanceof errors_1.NotionCLIError
82
+ ? error
83
+ : (0, errors_1.wrapNotionError)(error, {
84
+ attemptedId: id,
85
+ userInput: id
86
+ });
87
+ return {
88
+ id,
89
+ success: false,
90
+ error: cliError.code,
91
+ message: cliError.userMessage,
92
+ };
93
+ }
94
+ }
95
+ async run() {
96
+ const { args, flags } = await this.parse(BatchRetrieve);
97
+ try {
98
+ // Get IDs from args, flags, or stdin
99
+ let ids = [];
100
+ if (args.ids) {
101
+ // From positional argument
102
+ ids = args.ids.split(',').map(id => id.trim()).filter(id => id);
103
+ }
104
+ else if (flags.ids) {
105
+ // From --ids flag
106
+ ids = flags.ids.split(',').map(id => id.trim()).filter(id => id);
107
+ }
108
+ else if (!process.stdin.isTTY) {
109
+ // From stdin
110
+ ids = await this.readStdin();
111
+ }
112
+ if (ids.length === 0) {
113
+ throw new errors_1.NotionCLIError(errors_1.NotionCLIErrorCode.VALIDATION_ERROR, 'No IDs provided. Use --ids flag, positional argument, or pipe IDs via stdin', [
114
+ {
115
+ description: 'Provide IDs via --ids flag',
116
+ command: 'notion-cli batch retrieve --ids ID1,ID2,ID3'
117
+ },
118
+ {
119
+ description: 'Or pipe IDs from a file',
120
+ command: 'cat ids.txt | notion-cli batch retrieve'
121
+ }
122
+ ]);
123
+ }
124
+ // Fetch all resources in parallel
125
+ const results = await Promise.all(ids.map(id => this.retrieveResource(id, flags.type)));
126
+ // Count successes and failures
127
+ const successCount = results.filter(r => r.success).length;
128
+ const failureCount = results.filter(r => !r.success).length;
129
+ // Handle JSON output for automation (takes precedence)
130
+ if (flags.json) {
131
+ this.log(JSON.stringify({
132
+ success: successCount > 0,
133
+ total: results.length,
134
+ succeeded: successCount,
135
+ failed: failureCount,
136
+ results: results,
137
+ timestamp: new Date().toISOString(),
138
+ }, null, 2));
139
+ process.exit(failureCount === 0 ? 0 : 1);
140
+ return;
141
+ }
142
+ // Handle compact JSON output
143
+ if (flags['compact-json']) {
144
+ (0, helper_1.outputCompactJson)({
145
+ total: results.length,
146
+ succeeded: successCount,
147
+ failed: failureCount,
148
+ results: results,
149
+ });
150
+ process.exit(failureCount === 0 ? 0 : 1);
151
+ return;
152
+ }
153
+ // Handle raw JSON output
154
+ if (flags.raw) {
155
+ (0, helper_1.outputRawJson)(results);
156
+ process.exit(failureCount === 0 ? 0 : 1);
157
+ return;
158
+ }
159
+ // Handle table output (default)
160
+ const tableData = results.map(result => {
161
+ if (result.success && result.data) {
162
+ let title = '';
163
+ if ('object' in result.data) {
164
+ if (result.data.object === 'page') {
165
+ title = (0, helper_1.getPageTitle)(result.data);
166
+ }
167
+ else if (result.data.object === 'data_source') {
168
+ title = (0, helper_1.getDataSourceTitle)(result.data);
169
+ }
170
+ else if (result.data.object === 'block') {
171
+ title = (0, helper_1.getBlockPlainText)(result.data);
172
+ }
173
+ }
174
+ return {
175
+ id: result.id,
176
+ status: 'success',
177
+ type: result.data.object || flags.type,
178
+ title: title || '-',
179
+ };
180
+ }
181
+ else {
182
+ return {
183
+ id: result.id,
184
+ status: 'failed',
185
+ type: flags.type,
186
+ title: result.message || result.error || 'Unknown error',
187
+ };
188
+ }
189
+ });
190
+ const columns = {
191
+ id: {},
192
+ status: {},
193
+ type: {},
194
+ title: {},
195
+ };
196
+ const options = {
197
+ printLine: this.log.bind(this),
198
+ ...flags,
199
+ };
200
+ (0, table_formatter_1.formatTable)(tableData, columns, options);
201
+ // Print summary
202
+ this.log(`\nTotal: ${results.length} | Succeeded: ${successCount} | Failed: ${failureCount}`);
203
+ process.exit(failureCount === 0 ? 0 : 1);
204
+ }
205
+ catch (error) {
206
+ const cliError = error instanceof errors_1.NotionCLIError
207
+ ? error
208
+ : (0, errors_1.wrapNotionError)(error, {
209
+ endpoint: 'batch.retrieve'
210
+ });
211
+ if (flags.json) {
212
+ this.log(JSON.stringify(cliError.toJSON(), null, 2));
213
+ }
214
+ else {
215
+ this.error(cliError.toHumanString());
216
+ }
217
+ process.exit(1);
218
+ }
219
+ }
220
+ }
221
+ BatchRetrieve.description = 'Batch retrieve multiple pages, blocks, or data sources';
222
+ BatchRetrieve.aliases = ['batch:r'];
223
+ BatchRetrieve.examples = [
224
+ {
225
+ description: 'Retrieve multiple pages via --ids flag',
226
+ command: '$ notion-cli batch retrieve --ids PAGE_ID_1,PAGE_ID_2,PAGE_ID_3 --compact-json',
227
+ },
228
+ {
229
+ description: 'Retrieve multiple pages from stdin (one ID per line)',
230
+ command: '$ cat page_ids.txt | notion-cli batch retrieve --compact-json',
231
+ },
232
+ {
233
+ description: 'Retrieve multiple blocks',
234
+ command: '$ notion-cli batch retrieve --ids BLOCK_ID_1,BLOCK_ID_2 --type block --json',
235
+ },
236
+ {
237
+ description: 'Retrieve multiple data sources',
238
+ command: '$ notion-cli batch retrieve --ids DS_ID_1,DS_ID_2 --type database --json',
239
+ },
240
+ {
241
+ description: 'Retrieve with raw output',
242
+ command: '$ notion-cli batch retrieve --ids ID1,ID2,ID3 -r',
243
+ },
244
+ {
245
+ description: 'Retrieve using Notion URLs (auto-resolved)',
246
+ command: '$ notion-cli batch retrieve --ids "https://notion.so/Page-abc123,https://notion.so/Other-def456"',
247
+ },
248
+ ];
249
+ BatchRetrieve.args = {
250
+ ids: core_1.Args.string({
251
+ required: false,
252
+ description: 'Comma-separated list of IDs to retrieve (or use --ids flag or stdin)',
253
+ }),
254
+ };
255
+ BatchRetrieve.flags = {
256
+ ids: core_1.Flags.string({
257
+ description: 'Comma-separated list of IDs to retrieve',
258
+ }),
259
+ type: core_1.Flags.string({
260
+ description: 'Resource type to retrieve (page, block, database)',
261
+ options: ['page', 'block', 'database'],
262
+ default: 'page',
263
+ }),
264
+ raw: core_1.Flags.boolean({
265
+ char: 'r',
266
+ description: 'output raw json (recommended for AI assistants - returns all fields)',
267
+ }),
268
+ ...table_formatter_1.tableFlags,
269
+ ...base_flags_1.OutputFormatFlags,
270
+ ...base_flags_1.AutomationFlags,
271
+ };
272
+ exports.default = BatchRetrieve;
@@ -0,0 +1,42 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class BlockAppend extends Command {
3
+ static description: string;
4
+ static aliases: string[];
5
+ static examples: {
6
+ description: string;
7
+ command: string;
8
+ }[];
9
+ static flags: {
10
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
11
+ 'page-size': import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
12
+ retry: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
13
+ timeout: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
14
+ 'no-cache': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
15
+ verbose: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
16
+ minimal: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
17
+ columns: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
18
+ sort: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
19
+ filter: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
20
+ csv: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
21
+ extended: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
22
+ 'no-truncate': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
23
+ 'no-header': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
24
+ block_id: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
25
+ children: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
26
+ text: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
27
+ 'heading-1': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
28
+ 'heading-2': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
29
+ 'heading-3': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
30
+ bullet: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
31
+ numbered: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
32
+ todo: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
33
+ toggle: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
34
+ code: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
35
+ language: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
36
+ quote: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
37
+ callout: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
38
+ after: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
39
+ raw: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
40
+ };
41
+ run(): Promise<void>;
42
+ }
@@ -0,0 +1,219 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const table_formatter_1 = require("../../utils/table-formatter");
5
+ const notion = require("../../notion");
6
+ const helper_1 = require("../../helper");
7
+ const notion_resolver_1 = require("../../utils/notion-resolver");
8
+ const base_flags_1 = require("../../base-flags");
9
+ const errors_1 = require("../../errors");
10
+ class BlockAppend extends core_1.Command {
11
+ async run() {
12
+ const { flags } = await this.parse(BlockAppend);
13
+ try {
14
+ // Resolve block ID from URL or direct ID
15
+ const blockId = await (0, notion_resolver_1.resolveNotionId)(flags.block_id, 'page');
16
+ let children;
17
+ // Check if using simple text-based flags or complex JSON
18
+ const hasTextFlags = flags.text || flags['heading-1'] || flags['heading-2'] || flags['heading-3'] ||
19
+ flags.bullet || flags.numbered || flags.todo || flags.toggle ||
20
+ flags.code || flags.quote || flags.callout;
21
+ if (hasTextFlags && flags.children) {
22
+ this.error('Cannot use both text-based flags (--text, --heading-1, etc.) and --children flag together. Choose one approach.');
23
+ }
24
+ if (hasTextFlags) {
25
+ // Use simple text-based flags
26
+ children = (0, helper_1.buildBlocksFromTextFlags)({
27
+ text: flags.text,
28
+ heading1: flags['heading-1'],
29
+ heading2: flags['heading-2'],
30
+ heading3: flags['heading-3'],
31
+ bullet: flags.bullet,
32
+ numbered: flags.numbered,
33
+ todo: flags.todo,
34
+ toggle: flags.toggle,
35
+ code: flags.code,
36
+ language: flags.language,
37
+ quote: flags.quote,
38
+ callout: flags.callout,
39
+ });
40
+ if (children.length === 0) {
41
+ this.error('No content provided. Use text-based flags (--text, --heading-1, etc.) or --children flag.');
42
+ }
43
+ }
44
+ else if (flags.children) {
45
+ // Use complex JSON
46
+ try {
47
+ children = JSON.parse(flags.children);
48
+ }
49
+ catch (error) {
50
+ throw errors_1.NotionCLIErrorFactory.invalidJson(flags.children, error);
51
+ }
52
+ }
53
+ else {
54
+ this.error('No content provided. Use text-based flags (--text, --heading-1, etc.) or --children flag.');
55
+ }
56
+ const params = {
57
+ block_id: blockId,
58
+ children: children,
59
+ };
60
+ if (flags.after) {
61
+ // Resolve after block ID from URL or direct ID
62
+ const afterBlockId = await (0, notion_resolver_1.resolveNotionId)(flags.after, 'page');
63
+ params.after = afterBlockId;
64
+ }
65
+ const res = await notion.appendBlockChildren(params);
66
+ // Handle JSON output for automation
67
+ if (flags.json) {
68
+ this.log(JSON.stringify({
69
+ success: true,
70
+ data: res,
71
+ timestamp: new Date().toISOString()
72
+ }, null, 2));
73
+ process.exit(0);
74
+ return;
75
+ }
76
+ // Handle raw JSON output (legacy)
77
+ if (flags.raw) {
78
+ (0, helper_1.outputRawJson)(res);
79
+ process.exit(0);
80
+ return;
81
+ }
82
+ // Handle table output
83
+ const columns = {
84
+ object: {},
85
+ id: {},
86
+ type: {},
87
+ parent: {},
88
+ content: {
89
+ get: (row) => {
90
+ return (0, helper_1.getBlockPlainText)(row);
91
+ },
92
+ },
93
+ };
94
+ const options = {
95
+ printLine: this.log.bind(this),
96
+ ...flags,
97
+ };
98
+ (0, table_formatter_1.formatTable)(res.results, columns, options);
99
+ process.exit(0);
100
+ }
101
+ catch (error) {
102
+ const cliError = error instanceof errors_1.NotionCLIError
103
+ ? error
104
+ : (0, errors_1.wrapNotionError)(error, {
105
+ resourceType: 'block',
106
+ attemptedId: flags.block_id,
107
+ endpoint: 'blocks.children.append',
108
+ userInput: flags.children
109
+ });
110
+ if (flags.json) {
111
+ this.log(JSON.stringify(cliError.toJSON(), null, 2));
112
+ }
113
+ else {
114
+ this.error(cliError.toHumanString());
115
+ }
116
+ process.exit(1);
117
+ }
118
+ }
119
+ }
120
+ BlockAppend.description = 'Append block children';
121
+ BlockAppend.aliases = ['block:a'];
122
+ BlockAppend.examples = [
123
+ {
124
+ description: 'Append a simple paragraph',
125
+ command: `$ notion-cli block append -b BLOCK_ID --text "Hello world!"`,
126
+ },
127
+ {
128
+ description: 'Append a heading',
129
+ command: `$ notion-cli block append -b BLOCK_ID --heading-1 "Chapter Title"`,
130
+ },
131
+ {
132
+ description: 'Append a bullet point',
133
+ command: `$ notion-cli block append -b BLOCK_ID --bullet "First item"`,
134
+ },
135
+ {
136
+ description: 'Append a code block',
137
+ command: `$ notion-cli block append -b BLOCK_ID --code "console.log('test')" --language javascript`,
138
+ },
139
+ {
140
+ description: 'Append block children with complex JSON (for advanced cases)',
141
+ command: `$ notion-cli block append -b BLOCK_ID -c '[{"object":"block","type":"paragraph","paragraph":{"rich_text":[{"type":"text","text":{"content":"Hello world!"}}]}}]'`,
142
+ },
143
+ {
144
+ description: 'Append block children via URL',
145
+ command: `$ notion-cli block append -b https://notion.so/BLOCK_ID --text "Hello world!"`,
146
+ },
147
+ {
148
+ description: 'Append block children after a block',
149
+ command: `$ notion-cli block append -b BLOCK_ID --text "Hello world!" -a AFTER_BLOCK_ID`,
150
+ },
151
+ {
152
+ description: 'Append block children and output raw json',
153
+ command: `$ notion-cli block append -b BLOCK_ID --text "Hello world!" -r`,
154
+ },
155
+ {
156
+ description: 'Append block children and output JSON for automation',
157
+ command: `$ notion-cli block append -b BLOCK_ID --text "Hello world!" --json`,
158
+ },
159
+ ];
160
+ BlockAppend.flags = {
161
+ block_id: core_1.Flags.string({
162
+ char: 'b',
163
+ description: 'Parent block ID or URL',
164
+ required: true,
165
+ }),
166
+ children: core_1.Flags.string({
167
+ char: 'c',
168
+ description: 'Block children (JSON array) - for complex cases',
169
+ }),
170
+ // Simple text-based flags
171
+ text: core_1.Flags.string({
172
+ description: 'Paragraph text',
173
+ }),
174
+ 'heading-1': core_1.Flags.string({
175
+ description: 'H1 heading text',
176
+ }),
177
+ 'heading-2': core_1.Flags.string({
178
+ description: 'H2 heading text',
179
+ }),
180
+ 'heading-3': core_1.Flags.string({
181
+ description: 'H3 heading text',
182
+ }),
183
+ bullet: core_1.Flags.string({
184
+ description: 'Bulleted list item text',
185
+ }),
186
+ numbered: core_1.Flags.string({
187
+ description: 'Numbered list item text',
188
+ }),
189
+ todo: core_1.Flags.string({
190
+ description: 'To-do item text',
191
+ }),
192
+ toggle: core_1.Flags.string({
193
+ description: 'Toggle block text',
194
+ }),
195
+ code: core_1.Flags.string({
196
+ description: 'Code block content',
197
+ }),
198
+ language: core_1.Flags.string({
199
+ description: 'Code block language (used with --code)',
200
+ default: 'plain text',
201
+ }),
202
+ quote: core_1.Flags.string({
203
+ description: 'Quote block text',
204
+ }),
205
+ callout: core_1.Flags.string({
206
+ description: 'Callout block text',
207
+ }),
208
+ after: core_1.Flags.string({
209
+ char: 'a',
210
+ description: 'Block ID or URL to append after (optional)',
211
+ }),
212
+ raw: core_1.Flags.boolean({
213
+ char: 'r',
214
+ description: 'output raw json',
215
+ }),
216
+ ...table_formatter_1.tableFlags,
217
+ ...base_flags_1.AutomationFlags,
218
+ };
219
+ exports.default = BlockAppend;
@@ -0,0 +1,30 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class BlockDelete extends Command {
3
+ static description: string;
4
+ static aliases: string[];
5
+ static examples: {
6
+ description: string;
7
+ command: string;
8
+ }[];
9
+ static args: {
10
+ block_id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
11
+ };
12
+ static flags: {
13
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
14
+ 'page-size': import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
15
+ retry: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
16
+ timeout: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
17
+ 'no-cache': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
18
+ verbose: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
19
+ minimal: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
20
+ columns: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
21
+ sort: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
22
+ filter: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
23
+ csv: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
24
+ extended: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
25
+ 'no-truncate': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
26
+ 'no-header': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
27
+ raw: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
28
+ };
29
+ run(): Promise<void>;
30
+ }
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const table_formatter_1 = require("../../utils/table-formatter");
5
+ const notion = require("../../notion");
6
+ const helper_1 = require("../../helper");
7
+ const base_flags_1 = require("../../base-flags");
8
+ const errors_1 = require("../../errors");
9
+ const notion_resolver_1 = require("../../utils/notion-resolver");
10
+ class BlockDelete extends core_1.Command {
11
+ async run() {
12
+ const { args, flags } = await this.parse(BlockDelete);
13
+ try {
14
+ // Resolve URL/name/ID to clean Notion ID
15
+ const blockId = await (0, notion_resolver_1.resolveNotionId)(args.block_id, 'page');
16
+ const res = await notion.deleteBlock(blockId);
17
+ // Handle JSON output for automation
18
+ if (flags.json) {
19
+ this.log(JSON.stringify({
20
+ success: true,
21
+ data: res,
22
+ timestamp: new Date().toISOString()
23
+ }, null, 2));
24
+ process.exit(0);
25
+ return;
26
+ }
27
+ // Handle raw JSON output (legacy)
28
+ if (flags.raw) {
29
+ (0, helper_1.outputRawJson)(res);
30
+ process.exit(0);
31
+ return;
32
+ }
33
+ // Handle table output
34
+ const columns = {
35
+ object: {},
36
+ id: {},
37
+ type: {},
38
+ parent: {},
39
+ content: {
40
+ get: (row) => {
41
+ return (0, helper_1.getBlockPlainText)(row);
42
+ },
43
+ },
44
+ };
45
+ const options = {
46
+ printLine: this.log.bind(this),
47
+ ...flags,
48
+ };
49
+ (0, table_formatter_1.formatTable)([res], columns, options);
50
+ process.exit(0);
51
+ }
52
+ catch (error) {
53
+ const cliError = error instanceof errors_1.NotionCLIError
54
+ ? error
55
+ : (0, errors_1.wrapNotionError)(error, {
56
+ resourceType: 'block',
57
+ attemptedId: args.block_id,
58
+ endpoint: 'blocks.delete'
59
+ });
60
+ if (flags.json) {
61
+ this.log(JSON.stringify(cliError.toJSON(), null, 2));
62
+ }
63
+ else {
64
+ this.error(cliError.toHumanString());
65
+ }
66
+ process.exit(1);
67
+ }
68
+ }
69
+ }
70
+ BlockDelete.description = 'Delete a block';
71
+ BlockDelete.aliases = ['block:d'];
72
+ BlockDelete.examples = [
73
+ {
74
+ description: 'Delete a block',
75
+ command: `$ notion-cli block delete BLOCK_ID`,
76
+ },
77
+ {
78
+ description: 'Delete a block and output raw json',
79
+ command: `$ notion-cli block delete BLOCK_ID -r`,
80
+ },
81
+ {
82
+ description: 'Delete a block and output JSON for automation',
83
+ command: `$ notion-cli block delete BLOCK_ID --json`,
84
+ },
85
+ ];
86
+ BlockDelete.args = {
87
+ block_id: core_1.Args.string({ required: true }),
88
+ };
89
+ BlockDelete.flags = {
90
+ raw: core_1.Flags.boolean({
91
+ char: 'r',
92
+ description: 'output raw json',
93
+ }),
94
+ ...table_formatter_1.tableFlags,
95
+ ...base_flags_1.AutomationFlags,
96
+ };
97
+ exports.default = BlockDelete;