@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.
- package/LICENSE +21 -0
- package/README.md +552 -0
- package/bin/dev +17 -0
- package/bin/dev.cmd +3 -0
- package/bin/run +14 -0
- package/bin/run.cmd +3 -0
- package/dist/base-command.d.ts +73 -0
- package/dist/base-command.js +179 -0
- package/dist/base-flags.d.ts +14 -0
- package/dist/base-flags.js +59 -0
- package/dist/cache.d.ts +84 -0
- package/dist/cache.js +351 -0
- package/dist/commands/append.d.ts +37 -0
- package/dist/commands/append.js +120 -0
- package/dist/commands/batch/delete.d.ts +42 -0
- package/dist/commands/batch/delete.js +199 -0
- package/dist/commands/batch/retrieve.d.ts +43 -0
- package/dist/commands/batch/retrieve.js +272 -0
- package/dist/commands/block/append.d.ts +42 -0
- package/dist/commands/block/append.js +219 -0
- package/dist/commands/block/delete.d.ts +30 -0
- package/dist/commands/block/delete.js +97 -0
- package/dist/commands/block/retrieve/children.d.ts +31 -0
- package/dist/commands/block/retrieve/children.js +177 -0
- package/dist/commands/block/retrieve.d.ts +30 -0
- package/dist/commands/block/retrieve.js +101 -0
- package/dist/commands/block/update.d.ts +45 -0
- package/dist/commands/block/update.js +242 -0
- package/dist/commands/bookmark/list.d.ts +30 -0
- package/dist/commands/bookmark/list.js +60 -0
- package/dist/commands/bookmark/remove.d.ts +26 -0
- package/dist/commands/bookmark/remove.js +47 -0
- package/dist/commands/bookmark/set.d.ts +29 -0
- package/dist/commands/bookmark/set.js +96 -0
- package/dist/commands/browse.d.ts +13 -0
- package/dist/commands/browse.js +44 -0
- package/dist/commands/cache/info.d.ts +19 -0
- package/dist/commands/cache/info.js +145 -0
- package/dist/commands/config/set-token.d.ts +22 -0
- package/dist/commands/config/set-token.js +137 -0
- package/dist/commands/daily/index.d.ts +32 -0
- package/dist/commands/daily/index.js +135 -0
- package/dist/commands/daily/setup.d.ts +42 -0
- package/dist/commands/daily/setup.js +149 -0
- package/dist/commands/db/create.d.ts +31 -0
- package/dist/commands/db/create.js +124 -0
- package/dist/commands/db/query.d.ts +41 -0
- package/dist/commands/db/query.js +360 -0
- package/dist/commands/db/retrieve.d.ts +33 -0
- package/dist/commands/db/retrieve.js +134 -0
- package/dist/commands/db/schema.d.ts +32 -0
- package/dist/commands/db/schema.js +308 -0
- package/dist/commands/db/update.d.ts +31 -0
- package/dist/commands/db/update.js +117 -0
- package/dist/commands/doctor.d.ts +50 -0
- package/dist/commands/doctor.js +420 -0
- package/dist/commands/init.d.ts +65 -0
- package/dist/commands/init.js +479 -0
- package/dist/commands/list.d.ts +29 -0
- package/dist/commands/list.js +219 -0
- package/dist/commands/open.d.ts +29 -0
- package/dist/commands/open.js +100 -0
- package/dist/commands/page/create.d.ts +33 -0
- package/dist/commands/page/create.js +261 -0
- package/dist/commands/page/delete.d.ts +36 -0
- package/dist/commands/page/delete.js +107 -0
- package/dist/commands/page/export.d.ts +38 -0
- package/dist/commands/page/export.js +120 -0
- package/dist/commands/page/retrieve/property_item.d.ts +24 -0
- package/dist/commands/page/retrieve/property_item.js +75 -0
- package/dist/commands/page/retrieve.d.ts +36 -0
- package/dist/commands/page/retrieve.js +244 -0
- package/dist/commands/page/update.d.ts +34 -0
- package/dist/commands/page/update.js +184 -0
- package/dist/commands/quick.d.ts +35 -0
- package/dist/commands/quick.js +168 -0
- package/dist/commands/search.d.ts +43 -0
- package/dist/commands/search.js +361 -0
- package/dist/commands/stats.d.ts +35 -0
- package/dist/commands/stats.js +274 -0
- package/dist/commands/sync.d.ts +24 -0
- package/dist/commands/sync.js +183 -0
- package/dist/commands/template/get.d.ts +28 -0
- package/dist/commands/template/get.js +59 -0
- package/dist/commands/template/list.d.ts +32 -0
- package/dist/commands/template/list.js +62 -0
- package/dist/commands/template/remove.d.ts +27 -0
- package/dist/commands/template/remove.js +48 -0
- package/dist/commands/template/save.d.ts +32 -0
- package/dist/commands/template/save.js +92 -0
- package/dist/commands/template/use.d.ts +34 -0
- package/dist/commands/template/use.js +142 -0
- package/dist/commands/user/list.d.ts +27 -0
- package/dist/commands/user/list.js +99 -0
- package/dist/commands/user/retrieve/bot.d.ts +28 -0
- package/dist/commands/user/retrieve/bot.js +96 -0
- package/dist/commands/user/retrieve.d.ts +30 -0
- package/dist/commands/user/retrieve.js +103 -0
- package/dist/commands/whoami.d.ts +19 -0
- package/dist/commands/whoami.js +175 -0
- package/dist/deduplication.d.ts +41 -0
- package/dist/deduplication.js +71 -0
- package/dist/envelope.d.ts +169 -0
- package/dist/envelope.js +257 -0
- package/dist/errors/enhanced-errors.d.ts +168 -0
- package/dist/errors/enhanced-errors.js +567 -0
- package/dist/errors/index.d.ts +18 -0
- package/dist/errors/index.js +33 -0
- package/dist/examples/cache-retry-examples.d.ts +64 -0
- package/dist/examples/cache-retry-examples.js +375 -0
- package/dist/helper.d.ts +102 -0
- package/dist/helper.js +885 -0
- package/dist/http-agent.d.ts +38 -0
- package/dist/http-agent.js +60 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +4 -0
- package/dist/interface.d.ts +4 -0
- package/dist/interface.js +2 -0
- package/dist/notion.d.ts +144 -0
- package/dist/notion.js +547 -0
- package/dist/retry.d.ts +72 -0
- package/dist/retry.js +381 -0
- package/dist/utils/bookmarks.d.ts +32 -0
- package/dist/utils/bookmarks.js +98 -0
- package/dist/utils/daily-config.d.ts +22 -0
- package/dist/utils/daily-config.js +60 -0
- package/dist/utils/disk-cache.d.ts +80 -0
- package/dist/utils/disk-cache.js +291 -0
- package/dist/utils/fuzzy.d.ts +36 -0
- package/dist/utils/fuzzy.js +69 -0
- package/dist/utils/interactive-navigator.d.ts +63 -0
- package/dist/utils/interactive-navigator.js +123 -0
- package/dist/utils/markdown-to-blocks.d.ts +21 -0
- package/dist/utils/markdown-to-blocks.js +333 -0
- package/dist/utils/notion-resolver.d.ts +49 -0
- package/dist/utils/notion-resolver.js +278 -0
- package/dist/utils/notion-url-parser.d.ts +48 -0
- package/dist/utils/notion-url-parser.js +121 -0
- package/dist/utils/property-expander.d.ts +45 -0
- package/dist/utils/property-expander.js +323 -0
- package/dist/utils/schema-examples.d.ts +40 -0
- package/dist/utils/schema-examples.js +359 -0
- package/dist/utils/schema-extractor.d.ts +65 -0
- package/dist/utils/schema-extractor.js +235 -0
- package/dist/utils/shell-config.d.ts +30 -0
- package/dist/utils/shell-config.js +84 -0
- package/dist/utils/table-formatter.d.ts +36 -0
- package/dist/utils/table-formatter.js +125 -0
- package/dist/utils/templates.d.ts +30 -0
- package/dist/utils/templates.js +82 -0
- package/dist/utils/terminal-banner.d.ts +24 -0
- package/dist/utils/terminal-banner.js +34 -0
- package/dist/utils/token-validator.d.ts +42 -0
- package/dist/utils/token-validator.js +66 -0
- package/dist/utils/update-notifier.d.ts +26 -0
- package/dist/utils/update-notifier.js +54 -0
- package/dist/utils/workspace-cache.d.ts +58 -0
- package/dist/utils/workspace-cache.js +185 -0
- package/oclif.manifest.json +6471 -0
- package/package.json +118 -0
- package/scripts/banner.js +38 -0
- package/scripts/postinstall.js +44 -0
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Examples demonstrating enhanced retry logic and caching layer
|
|
4
|
+
*
|
|
5
|
+
* This file provides practical examples of how to use the new features.
|
|
6
|
+
* These examples can be adapted to your specific use cases.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.example1_basicUsage = example1_basicUsage;
|
|
10
|
+
exports.example2_cacheStats = example2_cacheStats;
|
|
11
|
+
exports.example3_cacheInvalidation = example3_cacheInvalidation;
|
|
12
|
+
exports.example4_customRetry = example4_customRetry;
|
|
13
|
+
exports.example5_circuitBreaker = example5_circuitBreaker;
|
|
14
|
+
exports.example6_batchOperations = example6_batchOperations;
|
|
15
|
+
exports.example7_errorCategorization = example7_errorCategorization;
|
|
16
|
+
exports.example8_delayCalculation = example8_delayCalculation;
|
|
17
|
+
exports.example9_productionPattern = example9_productionPattern;
|
|
18
|
+
exports.example10_configurationShowcase = example10_configurationShowcase;
|
|
19
|
+
exports.runAllExamples = runAllExamples;
|
|
20
|
+
const notion = require("../notion");
|
|
21
|
+
const cache_1 = require("../cache");
|
|
22
|
+
const retry_1 = require("../retry");
|
|
23
|
+
/**
|
|
24
|
+
* Example 1: Basic usage with automatic caching and retry
|
|
25
|
+
*/
|
|
26
|
+
async function example1_basicUsage() {
|
|
27
|
+
console.log('\n=== Example 1: Basic Usage ===');
|
|
28
|
+
const databaseId = 'your-database-id';
|
|
29
|
+
try {
|
|
30
|
+
// First call - will cache the result
|
|
31
|
+
console.log('First call (cache MISS expected):');
|
|
32
|
+
const ds1 = await notion.retrieveDataSource(databaseId);
|
|
33
|
+
console.log(`Retrieved data source: ${ds1.id}`);
|
|
34
|
+
// Second call - will use cache
|
|
35
|
+
console.log('\nSecond call (cache HIT expected):');
|
|
36
|
+
const ds2 = await notion.retrieveDataSource(databaseId);
|
|
37
|
+
console.log(`Retrieved data source: ${ds2.id}`);
|
|
38
|
+
// Verify both are the same (cached)
|
|
39
|
+
console.log(`\nSame object from cache: ${ds1 === ds2}`);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
console.error('Error:', error.message);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Example 2: Monitoring cache performance
|
|
47
|
+
*/
|
|
48
|
+
async function example2_cacheStats() {
|
|
49
|
+
console.log('\n=== Example 2: Cache Statistics ===');
|
|
50
|
+
// Clear cache to start fresh
|
|
51
|
+
cache_1.cacheManager.clear();
|
|
52
|
+
console.log('Cache cleared');
|
|
53
|
+
const databaseIds = ['db-id-1', 'db-id-2', 'db-id-3'];
|
|
54
|
+
// Make multiple calls
|
|
55
|
+
for (let i = 0; i < 3; i++) {
|
|
56
|
+
console.log(`\nRound ${i + 1}:`);
|
|
57
|
+
for (const dbId of databaseIds) {
|
|
58
|
+
try {
|
|
59
|
+
await notion.retrieveDataSource(dbId);
|
|
60
|
+
console.log(` Retrieved ${dbId}`);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
console.log(` Failed to retrieve ${dbId}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Display cache statistics
|
|
68
|
+
const stats = cache_1.cacheManager.getStats();
|
|
69
|
+
const hitRate = cache_1.cacheManager.getHitRate();
|
|
70
|
+
console.log('\n=== Cache Statistics ===');
|
|
71
|
+
console.log(`Total Requests: ${stats.hits + stats.misses}`);
|
|
72
|
+
console.log(`Cache Hits: ${stats.hits}`);
|
|
73
|
+
console.log(`Cache Misses: ${stats.misses}`);
|
|
74
|
+
console.log(`Hit Rate: ${(hitRate * 100).toFixed(2)}%`);
|
|
75
|
+
console.log(`Current Size: ${stats.size} entries`);
|
|
76
|
+
console.log(`Evictions: ${stats.evictions}`);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Example 3: Manual cache invalidation
|
|
80
|
+
*/
|
|
81
|
+
async function example3_cacheInvalidation() {
|
|
82
|
+
console.log('\n=== Example 3: Cache Invalidation ===');
|
|
83
|
+
const databaseId = 'your-database-id';
|
|
84
|
+
try {
|
|
85
|
+
// Retrieve and cache
|
|
86
|
+
console.log('Initial retrieval:');
|
|
87
|
+
const ds1 = await notion.retrieveDataSource(databaseId);
|
|
88
|
+
console.log(`Retrieved: ${ds1.id}`);
|
|
89
|
+
// Update the database
|
|
90
|
+
console.log('\nUpdating database...');
|
|
91
|
+
await notion.updateDataSource({
|
|
92
|
+
data_source_id: databaseId,
|
|
93
|
+
title: [{ type: 'text', text: { content: 'Updated Title' } }]
|
|
94
|
+
});
|
|
95
|
+
console.log('Database updated (cache automatically invalidated)');
|
|
96
|
+
// Retrieve again - will fetch fresh data
|
|
97
|
+
console.log('\nRetrieving after update:');
|
|
98
|
+
const ds2 = await notion.retrieveDataSource(databaseId);
|
|
99
|
+
console.log(`Retrieved: ${ds2.id}`);
|
|
100
|
+
// Manual invalidation example
|
|
101
|
+
console.log('\nManual cache invalidation:');
|
|
102
|
+
cache_1.cacheManager.invalidate('dataSource', databaseId);
|
|
103
|
+
console.log('Cache invalidated for specific data source');
|
|
104
|
+
// Or invalidate all data sources
|
|
105
|
+
cache_1.cacheManager.invalidate('dataSource');
|
|
106
|
+
console.log('Cache invalidated for all data sources');
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
console.error('Error:', error.message);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Example 4: Custom retry configuration
|
|
114
|
+
*/
|
|
115
|
+
async function example4_customRetry() {
|
|
116
|
+
console.log('\n=== Example 4: Custom Retry Configuration ===');
|
|
117
|
+
try {
|
|
118
|
+
const result = await (0, retry_1.fetchWithRetry)(async () => {
|
|
119
|
+
console.log('Attempting API call...');
|
|
120
|
+
// Simulate an operation that might fail
|
|
121
|
+
return await notion.client.users.me({});
|
|
122
|
+
}, {
|
|
123
|
+
config: {
|
|
124
|
+
maxRetries: 5,
|
|
125
|
+
baseDelay: 2000, // Start with 2 second delay
|
|
126
|
+
maxDelay: 60000, // Cap at 60 seconds
|
|
127
|
+
exponentialBase: 2.5, // Increase delay by 2.5x each time
|
|
128
|
+
jitterFactor: 0.2, // Add 20% random variation
|
|
129
|
+
},
|
|
130
|
+
onRetry: (context) => {
|
|
131
|
+
console.log(`Retry ${context.attempt}/${context.maxRetries}: ` +
|
|
132
|
+
`Last error: ${context.lastError.code || context.lastError.status}. ` +
|
|
133
|
+
`Total delay so far: ${context.totalDelay}ms`);
|
|
134
|
+
},
|
|
135
|
+
context: 'getCriticalUserInfo'
|
|
136
|
+
});
|
|
137
|
+
console.log('Success:', result);
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
console.error('Final error after all retries:', error.message);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Example 5: Circuit breaker pattern
|
|
145
|
+
*/
|
|
146
|
+
async function example5_circuitBreaker() {
|
|
147
|
+
console.log('\n=== Example 5: Circuit Breaker Pattern ===');
|
|
148
|
+
const breaker = new retry_1.CircuitBreaker(3, // Open circuit after 3 failures
|
|
149
|
+
2, // Close after 2 successes
|
|
150
|
+
30000 // 30 second timeout
|
|
151
|
+
);
|
|
152
|
+
const databaseIds = ['bad-id-1', 'bad-id-2', 'bad-id-3', 'bad-id-4', 'bad-id-5'];
|
|
153
|
+
for (const dbId of databaseIds) {
|
|
154
|
+
try {
|
|
155
|
+
console.log(`\nAttempting to retrieve ${dbId}...`);
|
|
156
|
+
const state = breaker.getState();
|
|
157
|
+
console.log(`Circuit breaker state: ${state.state} (failures: ${state.failures})`);
|
|
158
|
+
const result = await breaker.execute(() => notion.retrieveDataSource(dbId));
|
|
159
|
+
console.log(`Success: ${result.id}`);
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
console.error(`Failed: ${error.message}`);
|
|
163
|
+
const state = breaker.getState();
|
|
164
|
+
if (state.state === 'open') {
|
|
165
|
+
console.error('Circuit breaker is OPEN - stopping further attempts');
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// Show final state
|
|
171
|
+
const finalState = breaker.getState();
|
|
172
|
+
console.log('\nFinal circuit breaker state:', finalState);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Example 6: Batch operations with retry
|
|
176
|
+
*/
|
|
177
|
+
async function example6_batchOperations() {
|
|
178
|
+
console.log('\n=== Example 6: Batch Operations with Retry ===');
|
|
179
|
+
const databaseIds = ['db-1', 'db-2', 'db-3', 'db-4', 'db-5'];
|
|
180
|
+
const operations = databaseIds.map(dbId => () => notion.retrieveDataSource(dbId));
|
|
181
|
+
console.log('Processing batch with concurrency limit...');
|
|
182
|
+
const results = await (0, retry_1.batchWithRetry)(operations, {
|
|
183
|
+
concurrency: 2, // Process 2 at a time
|
|
184
|
+
config: {
|
|
185
|
+
maxRetries: 3,
|
|
186
|
+
baseDelay: 1000,
|
|
187
|
+
},
|
|
188
|
+
onRetry: (context) => {
|
|
189
|
+
console.log(` Retry ${context.attempt} for operation`);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
// Analyze results
|
|
193
|
+
const successful = results.filter(r => r.success).length;
|
|
194
|
+
const failed = results.filter(r => !r.success).length;
|
|
195
|
+
console.log('\n=== Batch Results ===');
|
|
196
|
+
console.log(`Total operations: ${results.length}`);
|
|
197
|
+
console.log(`Successful: ${successful}`);
|
|
198
|
+
console.log(`Failed: ${failed}`);
|
|
199
|
+
// Show details for failed operations
|
|
200
|
+
if (failed > 0) {
|
|
201
|
+
console.log('\nFailed operations:');
|
|
202
|
+
results.forEach((result, index) => {
|
|
203
|
+
if (!result.success) {
|
|
204
|
+
console.log(` Operation ${index + 1}: ${result.error.message}`);
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Example 7: Error categorization
|
|
211
|
+
*/
|
|
212
|
+
async function example7_errorCategorization() {
|
|
213
|
+
console.log('\n=== Example 7: Error Categorization ===');
|
|
214
|
+
// Simulate different types of errors
|
|
215
|
+
const errors = [
|
|
216
|
+
{ status: 429, message: 'Rate limited' },
|
|
217
|
+
{ status: 500, message: 'Internal server error' },
|
|
218
|
+
{ status: 400, message: 'Bad request' },
|
|
219
|
+
{ status: 401, message: 'Unauthorized' },
|
|
220
|
+
{ status: 503, message: 'Service unavailable' },
|
|
221
|
+
{ code: 'ECONNRESET', message: 'Connection reset' },
|
|
222
|
+
{ code: 'ETIMEDOUT', message: 'Timeout' },
|
|
223
|
+
];
|
|
224
|
+
console.log('Checking which errors are retryable:\n');
|
|
225
|
+
for (const error of errors) {
|
|
226
|
+
const retryable = (0, retry_1.isRetryableError)(error);
|
|
227
|
+
const status = error.status ? `HTTP ${error.status}` : error.code;
|
|
228
|
+
console.log(`${status} - ${error.message}: ` +
|
|
229
|
+
`${retryable ? 'RETRYABLE ✓' : 'NON-RETRYABLE ✗'}`);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Example 8: Delay calculation visualization
|
|
234
|
+
*/
|
|
235
|
+
async function example8_delayCalculation() {
|
|
236
|
+
console.log('\n=== Example 8: Delay Calculation ===');
|
|
237
|
+
const configs = [
|
|
238
|
+
{ name: 'Default', baseDelay: 1000, exponentialBase: 2, jitterFactor: 0.1 },
|
|
239
|
+
{ name: 'Aggressive', baseDelay: 2000, exponentialBase: 3, jitterFactor: 0.2 },
|
|
240
|
+
{ name: 'Conservative', baseDelay: 500, exponentialBase: 1.5, jitterFactor: 0.05 },
|
|
241
|
+
];
|
|
242
|
+
for (const config of configs) {
|
|
243
|
+
console.log(`\n${config.name} configuration:`);
|
|
244
|
+
console.log(`Base: ${config.baseDelay}ms, Exponential: ${config.exponentialBase}, Jitter: ${config.jitterFactor}`);
|
|
245
|
+
console.log('Retry delays:');
|
|
246
|
+
for (let attempt = 1; attempt <= 5; attempt++) {
|
|
247
|
+
const delay = (0, retry_1.calculateDelay)(attempt, {
|
|
248
|
+
maxRetries: 5,
|
|
249
|
+
baseDelay: config.baseDelay,
|
|
250
|
+
maxDelay: 30000,
|
|
251
|
+
exponentialBase: config.exponentialBase,
|
|
252
|
+
jitterFactor: config.jitterFactor,
|
|
253
|
+
retryableStatusCodes: [],
|
|
254
|
+
retryableErrorCodes: []
|
|
255
|
+
});
|
|
256
|
+
console.log(` Attempt ${attempt}: ~${delay}ms`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Example 9: Production-ready pattern
|
|
262
|
+
*/
|
|
263
|
+
async function example9_productionPattern() {
|
|
264
|
+
var _a, _b;
|
|
265
|
+
console.log('\n=== Example 9: Production-Ready Pattern ===');
|
|
266
|
+
// Setup circuit breaker for resilience
|
|
267
|
+
const breaker = new retry_1.CircuitBreaker(10, 3, 120000);
|
|
268
|
+
// Helper function with comprehensive error handling
|
|
269
|
+
async function safeDataSourceRetrieval(dataSourceId) {
|
|
270
|
+
try {
|
|
271
|
+
const result = await breaker.execute(() => notion.retrieveDataSource(dataSourceId), {
|
|
272
|
+
config: {
|
|
273
|
+
maxRetries: 5,
|
|
274
|
+
baseDelay: 1000,
|
|
275
|
+
maxDelay: 30000,
|
|
276
|
+
},
|
|
277
|
+
onRetry: (context) => {
|
|
278
|
+
// Log to monitoring service
|
|
279
|
+
console.log(`[RETRY] DataSource ${dataSourceId}: ` +
|
|
280
|
+
`attempt ${context.attempt}/${context.maxRetries}`);
|
|
281
|
+
},
|
|
282
|
+
context: `retrieveDataSource:${dataSourceId}`
|
|
283
|
+
});
|
|
284
|
+
return { success: true, data: result, error: null };
|
|
285
|
+
}
|
|
286
|
+
catch (error) {
|
|
287
|
+
// Log to error tracking service
|
|
288
|
+
console.error(`[ERROR] Failed to retrieve data source ${dataSourceId}: ${error.message}`);
|
|
289
|
+
// Check circuit breaker state
|
|
290
|
+
const state = breaker.getState();
|
|
291
|
+
if (state.state === 'open') {
|
|
292
|
+
console.error('[CRITICAL] Circuit breaker is open - service may be down');
|
|
293
|
+
}
|
|
294
|
+
return { success: false, data: null, error };
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
// Usage
|
|
298
|
+
const databaseId = 'your-database-id';
|
|
299
|
+
console.log(`Retrieving data source: ${databaseId}`);
|
|
300
|
+
const result = await safeDataSourceRetrieval(databaseId);
|
|
301
|
+
if (result.success) {
|
|
302
|
+
console.log('Success:', (_a = result.data) === null || _a === void 0 ? void 0 : _a.id);
|
|
303
|
+
// Get cache statistics for monitoring
|
|
304
|
+
// Cache statistics available via cacheManager.getStats() if needed
|
|
305
|
+
console.log(`Cache hit rate: ${(cache_1.cacheManager.getHitRate() * 100).toFixed(2)}%`);
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
console.error('Operation failed:', (_b = result.error) === null || _b === void 0 ? void 0 : _b.message);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Example 10: Configuration showcase
|
|
313
|
+
*/
|
|
314
|
+
async function example10_configurationShowcase() {
|
|
315
|
+
console.log('\n=== Example 10: Configuration Showcase ===');
|
|
316
|
+
// Show current cache configuration
|
|
317
|
+
const cacheConfig = cache_1.cacheManager.getConfig();
|
|
318
|
+
console.log('\nCache Configuration:');
|
|
319
|
+
console.log(` Enabled: ${cacheConfig.enabled}`);
|
|
320
|
+
console.log(` Default TTL: ${cacheConfig.defaultTtl}ms`);
|
|
321
|
+
console.log(` Max Size: ${cacheConfig.maxSize}`);
|
|
322
|
+
console.log(' TTL by type:');
|
|
323
|
+
console.log(` Data Sources: ${cacheConfig.ttlByType.dataSource}ms`);
|
|
324
|
+
console.log(` Databases: ${cacheConfig.ttlByType.database}ms`);
|
|
325
|
+
console.log(` Users: ${cacheConfig.ttlByType.user}ms`);
|
|
326
|
+
console.log(` Pages: ${cacheConfig.ttlByType.page}ms`);
|
|
327
|
+
console.log(` Blocks: ${cacheConfig.ttlByType.block}ms`);
|
|
328
|
+
// Show environment variables
|
|
329
|
+
console.log('\nEnvironment Variables:');
|
|
330
|
+
console.log(` NOTION_CLI_MAX_RETRIES: ${process.env.NOTION_CLI_MAX_RETRIES || 'default (3)'}`);
|
|
331
|
+
console.log(` NOTION_CLI_BASE_DELAY: ${process.env.NOTION_CLI_BASE_DELAY || 'default (1000ms)'}`);
|
|
332
|
+
console.log(` NOTION_CLI_CACHE_ENABLED: ${process.env.NOTION_CLI_CACHE_ENABLED || 'default (true)'}`);
|
|
333
|
+
console.log(` DEBUG: ${process.env.DEBUG || 'false'}`);
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Run all examples
|
|
337
|
+
*/
|
|
338
|
+
async function runAllExamples() {
|
|
339
|
+
console.log('='.repeat(60));
|
|
340
|
+
console.log('Enhanced Retry Logic and Caching Examples');
|
|
341
|
+
console.log('='.repeat(60));
|
|
342
|
+
// Note: These examples assume you have a valid NOTION_TOKEN
|
|
343
|
+
// and valid database IDs. Adjust the IDs in each example.
|
|
344
|
+
await example1_basicUsage();
|
|
345
|
+
await example2_cacheStats();
|
|
346
|
+
await example3_cacheInvalidation();
|
|
347
|
+
await example4_customRetry();
|
|
348
|
+
await example5_circuitBreaker();
|
|
349
|
+
await example6_batchOperations();
|
|
350
|
+
await example7_errorCategorization();
|
|
351
|
+
await example8_delayCalculation();
|
|
352
|
+
await example9_productionPattern();
|
|
353
|
+
await example10_configurationShowcase();
|
|
354
|
+
console.log('\n' + '='.repeat(60));
|
|
355
|
+
console.log('All examples completed!');
|
|
356
|
+
console.log('='.repeat(60));
|
|
357
|
+
}
|
|
358
|
+
// Export all examples
|
|
359
|
+
exports.default = {
|
|
360
|
+
example1_basicUsage,
|
|
361
|
+
example2_cacheStats,
|
|
362
|
+
example3_cacheInvalidation,
|
|
363
|
+
example4_customRetry,
|
|
364
|
+
example5_circuitBreaker,
|
|
365
|
+
example6_batchOperations,
|
|
366
|
+
example7_errorCategorization,
|
|
367
|
+
example8_delayCalculation,
|
|
368
|
+
example9_productionPattern,
|
|
369
|
+
example10_configurationShowcase,
|
|
370
|
+
runAllExamples,
|
|
371
|
+
};
|
|
372
|
+
// Run examples if executed directly
|
|
373
|
+
if (require.main === module) {
|
|
374
|
+
runAllExamples().catch(console.error);
|
|
375
|
+
}
|
package/dist/helper.d.ts
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { QueryDataSourceResponse, GetDataSourceResponse, DatabaseObjectResponse, DataSourceObjectResponse, PageObjectResponse, BlockObjectResponse } from '@notionhq/client/build/src/api-endpoints';
|
|
2
|
+
export declare const outputRawJson: (res: any) => Promise<void>;
|
|
3
|
+
/**
|
|
4
|
+
* Output data as compact JSON (single-line, no formatting)
|
|
5
|
+
* Useful for piping to other tools or scripts
|
|
6
|
+
*/
|
|
7
|
+
export declare const outputCompactJson: (res: any) => void;
|
|
8
|
+
/**
|
|
9
|
+
* Strip unnecessary metadata from Notion API responses to reduce size
|
|
10
|
+
* Removes created_by, last_edited_by, object fields, request_id, empty values, etc.
|
|
11
|
+
* Keeps timestamps (created_time, last_edited_time) and essential data
|
|
12
|
+
*
|
|
13
|
+
* @param data The data to strip metadata from (single object or array)
|
|
14
|
+
* @returns The stripped data
|
|
15
|
+
*/
|
|
16
|
+
export declare const stripMetadata: (data: any) => any;
|
|
17
|
+
/**
|
|
18
|
+
* Output data as a markdown table
|
|
19
|
+
* Converts column data into GitHub-flavored markdown table format
|
|
20
|
+
*/
|
|
21
|
+
export declare const outputMarkdownTable: (data: any[], columns: Record<string, any>) => void;
|
|
22
|
+
/**
|
|
23
|
+
* Output data as a pretty table with borders
|
|
24
|
+
* Enhanced table format with better visual separation
|
|
25
|
+
*/
|
|
26
|
+
export declare const outputPrettyTable: (data: any[], columns: Record<string, any>) => void;
|
|
27
|
+
/**
|
|
28
|
+
* Show a hint to users (especially AI assistants) that more data is available with the -r flag
|
|
29
|
+
* This makes the -r flag more discoverable for automation and AI use cases
|
|
30
|
+
*
|
|
31
|
+
* @param itemCount Number of items displayed in the table
|
|
32
|
+
* @param item The item object to count total fields from
|
|
33
|
+
* @param visibleFields Number of fields shown in the table (default: 4 for title, object, id, url)
|
|
34
|
+
*/
|
|
35
|
+
export declare function showRawFlagHint(itemCount: number, item: any, visibleFields?: number): void;
|
|
36
|
+
export declare const getFilterFields: (type: string) => Promise<{
|
|
37
|
+
title: string;
|
|
38
|
+
}[]>;
|
|
39
|
+
export declare const buildDatabaseQueryFilter: (name: string, type: string, field: string, value: string | string[] | boolean) => Promise<object | null>;
|
|
40
|
+
export declare const buildPagePropUpdateData: (name: string, type: string, value: string) => Promise<object | null>;
|
|
41
|
+
export declare const buildOneDepthJson: (pages: QueryDataSourceResponse["results"]) => Promise<{
|
|
42
|
+
oneDepthJson: any[];
|
|
43
|
+
relationJson: any[];
|
|
44
|
+
}>;
|
|
45
|
+
export declare const getDbTitle: (row: DatabaseObjectResponse) => string;
|
|
46
|
+
export declare const getDataSourceTitle: (row: GetDataSourceResponse | DataSourceObjectResponse) => string;
|
|
47
|
+
export declare const getPageTitle: (row: PageObjectResponse) => string;
|
|
48
|
+
export declare const getBlockPlainText: (row: BlockObjectResponse) => any;
|
|
49
|
+
/**
|
|
50
|
+
* Build block JSON from simple text-based flags
|
|
51
|
+
* Returns an array of block objects ready for Notion API
|
|
52
|
+
*/
|
|
53
|
+
export declare const buildBlocksFromTextFlags: (flags: {
|
|
54
|
+
text?: string;
|
|
55
|
+
heading1?: string;
|
|
56
|
+
heading2?: string;
|
|
57
|
+
heading3?: string;
|
|
58
|
+
bullet?: string;
|
|
59
|
+
numbered?: string;
|
|
60
|
+
todo?: string;
|
|
61
|
+
toggle?: string;
|
|
62
|
+
code?: string;
|
|
63
|
+
language?: string;
|
|
64
|
+
quote?: string;
|
|
65
|
+
callout?: string;
|
|
66
|
+
}) => any[];
|
|
67
|
+
/**
|
|
68
|
+
* Attempt to enrich a child_database block with its queryable data_source_id
|
|
69
|
+
*
|
|
70
|
+
* The Notion API returns child_database blocks without the database/data_source ID,
|
|
71
|
+
* making them unqueryable. This function attempts to resolve the block ID to a
|
|
72
|
+
* queryable data_source_id by trying to retrieve it as a data source.
|
|
73
|
+
*
|
|
74
|
+
* @param block The child_database block to enrich
|
|
75
|
+
* @returns The enriched block with data_source_id and database_id fields, or original block if resolution fails
|
|
76
|
+
*/
|
|
77
|
+
export declare const enrichChildDatabaseBlock: (block: BlockObjectResponse) => Promise<BlockObjectResponse>;
|
|
78
|
+
/**
|
|
79
|
+
* Get all child_database blocks from a list of blocks and enrich them with queryable IDs
|
|
80
|
+
*
|
|
81
|
+
* @param blocks Array of blocks to filter and enrich
|
|
82
|
+
* @returns Array of enriched child_database blocks with title, block_id, data_source_id, and database_id
|
|
83
|
+
*/
|
|
84
|
+
export declare const getChildDatabasesWithIds: (blocks: BlockObjectResponse[]) => Promise<any[]>;
|
|
85
|
+
/**
|
|
86
|
+
* Build block update content from simple text flags
|
|
87
|
+
* Returns an object with the block type properties for updating
|
|
88
|
+
*/
|
|
89
|
+
export declare const buildBlockUpdateFromTextFlags: (blockType: string, flags: {
|
|
90
|
+
text?: string;
|
|
91
|
+
heading1?: string;
|
|
92
|
+
heading2?: string;
|
|
93
|
+
heading3?: string;
|
|
94
|
+
bullet?: string;
|
|
95
|
+
numbered?: string;
|
|
96
|
+
todo?: string;
|
|
97
|
+
toggle?: string;
|
|
98
|
+
code?: string;
|
|
99
|
+
language?: string;
|
|
100
|
+
quote?: string;
|
|
101
|
+
callout?: string;
|
|
102
|
+
}) => any;
|