@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,479 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const readline = require("readline");
5
+ const base_flags_1 = require("../base-flags");
6
+ const errors_1 = require("../errors");
7
+ const client_1 = require("@notionhq/client");
8
+ const token_validator_1 = require("../utils/token-validator");
9
+ const shell_config_1 = require("../utils/shell-config");
10
+ const notion_1 = require("../notion");
11
+ const workspace_cache_1 = require("../utils/workspace-cache");
12
+ const terminal_banner_1 = require("../utils/terminal-banner");
13
+ /**
14
+ * Interactive first-time setup wizard for Notion CLI
15
+ *
16
+ * Guides new users through:
17
+ * 1. Token configuration
18
+ * 2. Connection testing
19
+ * 3. Workspace synchronization
20
+ *
21
+ * Designed to provide a welcoming, educational experience that sets users up for success.
22
+ */
23
+ class Init extends core_1.Command {
24
+ constructor() {
25
+ super(...arguments);
26
+ this.isJsonMode = false;
27
+ }
28
+ async run() {
29
+ const { args, flags } = await this.parse(Init);
30
+ this.isJsonMode = flags.json;
31
+ try {
32
+ // Check if already configured
33
+ const alreadyConfigured = await this.checkExistingSetup();
34
+ if (alreadyConfigured && !this.isJsonMode) {
35
+ const shouldReconfigure = await this.promptReconfigure();
36
+ if (!shouldReconfigure) {
37
+ this.log('\nSetup cancelled. Your existing configuration is unchanged.');
38
+ process.exit(0);
39
+ }
40
+ }
41
+ // Welcome message
42
+ if (!this.isJsonMode) {
43
+ this.showWelcome();
44
+ }
45
+ // Step 1: Configure token (use arg if provided, otherwise prompt interactively)
46
+ const tokenResult = await this.setupToken(args.token);
47
+ // Step 2: Test connection
48
+ const connectionResult = await this.testConnection();
49
+ // Step 3: Sync workspace
50
+ const syncResult = await this.syncWorkspace();
51
+ // Success summary
52
+ await this.showSuccess(tokenResult, connectionResult, syncResult);
53
+ process.exit(0);
54
+ }
55
+ catch (error) {
56
+ const cliError = error instanceof errors_1.NotionCLIError
57
+ ? error
58
+ : (0, errors_1.wrapNotionError)(error, {
59
+ endpoint: 'init'
60
+ });
61
+ if (this.isJsonMode) {
62
+ this.log(JSON.stringify(cliError.toJSON(), null, 2));
63
+ }
64
+ else {
65
+ this.error(cliError.toHumanString());
66
+ }
67
+ process.exit(1);
68
+ }
69
+ }
70
+ /**
71
+ * Check if user already has a configured token
72
+ */
73
+ async checkExistingSetup() {
74
+ if (!process.env.NOTION_TOKEN) {
75
+ return false;
76
+ }
77
+ try {
78
+ // Try to validate token
79
+ (0, token_validator_1.validateNotionToken)();
80
+ await (0, notion_1.botUser)();
81
+ return true;
82
+ }
83
+ catch {
84
+ // Token exists but is invalid
85
+ return false;
86
+ }
87
+ }
88
+ /**
89
+ * Prompt user if they want to reconfigure
90
+ */
91
+ async promptReconfigure() {
92
+ this.log('\nYou already have a configured Notion token.');
93
+ this.log('Running init again will update your configuration.');
94
+ this.log('');
95
+ const rl = readline.createInterface({
96
+ input: process.stdin,
97
+ output: process.stdout,
98
+ });
99
+ const answer = await new Promise((resolve) => {
100
+ rl.question('Do you want to reconfigure? (y/n): ', (answer) => {
101
+ rl.close();
102
+ resolve(answer.trim().toLowerCase());
103
+ });
104
+ });
105
+ return answer === 'y' || answer === 'yes';
106
+ }
107
+ /**
108
+ * Show welcome message
109
+ */
110
+ showWelcome() {
111
+ this.log(terminal_banner_1.ASCII_BANNER);
112
+ this.log(`${terminal_banner_1.colors.blue}Welcome to Notion CLI Setup!${terminal_banner_1.colors.reset}\n`);
113
+ this.log('This wizard will help you set up your Notion CLI in 3 steps:');
114
+ this.log(` ${terminal_banner_1.colors.dim}1.${terminal_banner_1.colors.reset} Configure your Notion integration token`);
115
+ this.log(` ${terminal_banner_1.colors.dim}2.${terminal_banner_1.colors.reset} Test the connection to Notion API`);
116
+ this.log(` ${terminal_banner_1.colors.dim}3.${terminal_banner_1.colors.reset} Sync your workspace databases`);
117
+ this.log('');
118
+ this.log('Let\'s get started!');
119
+ this.log('');
120
+ }
121
+ /**
122
+ * Step 1: Setup token
123
+ * Accepts an optional token argument — if provided, skips interactive prompt.
124
+ */
125
+ async setupToken(tokenArg) {
126
+ const stepNum = 1;
127
+ const stepTotal = 3;
128
+ if (!this.isJsonMode) {
129
+ this.log('='.repeat(60));
130
+ this.log(`Step ${stepNum}/${stepTotal}: Set your Notion token`);
131
+ this.log('='.repeat(60));
132
+ this.log('');
133
+ }
134
+ // Determine token source: argument > environment > interactive prompt
135
+ let token;
136
+ if (tokenArg) {
137
+ // Token provided as CLI argument — no prompting needed
138
+ token = tokenArg;
139
+ }
140
+ else if (this.isJsonMode) {
141
+ // JSON mode: token must be in environment or argument
142
+ if (!process.env.NOTION_TOKEN) {
143
+ throw new errors_1.NotionCLIError(errors_1.NotionCLIErrorCode.TOKEN_MISSING, 'Token required - pass as argument or set NOTION_TOKEN', [
144
+ {
145
+ description: 'Pass token as argument',
146
+ command: 'notion-cli init ntn_your_token_here --json'
147
+ }
148
+ ]);
149
+ }
150
+ token = process.env.NOTION_TOKEN;
151
+ }
152
+ else if (process.env.NOTION_TOKEN) {
153
+ // Token exists in env — ask if user wants to keep it
154
+ this.log('Found existing NOTION_TOKEN in environment.');
155
+ const rl = readline.createInterface({
156
+ input: process.stdin,
157
+ output: process.stdout,
158
+ });
159
+ const useExisting = await new Promise((resolve) => {
160
+ rl.question('Use existing token? (y/n): ', (answer) => {
161
+ rl.close();
162
+ resolve(answer.trim().toLowerCase());
163
+ });
164
+ });
165
+ if (useExisting === 'y' || useExisting === 'yes') {
166
+ this.log('Using existing token from environment.');
167
+ this.log('');
168
+ return {
169
+ source: 'environment',
170
+ updated: false
171
+ };
172
+ }
173
+ // User wants a new token — prompt for it
174
+ token = await this.promptForToken();
175
+ }
176
+ else {
177
+ // No token anywhere — show instructions and prompt
178
+ this.log('You need a Notion integration token to use this CLI.');
179
+ this.log('Get one at: https://www.notion.so/my-integrations');
180
+ this.log('');
181
+ token = await this.promptForToken();
182
+ }
183
+ // Validate token is not empty
184
+ if (!token) {
185
+ throw new errors_1.NotionCLIError(errors_1.NotionCLIErrorCode.TOKEN_INVALID, 'Token cannot be empty', [
186
+ {
187
+ description: 'Get your integration token from Notion',
188
+ link: 'https://developers.notion.com/docs/create-a-notion-integration'
189
+ }
190
+ ]);
191
+ }
192
+ // Accept tokens with or without "secret_" prefix — auto-prepend if needed
193
+ // Notion tokens can start with "secret_" (legacy) or "ntn_" (current)
194
+ if (!token.startsWith('secret_') && !token.startsWith('ntn_')) {
195
+ token = `secret_${token}`;
196
+ if (!this.isJsonMode) {
197
+ this.log(`${terminal_banner_1.colors.dim}Note: Automatically added "secret_" prefix to token${terminal_banner_1.colors.reset}`);
198
+ }
199
+ }
200
+ // Validate token length (Notion tokens are typically 50+ chars)
201
+ if (token.length < 20) {
202
+ throw new errors_1.NotionCLIError(errors_1.NotionCLIErrorCode.TOKEN_INVALID, 'Token appears to be too short', [
203
+ {
204
+ description: 'Notion integration tokens are typically 50+ characters',
205
+ },
206
+ {
207
+ description: 'Please verify you copied the complete token from Notion',
208
+ link: 'https://www.notion.so/my-integrations'
209
+ },
210
+ {
211
+ description: 'Token should look like: ntn_abc123... or secret_abc123... (40+ more characters)',
212
+ }
213
+ ]);
214
+ }
215
+ // Set token in current process for subsequent steps
216
+ process.env.NOTION_TOKEN = token;
217
+ // Persist token to shell rc file so it's available in future sessions
218
+ const { rcFile } = await (0, shell_config_1.persistToken)(token);
219
+ if (!this.isJsonMode) {
220
+ this.log('');
221
+ this.log(`Token saved to ${rcFile}`);
222
+ this.log(`Reload other terminal tabs with: source ${rcFile}`);
223
+ this.log('');
224
+ this.log('Step 1 complete!');
225
+ this.log('');
226
+ }
227
+ return {
228
+ source: 'user_input',
229
+ updated: true,
230
+ tokenLength: token.length
231
+ };
232
+ }
233
+ /**
234
+ * Prompt user for token via interactive readline
235
+ */
236
+ async promptForToken() {
237
+ const rl = readline.createInterface({
238
+ input: process.stdin,
239
+ output: process.stdout,
240
+ });
241
+ const token = await new Promise((resolve) => {
242
+ rl.question('Enter your Notion integration token: ', (answer) => {
243
+ rl.close();
244
+ resolve(answer.trim());
245
+ });
246
+ });
247
+ return token;
248
+ }
249
+ /**
250
+ * Step 2: Test connection
251
+ */
252
+ async testConnection() {
253
+ const stepNum = 2;
254
+ const stepTotal = 3;
255
+ if (!this.isJsonMode) {
256
+ this.log('='.repeat(60));
257
+ this.log(`Step ${stepNum}/${stepTotal}: Test connection`);
258
+ this.log('='.repeat(60));
259
+ this.log('');
260
+ core_1.ux.action.start('Connecting to Notion API');
261
+ }
262
+ const startTime = Date.now();
263
+ try {
264
+ // Validate token and fetch bot info
265
+ (0, token_validator_1.validateNotionToken)();
266
+ // Use a fresh client — the module-level client may have been created
267
+ // before process.env.NOTION_TOKEN was set (e.g., during init flow)
268
+ const freshClient = new client_1.Client({ auth: process.env.NOTION_TOKEN });
269
+ const userResponse = await freshClient.users.me({});
270
+ const user = userResponse;
271
+ const latency = Date.now() - startTime;
272
+ // Extract bot info
273
+ const botInfo = {
274
+ id: user.id,
275
+ name: user.name || 'Unnamed Bot',
276
+ type: user.type
277
+ };
278
+ let workspaceInfo = null;
279
+ if (user.type === 'bot') {
280
+ const botUser = user;
281
+ if (botUser.bot && typeof botUser.bot === 'object' && 'owner' in botUser.bot) {
282
+ if (botUser.bot.workspace_name) {
283
+ workspaceInfo = {
284
+ name: botUser.bot.workspace_name,
285
+ id: botUser.bot.workspace_id,
286
+ };
287
+ }
288
+ }
289
+ }
290
+ if (!this.isJsonMode) {
291
+ core_1.ux.action.stop('connected');
292
+ this.log('');
293
+ this.log(`Bot Name: ${botInfo.name}`);
294
+ this.log(`Bot ID: ${botInfo.id}`);
295
+ if (workspaceInfo) {
296
+ this.log(`Workspace: ${workspaceInfo.name}`);
297
+ }
298
+ this.log(`Connection latency: ${latency}ms`);
299
+ this.log('');
300
+ this.log('Step 2 complete!');
301
+ this.log('');
302
+ }
303
+ return {
304
+ success: true,
305
+ bot: botInfo,
306
+ workspace: workspaceInfo,
307
+ latency_ms: latency
308
+ };
309
+ }
310
+ catch (error) {
311
+ if (!this.isJsonMode) {
312
+ core_1.ux.action.stop('failed');
313
+ }
314
+ throw (0, errors_1.wrapNotionError)(error, {
315
+ endpoint: 'users.botUser',
316
+ resourceType: 'user'
317
+ });
318
+ }
319
+ }
320
+ /**
321
+ * Step 3: Sync workspace
322
+ */
323
+ async syncWorkspace() {
324
+ var _a;
325
+ const stepNum = 3;
326
+ const stepTotal = 3;
327
+ if (!this.isJsonMode) {
328
+ this.log('='.repeat(60));
329
+ this.log(`Step ${stepNum}/${stepTotal}: Sync workspace`);
330
+ this.log('='.repeat(60));
331
+ this.log('');
332
+ this.log('This will index all databases your integration can access.');
333
+ this.log('');
334
+ core_1.ux.action.start('Syncing databases');
335
+ }
336
+ const startTime = Date.now();
337
+ try {
338
+ // Use fresh client (same reason as testConnection — token may have been set mid-process)
339
+ const freshClient = new client_1.Client({ auth: process.env.NOTION_TOKEN });
340
+ // Fetch all databases
341
+ const databases = [];
342
+ let cursor = undefined;
343
+ while (true) {
344
+ const response = await freshClient.search({
345
+ filter: {
346
+ value: 'data_source',
347
+ property: 'object',
348
+ },
349
+ start_cursor: cursor,
350
+ page_size: 100,
351
+ });
352
+ databases.push(...response.results);
353
+ if (!this.isJsonMode && response.has_more) {
354
+ core_1.ux.action.start(`Syncing databases (found ${databases.length} so far)`);
355
+ }
356
+ if (!response.has_more || !response.next_cursor) {
357
+ break;
358
+ }
359
+ cursor = response.next_cursor;
360
+ }
361
+ const syncTime = Date.now() - startTime;
362
+ if (!this.isJsonMode) {
363
+ core_1.ux.action.stop(`found ${databases.length}`);
364
+ this.log('');
365
+ this.log(`Synced ${databases.length} database${databases.length === 1 ? '' : 's'} in ${(syncTime / 1000).toFixed(2)}s`);
366
+ this.log('');
367
+ if (databases.length > 0) {
368
+ this.log('Your integration has access to these databases:');
369
+ databases.slice(0, 5).forEach((db) => {
370
+ var _a, _b;
371
+ const title = ((_b = (_a = db.title) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.plain_text) || 'Untitled';
372
+ this.log(` - ${title}`);
373
+ });
374
+ if (databases.length > 5) {
375
+ this.log(` ... and ${databases.length - 5} more`);
376
+ }
377
+ this.log('');
378
+ }
379
+ else {
380
+ this.log('No databases found.');
381
+ this.log('Make sure you\'ve shared databases with your integration.');
382
+ this.log('Learn more: https://developers.notion.com/docs/create-a-notion-integration#give-your-integration-page-permissions');
383
+ this.log('');
384
+ }
385
+ this.log('Step 3 complete!');
386
+ this.log('');
387
+ }
388
+ // Try to load cache to show it's working
389
+ const cache = await (0, workspace_cache_1.loadCache)();
390
+ return {
391
+ success: true,
392
+ databases_found: databases.length,
393
+ sync_time_ms: syncTime,
394
+ cached: ((_a = cache === null || cache === void 0 ? void 0 : cache.databases) === null || _a === void 0 ? void 0 : _a.length) || 0
395
+ };
396
+ }
397
+ catch (error) {
398
+ if (!this.isJsonMode) {
399
+ core_1.ux.action.stop('failed');
400
+ }
401
+ throw (0, errors_1.wrapNotionError)(error, {
402
+ endpoint: 'search',
403
+ resourceType: 'database'
404
+ });
405
+ }
406
+ }
407
+ /**
408
+ * Show success summary
409
+ */
410
+ async showSuccess(tokenResult, connectionResult, syncResult) {
411
+ if (this.isJsonMode) {
412
+ this.log(JSON.stringify({
413
+ success: true,
414
+ message: 'Notion CLI setup complete',
415
+ data: {
416
+ token: tokenResult,
417
+ connection: connectionResult,
418
+ sync: syncResult
419
+ },
420
+ next_steps: [
421
+ 'notion-cli list - List all databases',
422
+ 'notion-cli db query <name-or-id> - Query a database',
423
+ 'notion-cli whoami - Check connection status',
424
+ 'notion-cli sync - Refresh workspace cache',
425
+ ],
426
+ metadata: {
427
+ timestamp: new Date().toISOString(),
428
+ command: 'init'
429
+ }
430
+ }, null, 2));
431
+ }
432
+ else {
433
+ this.log('='.repeat(60));
434
+ this.log(' Setup Complete!');
435
+ this.log('='.repeat(60));
436
+ this.log('');
437
+ this.log('Your Notion CLI is ready to use!');
438
+ this.log('');
439
+ this.log('Quick Start Commands:');
440
+ this.log(' notion-cli list - List all databases');
441
+ this.log(' notion-cli db query <name> - Query a database');
442
+ this.log(' notion-cli whoami - Check connection status');
443
+ this.log(' notion-cli sync - Refresh workspace cache');
444
+ this.log('');
445
+ this.log('Documentation:');
446
+ this.log(' https://github.com/Catafal/notion-cli');
447
+ this.log('');
448
+ this.log('Need help? Run any command with --help flag');
449
+ this.log('');
450
+ this.log('Happy building with Notion!');
451
+ this.log('');
452
+ }
453
+ }
454
+ }
455
+ Init.description = 'Interactive first-time setup wizard for Notion CLI';
456
+ Init.args = {
457
+ token: core_1.Args.string({
458
+ description: 'Notion integration token (starts with secret_ or ntn_)',
459
+ required: false,
460
+ }),
461
+ };
462
+ Init.examples = [
463
+ {
464
+ description: 'Set up with token directly',
465
+ command: '$ notion-cli init ntn_your_token_here',
466
+ },
467
+ {
468
+ description: 'Run interactive setup wizard',
469
+ command: '$ notion-cli init',
470
+ },
471
+ {
472
+ description: 'Run setup with automated JSON output',
473
+ command: '$ notion-cli init --json',
474
+ },
475
+ ];
476
+ Init.flags = {
477
+ ...base_flags_1.AutomationFlags,
478
+ };
479
+ exports.default = Init;
@@ -0,0 +1,29 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class List extends Command {
3
+ static description: string;
4
+ static aliases: string[];
5
+ static examples: {
6
+ description: string;
7
+ command: string;
8
+ }[];
9
+ static flags: {
10
+ filter: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ markdown: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
12
+ 'compact-json': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
13
+ pretty: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
14
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
15
+ 'page-size': import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
16
+ retry: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
17
+ timeout: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
18
+ 'no-cache': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
19
+ verbose: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
20
+ minimal: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
21
+ columns: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
22
+ sort: 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
+ };
28
+ run(): Promise<void>;
29
+ }