@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,359 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Property Example Generator for Notion API
|
|
4
|
+
*
|
|
5
|
+
* Generates copy-pastable property payload examples based on database schema.
|
|
6
|
+
* Helps AI agents understand the correct format for create/update operations.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.generatePropertyExamples = generatePropertyExamples;
|
|
10
|
+
exports.formatExamplesForConsole = formatExamplesForConsole;
|
|
11
|
+
exports.groupExamplesByWritability = groupExamplesByWritability;
|
|
12
|
+
/**
|
|
13
|
+
* Generate property examples for all properties in a data source schema
|
|
14
|
+
*
|
|
15
|
+
* @param properties - Properties object from GetDataSourceResponse
|
|
16
|
+
* @returns Array of property examples
|
|
17
|
+
*/
|
|
18
|
+
function generatePropertyExamples(properties) {
|
|
19
|
+
const examples = [];
|
|
20
|
+
for (const [propName, propDef] of Object.entries(properties)) {
|
|
21
|
+
const example = generateExampleForType(propName, propDef);
|
|
22
|
+
if (example) {
|
|
23
|
+
examples.push(example);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return examples;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Generate example for a single property based on its type
|
|
30
|
+
*
|
|
31
|
+
* @param name - Property name
|
|
32
|
+
* @param propDef - Property definition from Notion API
|
|
33
|
+
* @returns Property example or null if unsupported
|
|
34
|
+
*/
|
|
35
|
+
function generateExampleForType(name, propDef) {
|
|
36
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
37
|
+
if (!propDef || !propDef.type) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
const type = propDef.type;
|
|
41
|
+
switch (type) {
|
|
42
|
+
case 'title':
|
|
43
|
+
return {
|
|
44
|
+
property_name: name,
|
|
45
|
+
property_type: 'title',
|
|
46
|
+
simple_value: 'My Page Title',
|
|
47
|
+
notion_payload: {
|
|
48
|
+
[name]: {
|
|
49
|
+
title: [{ text: { content: 'My Page Title' } }]
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
description: 'Main title of the page (required for new pages)'
|
|
53
|
+
};
|
|
54
|
+
case 'rich_text':
|
|
55
|
+
return {
|
|
56
|
+
property_name: name,
|
|
57
|
+
property_type: 'rich_text',
|
|
58
|
+
simple_value: 'Some text content',
|
|
59
|
+
notion_payload: {
|
|
60
|
+
[name]: {
|
|
61
|
+
rich_text: [{ text: { content: 'Some text content' } }]
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
description: 'Multi-line text with optional formatting'
|
|
65
|
+
};
|
|
66
|
+
case 'number': {
|
|
67
|
+
const numberFormat = ((_a = propDef.number) === null || _a === void 0 ? void 0 : _a.format) || 'number';
|
|
68
|
+
return {
|
|
69
|
+
property_name: name,
|
|
70
|
+
property_type: 'number',
|
|
71
|
+
simple_value: 42,
|
|
72
|
+
notion_payload: {
|
|
73
|
+
[name]: { number: 42 }
|
|
74
|
+
},
|
|
75
|
+
description: `Numeric value (format: ${numberFormat})`
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
case 'checkbox':
|
|
79
|
+
return {
|
|
80
|
+
property_name: name,
|
|
81
|
+
property_type: 'checkbox',
|
|
82
|
+
simple_value: true,
|
|
83
|
+
notion_payload: {
|
|
84
|
+
[name]: { checkbox: true }
|
|
85
|
+
},
|
|
86
|
+
description: 'Boolean true/false value'
|
|
87
|
+
};
|
|
88
|
+
case 'select': {
|
|
89
|
+
const selectOptions = ((_b = propDef.select) === null || _b === void 0 ? void 0 : _b.options) || [];
|
|
90
|
+
const firstOption = ((_c = selectOptions[0]) === null || _c === void 0 ? void 0 : _c.name) || 'Option Name';
|
|
91
|
+
const selectOptionsList = selectOptions.map((o) => o.name).join(', ');
|
|
92
|
+
return {
|
|
93
|
+
property_name: name,
|
|
94
|
+
property_type: 'select',
|
|
95
|
+
simple_value: firstOption,
|
|
96
|
+
notion_payload: {
|
|
97
|
+
[name]: { select: { name: firstOption } }
|
|
98
|
+
},
|
|
99
|
+
description: selectOptions.length > 0
|
|
100
|
+
? `Single selection from: ${selectOptionsList}`
|
|
101
|
+
: 'Single selection (no options defined yet)'
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
case 'multi_select': {
|
|
105
|
+
const multiOptions = ((_d = propDef.multi_select) === null || _d === void 0 ? void 0 : _d.options) || [];
|
|
106
|
+
const exampleOptions = multiOptions.slice(0, 2).map((o) => o.name);
|
|
107
|
+
const multiOptionsList = multiOptions.map((o) => o.name).join(', ');
|
|
108
|
+
return {
|
|
109
|
+
property_name: name,
|
|
110
|
+
property_type: 'multi_select',
|
|
111
|
+
simple_value: exampleOptions,
|
|
112
|
+
notion_payload: {
|
|
113
|
+
[name]: {
|
|
114
|
+
multi_select: exampleOptions.map((n) => ({ name: n }))
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
description: multiOptions.length > 0
|
|
118
|
+
? `Multiple selections from: ${multiOptionsList}`
|
|
119
|
+
: 'Multiple selections (no options defined yet)'
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
case 'status': {
|
|
123
|
+
const statusOptions = ((_e = propDef.status) === null || _e === void 0 ? void 0 : _e.options) || [];
|
|
124
|
+
const firstStatus = ((_f = statusOptions[0]) === null || _f === void 0 ? void 0 : _f.name) || 'Status Name';
|
|
125
|
+
const statusOptionsList = statusOptions.map((o) => o.name).join(', ');
|
|
126
|
+
return {
|
|
127
|
+
property_name: name,
|
|
128
|
+
property_type: 'status',
|
|
129
|
+
simple_value: firstStatus,
|
|
130
|
+
notion_payload: {
|
|
131
|
+
[name]: { status: { name: firstStatus } }
|
|
132
|
+
},
|
|
133
|
+
description: statusOptions.length > 0
|
|
134
|
+
? `Status from: ${statusOptionsList}`
|
|
135
|
+
: 'Status value (no options defined yet)'
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
case 'date':
|
|
139
|
+
return {
|
|
140
|
+
property_name: name,
|
|
141
|
+
property_type: 'date',
|
|
142
|
+
simple_value: '2025-12-31',
|
|
143
|
+
notion_payload: {
|
|
144
|
+
[name]: { date: { start: '2025-12-31' } }
|
|
145
|
+
},
|
|
146
|
+
description: 'ISO date (YYYY-MM-DD) or date range with end property'
|
|
147
|
+
};
|
|
148
|
+
case 'url':
|
|
149
|
+
return {
|
|
150
|
+
property_name: name,
|
|
151
|
+
property_type: 'url',
|
|
152
|
+
simple_value: 'https://example.com',
|
|
153
|
+
notion_payload: {
|
|
154
|
+
[name]: { url: 'https://example.com' }
|
|
155
|
+
},
|
|
156
|
+
description: 'Valid URL starting with http:// or https://'
|
|
157
|
+
};
|
|
158
|
+
case 'email':
|
|
159
|
+
return {
|
|
160
|
+
property_name: name,
|
|
161
|
+
property_type: 'email',
|
|
162
|
+
simple_value: 'user@example.com',
|
|
163
|
+
notion_payload: {
|
|
164
|
+
[name]: { email: 'user@example.com' }
|
|
165
|
+
},
|
|
166
|
+
description: 'Valid email address'
|
|
167
|
+
};
|
|
168
|
+
case 'phone_number':
|
|
169
|
+
return {
|
|
170
|
+
property_name: name,
|
|
171
|
+
property_type: 'phone_number',
|
|
172
|
+
simple_value: '+1-555-123-4567',
|
|
173
|
+
notion_payload: {
|
|
174
|
+
[name]: { phone_number: '+1-555-123-4567' }
|
|
175
|
+
},
|
|
176
|
+
description: 'Phone number (any format)'
|
|
177
|
+
};
|
|
178
|
+
case 'people':
|
|
179
|
+
return {
|
|
180
|
+
property_name: name,
|
|
181
|
+
property_type: 'people',
|
|
182
|
+
simple_value: ['user-id-1', 'user-id-2'],
|
|
183
|
+
notion_payload: {
|
|
184
|
+
[name]: {
|
|
185
|
+
people: [
|
|
186
|
+
{ id: 'user-id-1' },
|
|
187
|
+
{ id: 'user-id-2' }
|
|
188
|
+
]
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
description: 'Array of Notion user IDs (use workspace users list to get IDs)'
|
|
192
|
+
};
|
|
193
|
+
case 'files':
|
|
194
|
+
return {
|
|
195
|
+
property_name: name,
|
|
196
|
+
property_type: 'files',
|
|
197
|
+
simple_value: 'https://example.com/file.pdf',
|
|
198
|
+
notion_payload: {
|
|
199
|
+
[name]: {
|
|
200
|
+
files: [
|
|
201
|
+
{
|
|
202
|
+
name: 'file.pdf',
|
|
203
|
+
type: 'external',
|
|
204
|
+
external: { url: 'https://example.com/file.pdf' }
|
|
205
|
+
}
|
|
206
|
+
]
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
description: 'External file URLs (Notion-hosted files cannot be set via API)'
|
|
210
|
+
};
|
|
211
|
+
case 'relation': {
|
|
212
|
+
const relatedDbId = ((_g = propDef.relation) === null || _g === void 0 ? void 0 : _g.database_id) || 'related-database-id';
|
|
213
|
+
return {
|
|
214
|
+
property_name: name,
|
|
215
|
+
property_type: 'relation',
|
|
216
|
+
simple_value: ['page-id-1', 'page-id-2'],
|
|
217
|
+
notion_payload: {
|
|
218
|
+
[name]: {
|
|
219
|
+
relation: [
|
|
220
|
+
{ id: 'page-id-1' },
|
|
221
|
+
{ id: 'page-id-2' }
|
|
222
|
+
]
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
description: `Array of page IDs from related database (${relatedDbId})`
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
// Read-only property types (cannot be set via API)
|
|
229
|
+
case 'created_time':
|
|
230
|
+
return {
|
|
231
|
+
property_name: name,
|
|
232
|
+
property_type: 'created_time',
|
|
233
|
+
simple_value: null,
|
|
234
|
+
notion_payload: {},
|
|
235
|
+
description: 'Read-only: Automatically set when page is created'
|
|
236
|
+
};
|
|
237
|
+
case 'created_by':
|
|
238
|
+
return {
|
|
239
|
+
property_name: name,
|
|
240
|
+
property_type: 'created_by',
|
|
241
|
+
simple_value: null,
|
|
242
|
+
notion_payload: {},
|
|
243
|
+
description: 'Read-only: Automatically set to user who created the page'
|
|
244
|
+
};
|
|
245
|
+
case 'last_edited_time':
|
|
246
|
+
return {
|
|
247
|
+
property_name: name,
|
|
248
|
+
property_type: 'last_edited_time',
|
|
249
|
+
simple_value: null,
|
|
250
|
+
notion_payload: {},
|
|
251
|
+
description: 'Read-only: Automatically updated when page is edited'
|
|
252
|
+
};
|
|
253
|
+
case 'last_edited_by':
|
|
254
|
+
return {
|
|
255
|
+
property_name: name,
|
|
256
|
+
property_type: 'last_edited_by',
|
|
257
|
+
simple_value: null,
|
|
258
|
+
notion_payload: {},
|
|
259
|
+
description: 'Read-only: Automatically set to user who last edited the page'
|
|
260
|
+
};
|
|
261
|
+
case 'formula': {
|
|
262
|
+
const expression = ((_h = propDef.formula) === null || _h === void 0 ? void 0 : _h.expression) || 'unknown';
|
|
263
|
+
return {
|
|
264
|
+
property_name: name,
|
|
265
|
+
property_type: 'formula',
|
|
266
|
+
simple_value: null,
|
|
267
|
+
notion_payload: {},
|
|
268
|
+
description: `Read-only: Computed formula (${expression})`
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
case 'rollup': {
|
|
272
|
+
const rollupFunc = ((_j = propDef.rollup) === null || _j === void 0 ? void 0 : _j.function) || 'unknown';
|
|
273
|
+
return {
|
|
274
|
+
property_name: name,
|
|
275
|
+
property_type: 'rollup',
|
|
276
|
+
simple_value: null,
|
|
277
|
+
notion_payload: {},
|
|
278
|
+
description: `Read-only: Rollup aggregation (${rollupFunc})`
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
case 'unique_id':
|
|
282
|
+
return {
|
|
283
|
+
property_name: name,
|
|
284
|
+
property_type: 'unique_id',
|
|
285
|
+
simple_value: null,
|
|
286
|
+
notion_payload: {},
|
|
287
|
+
description: 'Read-only: Auto-incrementing unique ID'
|
|
288
|
+
};
|
|
289
|
+
case 'verification':
|
|
290
|
+
return {
|
|
291
|
+
property_name: name,
|
|
292
|
+
property_type: 'verification',
|
|
293
|
+
simple_value: null,
|
|
294
|
+
notion_payload: {},
|
|
295
|
+
description: 'Read-only: Verification status'
|
|
296
|
+
};
|
|
297
|
+
default:
|
|
298
|
+
// Unsupported or unknown type
|
|
299
|
+
return {
|
|
300
|
+
property_name: name,
|
|
301
|
+
property_type: type,
|
|
302
|
+
simple_value: null,
|
|
303
|
+
notion_payload: {},
|
|
304
|
+
description: `Unsupported property type: ${type}`
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Format examples for human-readable console output
|
|
310
|
+
*
|
|
311
|
+
* @param examples - Array of property examples
|
|
312
|
+
* @returns Formatted string
|
|
313
|
+
*/
|
|
314
|
+
function formatExamplesForConsole(examples) {
|
|
315
|
+
const lines = [];
|
|
316
|
+
lines.push('');
|
|
317
|
+
lines.push('📋 Property Examples');
|
|
318
|
+
lines.push('='.repeat(80));
|
|
319
|
+
for (const example of examples) {
|
|
320
|
+
lines.push('');
|
|
321
|
+
lines.push(`${example.property_name} (${example.property_type})`);
|
|
322
|
+
lines.push(` ${example.description}`);
|
|
323
|
+
if (example.simple_value !== null) {
|
|
324
|
+
lines.push('');
|
|
325
|
+
lines.push(' Simple value:');
|
|
326
|
+
lines.push(` ${JSON.stringify(example.simple_value)}`);
|
|
327
|
+
lines.push('');
|
|
328
|
+
lines.push(' Notion API payload:');
|
|
329
|
+
const payload = JSON.stringify(example.notion_payload, null, 2);
|
|
330
|
+
const indentedPayload = payload.split('\n').map(line => ` ${line}`).join('\n');
|
|
331
|
+
lines.push(indentedPayload);
|
|
332
|
+
}
|
|
333
|
+
else {
|
|
334
|
+
lines.push('');
|
|
335
|
+
lines.push(' ⚠️ This property is read-only and cannot be set via API');
|
|
336
|
+
}
|
|
337
|
+
lines.push('-'.repeat(80));
|
|
338
|
+
}
|
|
339
|
+
return lines.join('\n');
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Group examples by writability (writable vs read-only)
|
|
343
|
+
*
|
|
344
|
+
* @param examples - Array of property examples
|
|
345
|
+
* @returns Grouped examples
|
|
346
|
+
*/
|
|
347
|
+
function groupExamplesByWritability(examples) {
|
|
348
|
+
const writable = [];
|
|
349
|
+
const readOnly = [];
|
|
350
|
+
for (const example of examples) {
|
|
351
|
+
if (example.simple_value === null && Object.keys(example.notion_payload).length === 0) {
|
|
352
|
+
readOnly.push(example);
|
|
353
|
+
}
|
|
354
|
+
else {
|
|
355
|
+
writable.push(example);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
return { writable, readOnly };
|
|
359
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { GetDataSourceResponse } from '@notionhq/client/build/src/api-endpoints';
|
|
2
|
+
/**
|
|
3
|
+
* Property schema for AI agents - simplified and easy to parse
|
|
4
|
+
*/
|
|
5
|
+
export interface PropertySchema {
|
|
6
|
+
name: string;
|
|
7
|
+
type: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
required?: boolean;
|
|
10
|
+
options?: string[];
|
|
11
|
+
config?: Record<string, any>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Database schema in AI-friendly format
|
|
15
|
+
*/
|
|
16
|
+
export interface DataSourceSchema {
|
|
17
|
+
id: string;
|
|
18
|
+
title: string;
|
|
19
|
+
description?: string;
|
|
20
|
+
properties: PropertySchema[];
|
|
21
|
+
url?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Extract clean, AI-parseable schema from Notion data source response
|
|
25
|
+
*
|
|
26
|
+
* This transforms the complex nested Notion API structure into a flat,
|
|
27
|
+
* easy-to-understand format that AI agents can work with directly.
|
|
28
|
+
*
|
|
29
|
+
* @param dataSource - Raw Notion data source response
|
|
30
|
+
* @returns Simplified schema object
|
|
31
|
+
*/
|
|
32
|
+
export declare function extractSchema(dataSource: GetDataSourceResponse): DataSourceSchema;
|
|
33
|
+
/**
|
|
34
|
+
* Filter properties by names
|
|
35
|
+
*
|
|
36
|
+
* @param schema - Full schema
|
|
37
|
+
* @param propertyNames - Array of property names to include
|
|
38
|
+
* @returns Filtered schema
|
|
39
|
+
*/
|
|
40
|
+
export declare function filterProperties(schema: DataSourceSchema, propertyNames: string[]): DataSourceSchema;
|
|
41
|
+
/**
|
|
42
|
+
* Format schema as human-readable table data
|
|
43
|
+
*
|
|
44
|
+
* @param schema - Schema to format
|
|
45
|
+
* @returns Array of objects for table display
|
|
46
|
+
*/
|
|
47
|
+
export declare function formatSchemaForTable(schema: DataSourceSchema): Array<Record<string, string>>;
|
|
48
|
+
/**
|
|
49
|
+
* Format schema as markdown documentation
|
|
50
|
+
*
|
|
51
|
+
* @param schema - Schema to format
|
|
52
|
+
* @returns Markdown string
|
|
53
|
+
*/
|
|
54
|
+
export declare function formatSchemaAsMarkdown(schema: DataSourceSchema): string;
|
|
55
|
+
/**
|
|
56
|
+
* Validate that a data object matches the schema
|
|
57
|
+
*
|
|
58
|
+
* @param schema - Schema to validate against
|
|
59
|
+
* @param data - Data object to validate
|
|
60
|
+
* @returns Validation result with errors
|
|
61
|
+
*/
|
|
62
|
+
export declare function validateAgainstSchema(schema: DataSourceSchema, data: Record<string, any>): {
|
|
63
|
+
valid: boolean;
|
|
64
|
+
errors: string[];
|
|
65
|
+
};
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractSchema = extractSchema;
|
|
4
|
+
exports.filterProperties = filterProperties;
|
|
5
|
+
exports.formatSchemaForTable = formatSchemaForTable;
|
|
6
|
+
exports.formatSchemaAsMarkdown = formatSchemaAsMarkdown;
|
|
7
|
+
exports.validateAgainstSchema = validateAgainstSchema;
|
|
8
|
+
/**
|
|
9
|
+
* Extract clean, AI-parseable schema from Notion data source response
|
|
10
|
+
*
|
|
11
|
+
* This transforms the complex nested Notion API structure into a flat,
|
|
12
|
+
* easy-to-understand format that AI agents can work with directly.
|
|
13
|
+
*
|
|
14
|
+
* @param dataSource - Raw Notion data source response
|
|
15
|
+
* @returns Simplified schema object
|
|
16
|
+
*/
|
|
17
|
+
function extractSchema(dataSource) {
|
|
18
|
+
const properties = [];
|
|
19
|
+
// Extract title from data source
|
|
20
|
+
const title = extractTitle(dataSource);
|
|
21
|
+
// Extract description if available
|
|
22
|
+
const description = extractDescription(dataSource);
|
|
23
|
+
// Process each property in the data source
|
|
24
|
+
if (dataSource.properties) {
|
|
25
|
+
for (const [propName, propConfig] of Object.entries(dataSource.properties)) {
|
|
26
|
+
const schema = extractPropertySchema(propName, propConfig);
|
|
27
|
+
if (schema) {
|
|
28
|
+
properties.push(schema);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
id: dataSource.id,
|
|
34
|
+
title,
|
|
35
|
+
description,
|
|
36
|
+
properties,
|
|
37
|
+
url: 'url' in dataSource ? dataSource.url : undefined,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Extract title from data source
|
|
42
|
+
*/
|
|
43
|
+
function extractTitle(dataSource) {
|
|
44
|
+
if ('title' in dataSource && Array.isArray(dataSource.title)) {
|
|
45
|
+
return dataSource.title
|
|
46
|
+
.map((t) => t.plain_text || '')
|
|
47
|
+
.join('')
|
|
48
|
+
.trim() || 'Untitled';
|
|
49
|
+
}
|
|
50
|
+
return 'Untitled';
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Extract description from data source
|
|
54
|
+
*/
|
|
55
|
+
function extractDescription(dataSource) {
|
|
56
|
+
if ('description' in dataSource && Array.isArray(dataSource.description)) {
|
|
57
|
+
const desc = dataSource.description
|
|
58
|
+
.map((d) => d.plain_text || '')
|
|
59
|
+
.join('')
|
|
60
|
+
.trim();
|
|
61
|
+
return desc || undefined;
|
|
62
|
+
}
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Extract individual property schema
|
|
67
|
+
*/
|
|
68
|
+
function extractPropertySchema(name, config) {
|
|
69
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
70
|
+
if (!config || !config.type) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
const schema = {
|
|
74
|
+
name,
|
|
75
|
+
type: config.type,
|
|
76
|
+
};
|
|
77
|
+
// Handle select and multi-select with options
|
|
78
|
+
if (config.type === 'select' && ((_a = config.select) === null || _a === void 0 ? void 0 : _a.options)) {
|
|
79
|
+
schema.options = config.select.options.map((opt) => opt.name);
|
|
80
|
+
schema.description = `Select one: ${schema.options.join(', ')}`;
|
|
81
|
+
}
|
|
82
|
+
if (config.type === 'multi_select' && ((_b = config.multi_select) === null || _b === void 0 ? void 0 : _b.options)) {
|
|
83
|
+
schema.options = config.multi_select.options.map((opt) => opt.name);
|
|
84
|
+
schema.description = `Select multiple: ${schema.options.join(', ')}`;
|
|
85
|
+
}
|
|
86
|
+
// Handle status property (similar to select)
|
|
87
|
+
if (config.type === 'status' && ((_c = config.status) === null || _c === void 0 ? void 0 : _c.options)) {
|
|
88
|
+
schema.options = config.status.options.map((opt) => opt.name);
|
|
89
|
+
schema.description = `Status: ${schema.options.join(', ')}`;
|
|
90
|
+
}
|
|
91
|
+
// Handle formula properties
|
|
92
|
+
if (config.type === 'formula' && ((_d = config.formula) === null || _d === void 0 ? void 0 : _d.expression)) {
|
|
93
|
+
schema.config = {
|
|
94
|
+
expression: config.formula.expression,
|
|
95
|
+
};
|
|
96
|
+
schema.description = `Formula: ${config.formula.expression}`;
|
|
97
|
+
}
|
|
98
|
+
// Handle rollup properties
|
|
99
|
+
if (config.type === 'rollup') {
|
|
100
|
+
schema.config = {
|
|
101
|
+
relation_property: (_e = config.rollup) === null || _e === void 0 ? void 0 : _e.relation_property_name,
|
|
102
|
+
rollup_property: (_f = config.rollup) === null || _f === void 0 ? void 0 : _f.rollup_property_name,
|
|
103
|
+
function: (_g = config.rollup) === null || _g === void 0 ? void 0 : _g.function,
|
|
104
|
+
};
|
|
105
|
+
schema.description = 'Rollup from related database';
|
|
106
|
+
}
|
|
107
|
+
// Handle relation properties
|
|
108
|
+
if (config.type === 'relation') {
|
|
109
|
+
schema.config = {
|
|
110
|
+
database_id: (_h = config.relation) === null || _h === void 0 ? void 0 : _h.database_id,
|
|
111
|
+
type: (_j = config.relation) === null || _j === void 0 ? void 0 : _j.type,
|
|
112
|
+
};
|
|
113
|
+
schema.description = 'Relation to another database';
|
|
114
|
+
}
|
|
115
|
+
// Handle number properties with format
|
|
116
|
+
if (config.type === 'number' && ((_k = config.number) === null || _k === void 0 ? void 0 : _k.format)) {
|
|
117
|
+
schema.config = {
|
|
118
|
+
format: config.number.format,
|
|
119
|
+
};
|
|
120
|
+
schema.description = `Number (${config.number.format})`;
|
|
121
|
+
}
|
|
122
|
+
// Mark title property as required
|
|
123
|
+
if (config.type === 'title') {
|
|
124
|
+
schema.required = true;
|
|
125
|
+
schema.description = 'Title (required)';
|
|
126
|
+
}
|
|
127
|
+
return schema;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Filter properties by names
|
|
131
|
+
*
|
|
132
|
+
* @param schema - Full schema
|
|
133
|
+
* @param propertyNames - Array of property names to include
|
|
134
|
+
* @returns Filtered schema
|
|
135
|
+
*/
|
|
136
|
+
function filterProperties(schema, propertyNames) {
|
|
137
|
+
const lowerNames = propertyNames.map(n => n.toLowerCase());
|
|
138
|
+
return {
|
|
139
|
+
...schema,
|
|
140
|
+
properties: schema.properties.filter(p => lowerNames.includes(p.name.toLowerCase())),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Format schema as human-readable table data
|
|
145
|
+
*
|
|
146
|
+
* @param schema - Schema to format
|
|
147
|
+
* @returns Array of objects for table display
|
|
148
|
+
*/
|
|
149
|
+
function formatSchemaForTable(schema) {
|
|
150
|
+
return schema.properties.map(prop => {
|
|
151
|
+
var _a;
|
|
152
|
+
return ({
|
|
153
|
+
name: prop.name,
|
|
154
|
+
type: prop.type,
|
|
155
|
+
required: prop.required ? 'Yes' : 'No',
|
|
156
|
+
options: ((_a = prop.options) === null || _a === void 0 ? void 0 : _a.join(', ')) || '-',
|
|
157
|
+
description: prop.description || '-',
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Format schema as markdown documentation
|
|
163
|
+
*
|
|
164
|
+
* @param schema - Schema to format
|
|
165
|
+
* @returns Markdown string
|
|
166
|
+
*/
|
|
167
|
+
function formatSchemaAsMarkdown(schema) {
|
|
168
|
+
var _a;
|
|
169
|
+
const lines = [];
|
|
170
|
+
lines.push(`# ${schema.title}`);
|
|
171
|
+
lines.push('');
|
|
172
|
+
if (schema.description) {
|
|
173
|
+
lines.push(schema.description);
|
|
174
|
+
lines.push('');
|
|
175
|
+
}
|
|
176
|
+
lines.push(`**Database ID:** \`${schema.id}\``);
|
|
177
|
+
if (schema.url) {
|
|
178
|
+
lines.push(`**URL:** ${schema.url}`);
|
|
179
|
+
}
|
|
180
|
+
lines.push('');
|
|
181
|
+
lines.push('## Properties');
|
|
182
|
+
lines.push('');
|
|
183
|
+
lines.push('| Name | Type | Required | Options/Details |');
|
|
184
|
+
lines.push('|------|------|----------|-----------------|');
|
|
185
|
+
for (const prop of schema.properties) {
|
|
186
|
+
const required = prop.required ? '✓' : '';
|
|
187
|
+
const details = ((_a = prop.options) === null || _a === void 0 ? void 0 : _a.join(', ')) || prop.description || '';
|
|
188
|
+
lines.push(`| ${prop.name} | ${prop.type} | ${required} | ${details} |`);
|
|
189
|
+
}
|
|
190
|
+
return lines.join('\n');
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Validate that a data object matches the schema
|
|
194
|
+
*
|
|
195
|
+
* @param schema - Schema to validate against
|
|
196
|
+
* @param data - Data object to validate
|
|
197
|
+
* @returns Validation result with errors
|
|
198
|
+
*/
|
|
199
|
+
function validateAgainstSchema(schema, data) {
|
|
200
|
+
const errors = [];
|
|
201
|
+
// Check required properties
|
|
202
|
+
for (const prop of schema.properties) {
|
|
203
|
+
if (prop.required && !(prop.name in data)) {
|
|
204
|
+
errors.push(`Missing required property: ${prop.name}`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
// Check property types and options
|
|
208
|
+
for (const [key, value] of Object.entries(data)) {
|
|
209
|
+
const propSchema = schema.properties.find(p => p.name === key);
|
|
210
|
+
if (!propSchema) {
|
|
211
|
+
errors.push(`Unknown property: ${key}`);
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
// Validate select/multi-select options
|
|
215
|
+
if (propSchema.options && propSchema.options.length > 0) {
|
|
216
|
+
if (propSchema.type === 'select') {
|
|
217
|
+
if (typeof value === 'string' && !propSchema.options.includes(value)) {
|
|
218
|
+
errors.push(`Invalid option for ${key}: ${value}. Must be one of: ${propSchema.options.join(', ')}`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (propSchema.type === 'multi_select') {
|
|
222
|
+
if (Array.isArray(value)) {
|
|
223
|
+
const invalidOptions = value.filter(v => !propSchema.options.includes(v));
|
|
224
|
+
if (invalidOptions.length > 0) {
|
|
225
|
+
errors.push(`Invalid options for ${key}: ${invalidOptions.join(', ')}`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return {
|
|
232
|
+
valid: errors.length === 0,
|
|
233
|
+
errors,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shell Configuration Utility
|
|
3
|
+
*
|
|
4
|
+
* Detects the user's shell and persists environment variables (e.g., NOTION_TOKEN)
|
|
5
|
+
* to the appropriate rc file (.zshrc, .bashrc, etc.).
|
|
6
|
+
*
|
|
7
|
+
* Used by both `config set-token` and `init` commands to avoid duplicating
|
|
8
|
+
* shell detection and rc file writing logic.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Detect the current shell from the SHELL environment variable.
|
|
12
|
+
* Falls back to bash on Unix, powershell on Windows.
|
|
13
|
+
*/
|
|
14
|
+
export declare function detectShell(): string;
|
|
15
|
+
/**
|
|
16
|
+
* Resolve the path to the shell's rc/config file.
|
|
17
|
+
*/
|
|
18
|
+
export declare function getRcFilePath(shell: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* Persist a Notion token to the user's shell rc file.
|
|
21
|
+
*
|
|
22
|
+
* Reads the rc file, checks if NOTION_TOKEN already exists (replaces it if so),
|
|
23
|
+
* otherwise appends a new export line. Creates the file if it doesn't exist.
|
|
24
|
+
*
|
|
25
|
+
* Returns the shell name and rc file path so callers can inform the user.
|
|
26
|
+
*/
|
|
27
|
+
export declare function persistToken(token: string): Promise<{
|
|
28
|
+
rcFile: string;
|
|
29
|
+
shell: string;
|
|
30
|
+
}>;
|