@visus-io/notion-sdk-ts 2.0.0 → 2.1.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 (206) hide show
  1. package/README.md +66 -921
  2. package/dist/api/base.api.d.ts +161 -0
  3. package/dist/api/base.api.js +228 -0
  4. package/dist/api/blocks.api.d.ts +3867 -4
  5. package/dist/api/blocks.api.js +16 -47
  6. package/dist/api/comments.api.d.ts +259 -4
  7. package/dist/api/comments.api.js +11 -29
  8. package/dist/api/dataSources.api.d.ts +788 -4
  9. package/dist/api/dataSources.api.js +14 -28
  10. package/dist/api/databases.api.d.ts +491 -4
  11. package/dist/api/databases.api.js +20 -45
  12. package/dist/api/fileUploads.api.d.ts +25 -3
  13. package/dist/api/fileUploads.api.js +7 -2
  14. package/dist/api/index.d.ts +0 -1
  15. package/dist/api/index.js +0 -1
  16. package/dist/api/pages.api.d.ts +864 -3
  17. package/dist/api/pages.api.js +14 -28
  18. package/dist/api/search.api.d.ts +0 -1
  19. package/dist/api/search.api.js +5 -11
  20. package/dist/api/users.api.d.ts +40 -4
  21. package/dist/api/users.api.js +12 -35
  22. package/dist/client.d.ts +0 -1
  23. package/dist/client.js +0 -1
  24. package/dist/errors.d.ts +0 -1
  25. package/dist/errors.js +0 -1
  26. package/dist/helpers/block.helpers.d.ts +4 -1
  27. package/dist/helpers/block.helpers.js +11 -1
  28. package/dist/helpers/file.helpers.d.ts +0 -1
  29. package/dist/helpers/file.helpers.js +0 -1
  30. package/dist/helpers/filter.helpers.d.ts +0 -1
  31. package/dist/helpers/filter.helpers.js +0 -1
  32. package/dist/helpers/index.d.ts +0 -1
  33. package/dist/helpers/index.js +0 -1
  34. package/dist/helpers/pagination.helpers.d.ts +0 -1
  35. package/dist/helpers/pagination.helpers.js +0 -1
  36. package/dist/helpers/parent.helpers.d.ts +0 -1
  37. package/dist/helpers/parent.helpers.js +0 -1
  38. package/dist/helpers/property.helpers.d.ts +0 -1
  39. package/dist/helpers/property.helpers.js +0 -1
  40. package/dist/helpers/richText.helpers.d.ts +0 -1
  41. package/dist/helpers/richText.helpers.js +0 -1
  42. package/dist/helpers/sort.helpers.d.ts +0 -1
  43. package/dist/helpers/sort.helpers.js +0 -1
  44. package/dist/index.d.ts +0 -1
  45. package/dist/index.js +0 -1
  46. package/dist/models/base.model.d.ts +2 -3
  47. package/dist/models/base.model.js +0 -1
  48. package/dist/models/block.model.d.ts +0 -1
  49. package/dist/models/block.model.js +0 -1
  50. package/dist/models/comment.model.d.ts +0 -1
  51. package/dist/models/comment.model.js +0 -1
  52. package/dist/models/dataSource.model.d.ts +0 -1
  53. package/dist/models/dataSource.model.js +0 -1
  54. package/dist/models/database.model.d.ts +0 -1
  55. package/dist/models/database.model.js +0 -1
  56. package/dist/models/fileUpload.model.d.ts +0 -1
  57. package/dist/models/fileUpload.model.js +0 -1
  58. package/dist/models/index.d.ts +0 -1
  59. package/dist/models/index.js +0 -1
  60. package/dist/models/page.model.d.ts +0 -1
  61. package/dist/models/page.model.js +0 -1
  62. package/dist/models/richText.model.d.ts +0 -1
  63. package/dist/models/richText.model.js +0 -1
  64. package/dist/models/user.model.d.ts +0 -1
  65. package/dist/models/user.model.js +0 -1
  66. package/dist/notion.d.ts +0 -1
  67. package/dist/notion.js +0 -1
  68. package/dist/schemas/block.schema.d.ts +261 -82
  69. package/dist/schemas/block.schema.js +157 -82
  70. package/dist/schemas/codeLanguages.d.ts +0 -1
  71. package/dist/schemas/codeLanguages.js +0 -1
  72. package/dist/schemas/colors.d.ts +0 -1
  73. package/dist/schemas/colors.js +0 -1
  74. package/dist/schemas/comment.schema.d.ts +9 -10
  75. package/dist/schemas/comment.schema.js +54 -21
  76. package/dist/schemas/dataSource.schema.d.ts +13 -14
  77. package/dist/schemas/dataSource.schema.js +46 -13
  78. package/dist/schemas/database.schema.d.ts +13 -14
  79. package/dist/schemas/database.schema.js +51 -18
  80. package/dist/schemas/emoji.schema.d.ts +1 -2
  81. package/dist/schemas/emoji.schema.js +37 -5
  82. package/dist/schemas/file.schema.d.ts +3 -4
  83. package/dist/schemas/file.schema.js +49 -16
  84. package/dist/schemas/fileUpload.schema.d.ts +3 -4
  85. package/dist/schemas/fileUpload.schema.js +47 -14
  86. package/dist/schemas/index.d.ts +1 -1
  87. package/dist/schemas/index.js +1 -1
  88. package/dist/schemas/page.schema.d.ts +30 -31
  89. package/dist/schemas/page.schema.js +47 -14
  90. package/dist/schemas/pageProperties.schema.d.ts +47 -48
  91. package/dist/schemas/pageProperties.schema.js +162 -129
  92. package/dist/schemas/pagination.schema.d.ts +1 -2
  93. package/dist/schemas/pagination.schema.js +40 -8
  94. package/dist/schemas/parent.schema.d.ts +1 -2
  95. package/dist/schemas/parent.schema.js +51 -19
  96. package/dist/schemas/propertyObjects.schema.d.ts +1 -2
  97. package/dist/schemas/propertyObjects.schema.js +194 -162
  98. package/dist/schemas/richText.schema.d.ts +7 -8
  99. package/dist/schemas/richText.schema.js +95 -57
  100. package/dist/schemas/shared.schema.d.ts +15 -0
  101. package/dist/schemas/shared.schema.js +54 -0
  102. package/dist/schemas/user.schema.d.ts +3 -4
  103. package/dist/schemas/user.schema.js +63 -31
  104. package/dist/validation.d.ts +0 -1
  105. package/dist/validation.js +0 -1
  106. package/package.json +3 -1
  107. package/dist/api/blocks.api.d.ts.map +0 -1
  108. package/dist/api/blocks.api.js.map +0 -1
  109. package/dist/api/comments.api.d.ts.map +0 -1
  110. package/dist/api/comments.api.js.map +0 -1
  111. package/dist/api/dataSources.api.d.ts.map +0 -1
  112. package/dist/api/dataSources.api.js.map +0 -1
  113. package/dist/api/databases.api.d.ts.map +0 -1
  114. package/dist/api/databases.api.js.map +0 -1
  115. package/dist/api/fileUploads.api.d.ts.map +0 -1
  116. package/dist/api/fileUploads.api.js.map +0 -1
  117. package/dist/api/index.d.ts.map +0 -1
  118. package/dist/api/index.js.map +0 -1
  119. package/dist/api/pages.api.d.ts.map +0 -1
  120. package/dist/api/pages.api.js.map +0 -1
  121. package/dist/api/search.api.d.ts.map +0 -1
  122. package/dist/api/search.api.js.map +0 -1
  123. package/dist/api/users.api.d.ts.map +0 -1
  124. package/dist/api/users.api.js.map +0 -1
  125. package/dist/client.d.ts.map +0 -1
  126. package/dist/client.js.map +0 -1
  127. package/dist/errors.d.ts.map +0 -1
  128. package/dist/errors.js.map +0 -1
  129. package/dist/helpers/block.helpers.d.ts.map +0 -1
  130. package/dist/helpers/block.helpers.js.map +0 -1
  131. package/dist/helpers/file.helpers.d.ts.map +0 -1
  132. package/dist/helpers/file.helpers.js.map +0 -1
  133. package/dist/helpers/filter.helpers.d.ts.map +0 -1
  134. package/dist/helpers/filter.helpers.js.map +0 -1
  135. package/dist/helpers/index.d.ts.map +0 -1
  136. package/dist/helpers/index.js.map +0 -1
  137. package/dist/helpers/pagination.helpers.d.ts.map +0 -1
  138. package/dist/helpers/pagination.helpers.js.map +0 -1
  139. package/dist/helpers/parent.helpers.d.ts.map +0 -1
  140. package/dist/helpers/parent.helpers.js.map +0 -1
  141. package/dist/helpers/property.helpers.d.ts.map +0 -1
  142. package/dist/helpers/property.helpers.js.map +0 -1
  143. package/dist/helpers/richText.helpers.d.ts.map +0 -1
  144. package/dist/helpers/richText.helpers.js.map +0 -1
  145. package/dist/helpers/sort.helpers.d.ts.map +0 -1
  146. package/dist/helpers/sort.helpers.js.map +0 -1
  147. package/dist/index.d.ts.map +0 -1
  148. package/dist/index.js.map +0 -1
  149. package/dist/models/base.model.d.ts.map +0 -1
  150. package/dist/models/base.model.js.map +0 -1
  151. package/dist/models/block.model.d.ts.map +0 -1
  152. package/dist/models/block.model.js.map +0 -1
  153. package/dist/models/comment.model.d.ts.map +0 -1
  154. package/dist/models/comment.model.js.map +0 -1
  155. package/dist/models/dataSource.model.d.ts.map +0 -1
  156. package/dist/models/dataSource.model.js.map +0 -1
  157. package/dist/models/database.model.d.ts.map +0 -1
  158. package/dist/models/database.model.js.map +0 -1
  159. package/dist/models/fileUpload.model.d.ts.map +0 -1
  160. package/dist/models/fileUpload.model.js.map +0 -1
  161. package/dist/models/index.d.ts.map +0 -1
  162. package/dist/models/index.js.map +0 -1
  163. package/dist/models/page.model.d.ts.map +0 -1
  164. package/dist/models/page.model.js.map +0 -1
  165. package/dist/models/richText.model.d.ts.map +0 -1
  166. package/dist/models/richText.model.js.map +0 -1
  167. package/dist/models/user.model.d.ts.map +0 -1
  168. package/dist/models/user.model.js.map +0 -1
  169. package/dist/notion.d.ts.map +0 -1
  170. package/dist/notion.js.map +0 -1
  171. package/dist/schemas/block.schema.d.ts.map +0 -1
  172. package/dist/schemas/block.schema.js.map +0 -1
  173. package/dist/schemas/codeLanguages.d.ts.map +0 -1
  174. package/dist/schemas/codeLanguages.js.map +0 -1
  175. package/dist/schemas/colors.d.ts.map +0 -1
  176. package/dist/schemas/colors.js.map +0 -1
  177. package/dist/schemas/comment.schema.d.ts.map +0 -1
  178. package/dist/schemas/comment.schema.js.map +0 -1
  179. package/dist/schemas/dataSource.schema.d.ts.map +0 -1
  180. package/dist/schemas/dataSource.schema.js.map +0 -1
  181. package/dist/schemas/database.schema.d.ts.map +0 -1
  182. package/dist/schemas/database.schema.js.map +0 -1
  183. package/dist/schemas/emoji.schema.d.ts.map +0 -1
  184. package/dist/schemas/emoji.schema.js.map +0 -1
  185. package/dist/schemas/file.schema.d.ts.map +0 -1
  186. package/dist/schemas/file.schema.js.map +0 -1
  187. package/dist/schemas/fileUpload.schema.d.ts.map +0 -1
  188. package/dist/schemas/fileUpload.schema.js.map +0 -1
  189. package/dist/schemas/index.d.ts.map +0 -1
  190. package/dist/schemas/index.js.map +0 -1
  191. package/dist/schemas/page.schema.d.ts.map +0 -1
  192. package/dist/schemas/page.schema.js.map +0 -1
  193. package/dist/schemas/pageProperties.schema.d.ts.map +0 -1
  194. package/dist/schemas/pageProperties.schema.js.map +0 -1
  195. package/dist/schemas/pagination.schema.d.ts.map +0 -1
  196. package/dist/schemas/pagination.schema.js.map +0 -1
  197. package/dist/schemas/parent.schema.d.ts.map +0 -1
  198. package/dist/schemas/parent.schema.js.map +0 -1
  199. package/dist/schemas/propertyObjects.schema.d.ts.map +0 -1
  200. package/dist/schemas/propertyObjects.schema.js.map +0 -1
  201. package/dist/schemas/richText.schema.d.ts.map +0 -1
  202. package/dist/schemas/richText.schema.js.map +0 -1
  203. package/dist/schemas/user.schema.d.ts.map +0 -1
  204. package/dist/schemas/user.schema.js.map +0 -1
  205. package/dist/validation.d.ts.map +0 -1
  206. package/dist/validation.js.map +0 -1
package/README.md CHANGED
@@ -5,43 +5,12 @@
5
5
  [![Sonar Quality Gate](https://img.shields.io/sonar/quality_gate/visus%3Anotion-sdk-ts?server=https%3A%2F%2Fsonarcloud.io&style=for-the-badge&logo=sonarcloud&logoColor=white)](https://sonarcloud.io/summary/overall?id=visus%3Anotion-sdk-ts)
6
6
  [![Sonar Coverage](https://img.shields.io/sonar/coverage/visus%3Anotion-sdk-ts?server=https%3A%2F%2Fsonarcloud.io&style=for-the-badge&logo=sonarcloud&logoColor=white)](https://sonarcloud.io/summary/overall?id=visus%3Anotion-sdk-ts)
7
7
 
8
- ![NPM Version](https://img.shields.io/npm/v/%40visus-io%2Fnotion-sdk-ts?style=for-the-badge&logo=npm)
8
+ [![NPM Version](https://img.shields.io/npm/v/%40visus-io%2Fnotion-sdk-ts?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/@visus-io/notion-sdk-ts)
9
9
  ![NPM Downloads](https://img.shields.io/npm/dm/%40visus-io%2Fnotion-sdk-ts?style=for-the-badge&logo=npm)
10
10
  ![GitHub](https://img.shields.io/github/license/visus-io/notion-sdk-ts?style=for-the-badge)
11
11
 
12
12
  A type-safe TypeScript SDK for the Notion API with Zod validation, OOP models, and ergonomic helpers.
13
13
 
14
- ## Table of Contents
15
-
16
- - [Features](#features)
17
- - [Installation](#installation)
18
- - [Migration to API Version 2025-09-03](#migration-to-api-version-2025-09-03)
19
- - [Quick Start](#quick-start)
20
- - [Helpers](#helpers)
21
- - [Rich Text](#rich-text)
22
- - [Block Builder](#block-builder)
23
- - [Page Properties](#page-properties)
24
- - [Filters](#filters)
25
- - [Sorting](#sorting)
26
- - [Parent, Icon, Cover & File](#parent-icon-cover--file)
27
- - [Models](#models)
28
- - [Error Handling](#error-handling)
29
- - [Request Size Limits](#request-size-limits)
30
- - [Pagination](#pagination)
31
- - [Configuration](#configuration)
32
- - [API Reference](#api-reference)
33
- - [Pages](#pages-api)
34
- - [Blocks](#blocks-api)
35
- - [Databases](#databases-api)
36
- - [Data Sources](#data-sources-api)
37
- - [Comments](#comments-api)
38
- - [Search](#search-api)
39
- - [Users](#users-api)
40
- - [File Uploads](#file-uploads-api)
41
- - [TypeScript Support](#typescript-support)
42
- - [Development](#development)
43
- - [Project Structure](#project-structure)
44
-
45
14
  ## Features
46
15
 
47
16
  - **Type-safe** Zod v4 runtime validation on every API response; full TypeScript declarations
@@ -57,159 +26,16 @@ A type-safe TypeScript SDK for the Notion API with Zod validation, OOP models, a
57
26
 
58
27
  ```bash
59
28
  npm install @visus-io/notion-sdk-ts
29
+ # or
30
+ bun add @visus-io/notion-sdk-ts
60
31
  ```
61
32
 
62
- ## Migration to API Version 2025-09-03
63
-
64
- **This SDK now defaults to Notion API version `2025-09-03`** (previously `2022-06-28`). This version introduces breaking changes to support multi-source databases.
65
-
66
- ### What Changed
67
-
68
- **Database Creation**
69
-
70
- - Properties are now specified under `initial_data_source.properties` instead of top-level `properties`
71
- - Parent can be `{ page_id: string }` or `{ workspace: true }` (data source parents removed)
72
-
73
- ```typescript
74
- // ❌ Old (2022-06-28)
75
- await notion.databases.create({
76
- parent: { page_id: 'page-id' },
77
- properties: {
78
- Name: { title: {} },
79
- Status: {
80
- select: {
81
- options: [
82
- /* ... */
83
- ],
84
- },
85
- },
86
- },
87
- });
88
-
89
- // ✅ New (2025-09-03)
90
- await notion.databases.create({
91
- parent: { page_id: 'page-id' },
92
- initial_data_source: {
93
- properties: {
94
- Name: { title: {} },
95
- Status: {
96
- select: {
97
- options: [
98
- /* ... */
99
- ],
100
- },
101
- },
102
- },
103
- },
104
- });
105
- ```
106
-
107
- **Database Updates**
108
-
109
- - `properties` field removed from update options (use Data Sources API instead)
110
- - Added `is_inline` and `parent` fields for moving/configuring databases
111
-
112
- ```typescript
113
- // ❌ Old (2022-06-28) - properties updated on database
114
- await notion.databases.update('db-id', {
115
- properties: { NewField: { number: {} } },
116
- });
117
-
118
- // ✅ New (2025-09-03) - properties updated on data source
119
- const db = await notion.databases.retrieve('db-id');
120
- const dataSourceId = db.dataSources[0].id;
121
- await notion.dataSources.update(dataSourceId, {
122
- properties: { NewField: { number: {} } },
123
- });
124
- ```
125
-
126
- **Search API**
127
-
128
- - Search now returns `DataSource` objects instead of `Database` objects
129
- - Filter value changed from `'database'` to `'data_source'`
130
-
131
- ```typescript
132
- // ❌ Old (2022-06-28)
133
- const results = await notion.search.query({
134
- filter: { property: 'object', value: 'database' },
135
- });
136
-
137
- // ✅ New (2025-09-03)
138
- const results = await notion.search.query({
139
- filter: { property: 'object', value: 'data_source' },
140
- });
141
- ```
142
-
143
- **Page Creation with Database Parent**
144
-
145
- - Use `parent.dataSource(dataSourceId, databaseId)` instead of `parent.database(id)` for creating pages
146
- - Both data source ID and database ID are required
147
-
148
- ```typescript
149
- // ❌ Old (2022-06-28)
150
- await notion.pages.create({
151
- parent: parent.database('database-id'),
152
- properties: {
153
- /* ... */
154
- },
155
- });
156
-
157
- // ✅ New (2025-09-03) - recommended
158
- const db = await notion.databases.retrieve('database-id');
159
- const dataSourceId = db.dataSources[0].id;
160
- await notion.pages.create({
161
- parent: parent.dataSource(dataSourceId, db.id),
162
- properties: {
163
- /* ... */
164
- },
165
- });
166
- ```
167
-
168
- ### How to Get Data Source IDs
169
-
170
- ```typescript
171
- // Retrieve database to get its data sources
172
- const database = await notion.databases.retrieve('database-id');
173
-
174
- // Get the first (and usually only) data source
175
- const dataSourceId = database.dataSources[0].id;
176
-
177
- // Or iterate through all data sources
178
- database.dataSources.forEach((ds) => {
179
- console.log(`Data Source: ${ds.name} (${ds.id})`);
180
- });
181
- ```
182
-
183
- ### Reverting to Old Version
184
-
185
- If you need to stay on the old API version temporarily:
186
-
187
- ```typescript
188
- const notion = new Notion({
189
- auth: process.env.NOTION_TOKEN,
190
- notionVersion: '2022-06-28', // Use old version
191
- });
192
- ```
193
-
194
- **Note:** The old version may not work correctly with databases that have multiple data sources. We recommend migrating to `2025-09-03` as soon as possible.
195
-
196
- ### More Information
197
-
198
- For complete details, see the [official Notion API upgrade guide](https://developers.notion.com/guides/get-started/upgrade-guide-2025-09-03).
33
+ **Requirements:** Node.js 18+ or Bun 1.3.10+ (uses native `fetch`)
199
34
 
200
35
  ## Quick Start
201
36
 
202
37
  ```typescript
203
- import {
204
- Notion,
205
- block,
206
- richText,
207
- filter,
208
- sort,
209
- prop,
210
- parent,
211
- paginate,
212
- } from '@visus-io/notion-sdk-ts';
38
+ import { Notion, block, richText, filter, sort, prop, parent } from '@visus-io/notion-sdk-ts';
213
39
 
214
40
  const notion = new Notion({ auth: process.env.NOTION_TOKEN });
215
41
 
@@ -217,7 +43,7 @@ const notion = new Notion({ auth: process.env.NOTION_TOKEN });
217
43
  const page = await notion.pages.retrieve('page-id');
218
44
  console.log(page.getTitle());
219
45
 
220
- // Create a page in a database (2025-09-03 API)
46
+ // Create a page in a database
221
47
  const database = await notion.databases.retrieve('database-id');
222
48
  const dataSourceId = database.dataSources[0].id;
223
49
 
@@ -227,7 +53,6 @@ await notion.pages.create({
227
53
  Name: prop.title('New Task'),
228
54
  Status: prop.status('In Progress'),
229
55
  Priority: prop.select('High'),
230
- 'Due Date': prop.date('2025-03-01'),
231
56
  },
232
57
  });
233
58
 
@@ -236,14 +61,11 @@ await notion.blocks.children.append('page-id', {
236
61
  children: [
237
62
  block.heading2('Meeting Notes'),
238
63
  block.paragraph('Discussed the roadmap for Q2.'),
239
- block.paragraph(richText('Action item: ').build().concat(richText('ship v2').bold().build())),
240
64
  block.toDo('Follow up with design', { checked: false }),
241
- block.divider(),
242
- block.code('console.log("hello")', 'typescript'),
243
65
  ],
244
66
  });
245
67
 
246
- // Query a database with typed filters and sorts
68
+ // Query a database with filters
247
69
  const results = await notion.databases.query('database-id', {
248
70
  filter: filter.and(
249
71
  filter.status('Status').equals('In Progress'),
@@ -251,780 +73,103 @@ const results = await notion.databases.query('database-id', {
251
73
  ),
252
74
  sorts: [sort.property('Due Date').ascending()],
253
75
  });
254
-
255
- for (const page of results.results) {
256
- console.log(page.getTitle(), page.url);
257
- }
258
-
259
- // Search across workspace
260
- const search = await notion.search.query({
261
- query: 'project planning',
262
- filter: { property: 'object', value: 'page' },
263
- });
264
- ```
265
-
266
- ## Helpers
267
-
268
- The SDK provides namespace objects that eliminate the verbose JSON the Notion API requires. All text-accepting helpers accept a `string`, a `RichTextBuilder`, or a raw `NotionRichText` array.
269
-
270
- ### Rich Text
271
-
272
- Build formatted rich text with a chainable API:
273
-
274
- ```typescript
275
- import { richText } from '@visus-io/notion-sdk-ts';
276
-
277
- // Plain text
278
- richText('Hello world').build();
279
-
280
- // Chained formatting
281
- richText('Important').bold().italic().color('red').build();
282
-
283
- // Link
284
- richText('Notion').link('https://notion.so').build();
285
-
286
- // Combine multiple segments
287
- richText.join(
288
- richText('Normal '),
289
- richText('bold').bold(),
290
- richText(' and '),
291
- richText('italic').italic(),
292
- );
293
-
294
- // Mentions
295
- richText.mentionPage('page-id').build();
296
- richText.mentionDatabase('db-id').build();
297
- richText.mentionUser({ object: 'user', id: 'user-id' }).build();
298
- richText.mentionDate('2025-03-01').build();
299
- richText.mentionLinkPreview('https://example.com').build();
300
-
301
- // Inline equation
302
- richText.equation('E=mc^2').build();
303
76
  ```
304
77
 
305
- ### Block Builder
306
-
307
- Factory functions for all 31 block types. Returns plain objects ready for `blocks.children.append()` or `pages.create()`:
78
+ ## Documentation
308
79
 
309
- ```typescript
310
- import { block, richText } from '@visus-io/notion-sdk-ts';
80
+ Comprehensive documentation is available in the [**GitHub Wiki**](https://github.com/visus-io/notion-sdk-ts/wiki):
311
81
 
312
- const children = [
313
- // Text blocks (accept string, RichTextBuilder, or NotionRichText)
314
- block.heading1('Title'),
315
- block.heading2('Subtitle', { isToggleable: true }),
316
- block.paragraph('Plain text'),
317
- block.paragraph(richText('Styled text').bold().color('blue')),
318
- block.bulletedListItem('First item'),
319
- block.numberedListItem('Step one'),
320
- block.toDo('Task', { checked: true }),
321
- block.toggle('Click to expand', { children: [block.paragraph('Hidden content')] }),
322
- block.quote('A wise saying'),
323
- block.callout('Heads up!', { icon: { type: 'emoji', emoji: '⚠️' } }),
82
+ ### Getting Started
324
83
 
325
- // Code & math
326
- block.code('const x = 42;', 'typescript', { caption: 'Example' }),
327
- block.equation('\\sum_{i=1}^{n} i'),
84
+ - [**Getting Started**](https://github.com/visus-io/notion-sdk-ts/wiki/Getting-Started) - Installation, quick start, and basic configuration
85
+ - [**Migration Guide**](https://github.com/visus-io/notion-sdk-ts/wiki/Migration-Guide) - Migrating to API version 2025-09-03
86
+ - [**Common Use Cases**](https://github.com/visus-io/notion-sdk-ts/wiki/Common-Use-Cases) - Practical examples and workflows
328
87
 
329
- // Media (accept URL string or FileSource object)
330
- block.image('https://example.com/photo.png', { caption: 'Photo' }),
331
- block.video('https://example.com/video.mp4'),
332
- block.audio('https://example.com/song.mp3'),
333
- block.file('https://example.com/doc.pdf'),
334
- block.pdf('https://example.com/doc.pdf'),
88
+ ### Core Concepts
335
89
 
336
- // Embeds
337
- block.embed('https://twitter.com/example/status/123'),
338
- block.bookmark('https://example.com', { caption: 'Example site' }),
339
- block.linkPreview('https://github.com/example/repo'),
90
+ - [**Helpers**](https://github.com/visus-io/notion-sdk-ts/wiki/Helpers) - Rich Text, Block Builder, Properties, Filters, Sorting
91
+ - [**Models**](https://github.com/visus-io/notion-sdk-ts/wiki/Models) - Page, Block, Database, DataSource, User, Comment, FileUpload
92
+ - [**API Reference**](https://github.com/visus-io/notion-sdk-ts/wiki/API-Reference) - Complete API endpoint documentation
340
93
 
341
- // Structural
342
- block.divider(),
343
- block.breadcrumb(),
344
- block.tableOfContents(),
345
- block.table(3, {
346
- hasColumnHeader: true,
347
- children: [
348
- block.tableRow(['Name', 'Role', 'Status']),
349
- block.tableRow(['Alice', 'Engineer', 'Active']),
350
- ],
351
- }),
352
- block.columnList([[block.paragraph('Column 1')], [block.paragraph('Column 2')]]),
94
+ ### Configuration & Advanced Topics
353
95
 
354
- // Synced blocks
355
- block.syncedBlock({ children: [block.paragraph('Original content')] }),
356
- block.syncedBlock({ syncedFrom: 'source-block-id' }),
357
- ];
358
- ```
96
+ - [**Configuration & Features**](https://github.com/visus-io/notion-sdk-ts/wiki/Configuration) - Client options, rate limiting, retries
97
+ - [**Error Handling**](https://github.com/visus-io/notion-sdk-ts/wiki/Error-Handling) - Error types, codes, and handling patterns
98
+ - [**Pagination**](https://github.com/visus-io/notion-sdk-ts/wiki/Pagination) - Automatic pagination helpers
99
+ - [**Request Size Limits**](https://github.com/visus-io/notion-sdk-ts/wiki/Request-Size-Limits) - Notion API size limits
359
100
 
360
- ### Page Properties
101
+ ### Development
361
102
 
362
- Factory functions for setting page property values when creating or updating pages:
103
+ - [**TypeScript Support**](https://github.com/visus-io/notion-sdk-ts/wiki/TypeScript-Support) - Types, schemas, and type safety
104
+ - [**Development & Contributing**](https://github.com/visus-io/notion-sdk-ts/wiki/Development) - Project structure and architecture
363
105
 
364
- ```typescript
365
- import { prop, richText } from '@visus-io/notion-sdk-ts';
106
+ ## Migration Notice
366
107
 
367
- const properties = {
368
- Name: prop.title('My Task'),
369
- Description: prop.richText('Some notes'),
370
- Notes: prop.richText(richText('Important').bold()),
371
- Score: prop.number(95),
372
- Done: prop.checkbox(true),
373
- Priority: prop.select('High'),
374
- Tags: prop.multiSelect(['urgent', 'frontend']),
375
- Status: prop.status('In Progress'),
376
- 'Due Date': prop.date('2025-03-01'),
377
- 'Date Range': prop.date('2025-03-01', { end: '2025-03-15' }),
378
- Website: prop.url('https://example.com'),
379
- Contact: prop.email('user@example.com'),
380
- Phone: prop.phoneNumber('+1-555-0100'),
381
- Related: prop.relation(['page-id-1', 'page-id-2']),
382
- Assignee: prop.people(['user-id']),
383
- Attachments: prop.files([{ name: 'doc.pdf', url: 'https://example.com/doc.pdf' }]),
384
- };
108
+ **This SDK now defaults to Notion API version `2025-09-03`** (previously `2022-06-28`). This version introduces breaking changes for multi-source database support.
385
109
 
386
- // Clear a property by passing null
387
- prop.select(null);
388
- prop.date(null);
389
- prop.url(null);
390
- ```
110
+ ### Key Changes
391
111
 
392
- ### Filters
112
+ - **Database creation:** Properties moved to `initial_data_source.properties`
113
+ - **Database updates:** Use Data Sources API for property changes
114
+ - **Page creation:** Requires both data source ID and database ID
115
+ - **Search API:** Returns `DataSource` objects instead of `Database`
393
116
 
394
- Chainable filter builders for database queries:
117
+ ### Quick Migration Example
395
118
 
396
119
  ```typescript
397
- import { filter } from '@visus-io/notion-sdk-ts';
398
-
399
- // Single property filters
400
- filter.status('Status').equals('Active');
401
- filter.select('Priority').doesNotEqual('Low');
402
- filter.number('Score').greaterThan(80);
403
- filter.checkbox('Done').equals(false);
404
- filter.date('Due Date').before('2025-06-01');
405
- filter.date('Due Date').pastWeek();
406
- filter.text('Description').contains('important');
407
- filter.title('Name').startsWith('Project');
408
- filter.url('Website').isNotEmpty();
409
- filter.email('Contact').isNotEmpty();
410
- filter.multiSelect('Tags').contains('urgent');
411
- filter.people('Assignee').contains('user-id');
412
- filter.relation('Project').contains('page-id');
413
- filter.files('Attachments').isNotEmpty();
414
-
415
- // Timestamp filters (no property name needed)
416
- filter.createdTime().after('2025-01-01');
417
- filter.lastEditedTime().pastMonth();
418
-
419
- // Compound filters
420
- filter.and(
421
- filter.status('Status').equals('Active'),
422
- filter.number('Score').greaterThan(80),
423
- filter.or(filter.date('Due Date').before('2025-06-01'), filter.date('Due Date').isEmpty()),
424
- );
425
- ```
426
-
427
- ### Sorting
428
-
429
- ```typescript
430
- import { sort } from '@visus-io/notion-sdk-ts';
431
-
432
- const sorts = [
433
- sort.property('Priority').ascending(),
434
- sort.property('Due Date').descending(),
435
- sort.createdTime().descending(),
436
- sort.lastEditedTime().ascending(),
437
- ];
438
- ```
439
-
440
- ### Parent, Icon, Cover & File
441
-
442
- ```typescript
443
- import { parent, icon, cover, notionFile } from '@visus-io/notion-sdk-ts';
444
-
445
- // Parent objects
446
- parent.page('page-id');
447
- parent.dataSource('data-source-id', 'database-id'); // Note: both IDs required in 2025-09-03
448
- parent.workspace();
449
- parent.block('block-id'); // For comments on blocks
450
-
451
- // Icons
452
- icon.emoji('🚀');
453
- icon.external('https://example.com/icon.png');
454
- icon.fileUpload('upload-id');
455
-
456
- // Covers
457
- cover.external('https://example.com/banner.jpg');
458
- cover.fileUpload('upload-id');
459
-
460
- // File references
461
- notionFile.external('https://example.com/doc.pdf');
462
- notionFile.upload('upload-id');
463
- ```
464
-
465
- ## Models
466
-
467
- All API methods return model instances with typed properties and helper methods. Every model validates raw API data through its Zod schema on construction.
468
-
469
- ### Page
470
-
471
- ```typescript
472
- const page = await notion.pages.retrieve('page-id');
473
-
474
- page.id; // UUID
475
- page.url; // Notion URL
476
- page.publicUrl; // Public URL (if shared)
477
- page.createdTime; // Date
478
- page.lastEditedTime; // Date
479
- page.archived; // boolean
480
- page.inTrash; // boolean
481
- page.properties; // Record of property values
482
-
483
- page.getTitle(); // Plain text title
484
- page.getProperty('Name'); // Specific property value
485
- page.isInDatabase(); // true if parent is a database
486
- page.isSubpage(); // true if parent is a page
487
- page.toJSON(); // Raw validated data
488
- ```
489
-
490
- ### Block
491
-
492
- ```typescript
493
- const block = await notion.blocks.retrieve('block-id');
494
-
495
- block.id; // UUID
496
- block.type; // 'paragraph' | 'heading_1' | ...
497
- block.hasChildren; // boolean
498
-
499
- block.isTextBlock(); // paragraph, heading, list item, etc.
500
- block.isHeading(); // heading_1, heading_2, heading_3
501
- block.canHaveChildren(); // toggle, column, synced_block, etc.
502
- block.getPlainText(); // Extracted text content
503
- block.toJSON();
504
- ```
505
-
506
- ### Database
507
-
508
- ```typescript
509
- const db = await notion.databases.retrieve('database-id');
510
-
511
- db.id; // UUID
512
- db.title; // NotionRichText
513
- db.description; // NotionRichText
514
- db.dataSources; // DataSourceRef[]
515
- db.url; // Notion URL
516
- db.isInline; // boolean
517
-
518
- db.getTitle(); // Plain text title
519
- db.getDescription(); // Plain text description
520
- db.isFullPage(); // true if not inline
521
- db.hasPageParent();
522
- db.hasWorkspaceParent();
523
- db.toJSON();
524
- ```
525
-
526
- ### DataSource
527
-
528
- ```typescript
529
- const ds = await notion.dataSources.retrieve('data-source-id');
530
-
531
- ds.id; // UUID
532
- ds.properties; // Property configurations
533
-
534
- ds.getTitle();
535
- ds.getDescription();
536
- ds.getParentDatabaseId();
537
- ds.getProperty('Name'); // Specific property config
538
- ds.getPropertyNames(); // All property names
539
- ds.hasProperty('Status');
540
- ds.toJSON();
541
- ```
542
-
543
- ### User
544
-
545
- ```typescript
546
- const user = await notion.users.retrieve('user-id');
547
-
548
- user.id; // UUID
549
- user.type; // 'person' | 'bot' | undefined
550
- user.name; // string | undefined
551
- user.avatarUrl; // string | undefined
552
-
553
- user.isPerson(); // Type guard
554
- user.isBot(); // Type guard
555
- user.getEmail(); // Person users only
556
- user.getBotInfo(); // Bot users only
557
- user.toJSON();
558
- ```
559
-
560
- ### Comment
561
-
562
- ```typescript
563
- const comments = await notion.comments.list('page-id');
564
- const comment = comments.results[0];
565
-
566
- comment.id;
567
- comment.discussionId;
568
- comment.richText; // NotionRichText
569
- comment.createdTime; // Date
570
- comment.attachments;
571
- comment.displayName;
572
-
573
- comment.getPlainText();
574
- comment.hasAttachments();
575
- comment.hasCustomDisplayName();
576
- comment.getDisplayName(); // Resolved display name string
577
- comment.hasPageParent();
578
- comment.hasBlockParent();
579
- comment.toJSON();
580
- ```
581
-
582
- ### FileUpload
583
-
584
- ```typescript
585
- const upload = await notion.fileUploads.retrieve('upload-id');
586
-
587
- upload.id;
588
- upload.status; // 'pending' | 'uploaded' | 'expired' | 'failed'
589
- upload.filename;
590
- upload.contentType;
591
- upload.contentLength;
592
- upload.uploadUrl;
593
- upload.completeUrl;
594
-
595
- upload.isPending();
596
- upload.isUploaded();
597
- upload.isExpired();
598
- upload.isFailed();
599
- upload.toJSON();
600
- ```
601
-
602
- ### RichText Utility
603
-
604
- Parse and convert Notion rich text to other formats:
605
-
606
- ```typescript
607
- import { RichText } from '@visus-io/notion-sdk-ts';
608
-
609
- const rt = new RichText(page.properties.Name.title);
610
-
611
- rt.toPlainText(); // "Project Documentation"
612
- rt.toMarkdown(); // "**Project** Documentation"
613
- rt.toHTML(); // "<strong>Project</strong> Documentation"
614
- rt.hasLinks(); // boolean
615
- rt.getLinks(); // string[]
616
- rt.toJSON(); // Raw NotionRichText
617
- ```
618
-
619
- **Supported conversions:**
620
-
621
- | Format | Bold | Italic | Strikethrough | Underline | Code | Link |
622
- | -------- | ---------- | -------- | ------------- | --------- | ------------ | ------------- |
623
- | Markdown | `**text**` | `*text*` | `~~text~~` | -- | `` `text` `` | `[text](url)` |
624
- | HTML | `<strong>` | `<em>` | `<s>` | `<u>` | `<code>` | `<a href="">` |
625
-
626
- ## Error Handling
627
-
628
- Four error classes cover all failure modes:
629
-
630
- ```typescript
631
- import {
632
- NotionAPIError,
633
- NotionNetworkError,
634
- NotionRequestTimeoutError,
635
- NotionValidationError,
636
- } from '@visus-io/notion-sdk-ts';
637
-
638
- try {
639
- await notion.pages.retrieve('page-id');
640
- } catch (error) {
641
- if (error instanceof NotionValidationError) {
642
- // Client-side size limit exceeded (thrown before the request is sent)
643
- console.error(error.message);
644
- } else if (error instanceof NotionAPIError) {
645
- // Structured API error with status code and error code
646
- console.error(error.status, error.code, error.message);
647
-
648
- error.isNotFound(); // 404
649
- error.isUnauthorized(); // 401
650
- error.isValidationError(); // 400
651
- error.isRateLimited(); // 429 (auto-retried by default)
652
- error.isServerError(); // 5xx
653
- error.isRetryable(); // rate limited OR server error
654
- } else if (error instanceof NotionNetworkError) {
655
- // DNS failure, connection refused, etc.
656
- console.error(error.message, error.cause);
657
- } else if (error instanceof NotionRequestTimeoutError) {
658
- // Request exceeded configured timeout
659
- console.error(error.message);
660
- }
661
- }
662
- ```
663
-
664
- **Error codes:** `invalid_json`, `invalid_request_url`, `invalid_request`, `validation_error`, `missing_version`, `unauthorized`, `restricted_resource`, `object_not_found`, `conflict_error`, `rate_limited`, `internal_server_error`, `service_unavailable`, `database_connection_unavailable`, `gateway_timeout`
665
-
666
- ## Request Size Limits
667
-
668
- The SDK enforces [Notion API size limits](https://developers.notion.com/reference/request-limits#size-limits) client-side, throwing `NotionValidationError` before the request is sent. This applies at both layers: helpers validate when constructing objects, and API methods validate before sending.
669
-
670
- | Limit | Value | Where enforced |
671
- | ---------------------------- | ------------ | ----------------------------------------------------------------------------------------------- |
672
- | `text.content` length | 2,000 chars | `richText()`, `block.*()`, `prop.title()`, `prop.richText()` |
673
- | `text.link.url` length | 2,000 chars | `richText().link()` |
674
- | `equation.expression` length | 1,000 chars | `richText.equation()`, `block.equation()` |
675
- | Any URL property | 2,000 chars | `prop.url()`, `block.embed()`, `block.bookmark()`, `block.linkPreview()`, `block.image()`, etc. |
676
- | Email property | 200 chars | `prop.email()` |
677
- | Phone number property | 200 chars | `prop.phoneNumber()` |
678
- | Block/rich-text arrays | 100 elements | `blocks.children.append()`, `pages.create()`, `comments.create()`, `databases.create/update()` |
679
- | Multi-select options | 100 options | `prop.multiSelect()` |
680
- | Relation pages | 100 pages | `prop.relation()` |
681
- | People users | 100 users | `prop.people()` |
682
- | Comment attachments | 3 files | `comments.create()` |
683
- | `filter_properties` | 100 items | `pages.retrieve()`, `databases.retrieve/query()`, `dataSources.retrieve/query()` |
684
-
685
- All limit constants are exported as `LIMITS` for reference:
686
-
687
- ```typescript
688
- import { LIMITS } from '@visus-io/notion-sdk-ts';
689
-
690
- console.log(LIMITS.RICH_TEXT_CONTENT); // 2000
691
- console.log(LIMITS.URL); // 2000
692
- console.log(LIMITS.EMAIL); // 200
693
- console.log(LIMITS.ARRAY_ELEMENTS); // 100
694
- ```
695
-
696
- ## Pagination
697
-
698
- All list endpoints return `PaginatedList<T>` with cursor-based pagination:
699
-
700
- ```typescript
701
- interface PaginatedList<T> {
702
- results: T[];
703
- next_cursor: string | null;
704
- has_more: boolean;
705
- }
706
- ```
707
-
708
- The SDK provides helper utilities to automatically collect all results:
709
-
710
- ### `paginate()` - Collect all results
711
-
712
- Automatically fetches all pages and returns a single array:
713
-
714
- ```typescript
715
- import { paginate } from '@visus-io/notion-sdk-ts';
716
-
717
- // All blocks from a page
718
- const blocks = await paginate((cursor) =>
719
- notion.blocks.children.list('page-id', { start_cursor: cursor, page_size: 100 }),
720
- );
721
-
722
- // All pages from a database query
723
- const pages = await paginate((cursor) =>
724
- notion.databases.query('database-id', {
725
- start_cursor: cursor,
726
- page_size: 100,
727
- filter: filter.status('Status').equals('Active'),
728
- }),
729
- );
730
-
731
- // All comments on a page
732
- const comments = await paginate((cursor) =>
733
- notion.comments.list('page-id', { start_cursor: cursor }),
734
- );
735
-
736
- // All users in workspace
737
- const users = await paginate((cursor) => notion.users.list({ start_cursor: cursor }));
738
-
739
- // All search results
740
- const searchResults = await paginate((cursor) =>
741
- notion.search.query({
742
- query: 'project',
743
- filter: { property: 'object', value: 'page' },
744
- start_cursor: cursor,
745
- }),
746
- );
747
- ```
748
-
749
- ### `paginateIterator()` - Memory-efficient iteration
750
-
751
- Process results one at a time without loading everything into memory:
752
-
753
- ```typescript
754
- import { paginateIterator } from '@visus-io/notion-sdk-ts';
755
-
756
- // Process blocks one at a time
757
- for await (const block of paginateIterator((cursor) =>
758
- notion.blocks.children.list('page-id', { start_cursor: cursor }),
759
- )) {
760
- console.log(block.type, block.id);
761
- if (block.isTextBlock()) {
762
- console.log(block.getPlainText());
763
- }
764
- }
765
-
766
- // Process database pages one at a time
767
- for await (const page of paginateIterator((cursor) =>
768
- notion.databases.query('database-id', {
769
- start_cursor: cursor,
770
- filter: filter.status('Status').equals('Active'),
771
- }),
772
- )) {
773
- console.log(page.getTitle());
774
- // Process without loading all pages into memory
775
- }
776
- ```
777
-
778
- ### `paginateWithMetadata()` - Get results with pagination stats
779
-
780
- Useful for tracking API usage and performance:
781
-
782
- ```typescript
783
- import { paginateWithMetadata } from '@visus-io/notion-sdk-ts';
784
-
785
- const { items, pageCount, totalCount } = await paginateWithMetadata((cursor) =>
786
- notion.blocks.children.list('page-id', { start_cursor: cursor }),
787
- );
788
-
789
- console.log(`Fetched ${totalCount} blocks across ${pageCount} API calls`);
790
- ```
791
-
792
- **Paginated endpoints:** `blocks.children.list()`, `comments.list()`, `databases.query()`, `dataSources.query()`, `search.query()`, `users.list()`
793
-
794
- ## Configuration
795
-
796
- ```typescript
797
- const notion = new Notion({
798
- auth: process.env.NOTION_TOKEN, // Required
799
-
800
- // All optional:
801
- baseUrl: 'https://api.notion.com', // Default
802
- notionVersion: '2025-09-03', // Default (use '2022-06-28' for old version)
803
- timeoutMs: 60_000, // Default: 60s
804
- retryOnRateLimit: true, // Default: true
805
- maxRetries: 3, // Default: 3
806
- fetch: customFetch, // Custom fetch implementation
120
+ // OLD (2022-06-28)
121
+ await notion.pages.create({
122
+ parent: parent.database('database-id'),
123
+ properties: { Name: prop.title('Task') },
807
124
  });
808
- ```
809
-
810
- **Rate limiting:** The SDK automatically retries 429 responses using the server's `Retry-After` header when present, falling back to exponential backoff (1s, 2s, 4s, 8s... capped at 60s) otherwise. Disable with `retryOnRateLimit: false` or adjust with `maxRetries`.
811
-
812
- ## API Reference
813
-
814
- ### Pages API
815
-
816
- | Method | Description |
817
- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------ |
818
- | `pages.retrieve(id, options?)` | Get a page. Options: `filter_properties` (max 100) |
819
- | `pages.create(options)` | Create a page. Requires `parent` + `properties`. Optional: `icon`, `cover`, `children` (max 100), `template`, `position` |
820
- | `pages.update(id, options)` | Update properties, icon, cover, lock status, or archive state. Supports `erase_content` |
821
- | `pages.archive(id)` | Archive a page |
822
- | `pages.restore(id)` | Restore an archived page |
823
-
824
- ### Blocks API
825
125
 
826
- | Method | Description |
827
- | ------------------------------------- | --------------------------------------------------------- |
828
- | `blocks.retrieve(id, options?)` | Get a block |
829
- | `blocks.update(id, options)` | Update block content |
830
- | `blocks.delete(id)` | Delete (archive) a block |
831
- | `blocks.children.list(id, params?)` | List child blocks (paginated) |
832
- | `blocks.children.append(id, options)` | Append child blocks (max 100). Optional: `after` block ID |
833
-
834
- ### Databases API
835
-
836
- | Method | Description |
837
- | ---------------------------------- | ----------------------------------------------------------------------- |
838
- | `databases.retrieve(id, options?)` | Get a database |
839
- | `databases.query(id, options?)` | Query with `filter`, `sorts`, pagination. Returns `PaginatedList<Page>` |
840
- | `databases.create(options)` | Create a database. Requires `parent` + `properties` |
841
- | `databases.update(id, options)` | Update title, description, properties, icon, cover |
842
- | `databases.archive(id)` | Archive a database |
843
- | `databases.restore(id)` | Restore a database |
844
-
845
- ### Data Sources API
846
-
847
- Data sources represent individual tables under databases (API version 2025-09-03).
848
-
849
- | Method | Description |
850
- | ----------------------------------------- | -------------------------------------------------------------------- |
851
- | `dataSources.retrieve(id, options?)` | Get a data source |
852
- | `dataSources.query(id, options?)` | Query with filters/sorts. `result_type`: `'page'` or `'data_source'` |
853
- | `dataSources.create(options)` | Create a data source under a database |
854
- | `dataSources.update(id, options)` | Update a data source |
855
- | `dataSources.archive(id)` / `restore(id)` | Archive/restore |
856
- | `dataSources.trash(id)` / `untrash(id)` | Move to/from trash |
857
-
858
- ### Comments API
859
-
860
- | Method | Description |
861
- | ---------------------------------- | -------------------------------------------------------------------------------------------------------- |
862
- | `comments.list(parentId, params?)` | List comments on a page/block (paginated) |
863
- | `comments.create(options)` | Create a comment. Options: `parent`, `rich_text`, `discussion_id`, `attachments` (max 3), `display_name` |
864
-
865
- ### Search API
866
-
867
- | Method | Description |
868
- | ------------------------ | --------------------------------------------------------------------------------------------------------------------------- |
869
- | `search.query(options?)` | Search workspace. Filter by `'page'` or `'database'`. Sort by `last_edited_time`. Returns `PaginatedList<Page \| Database>` |
870
-
871
- ### Users API
872
-
873
- | Method | Description |
874
- | --------------------- | -------------------------------------- |
875
- | `users.list(params?)` | List all workspace users (paginated) |
876
- | `users.retrieve(id)` | Get a user by ID |
877
- | `users.me()` | Get the bot user for the current token |
878
-
879
- ### File Uploads API
880
-
881
- | Method | Description |
882
- | ----------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
883
- | `fileUploads.uploadFile(filename, data, contentType)` | Upload a file in one call (handles initiate + upload + complete). `data`: `Buffer \| ArrayBuffer \| Blob` |
884
- | `fileUploads.initiate(options)` | Step 1: Initiate upload |
885
- | `fileUploads.upload(url, data, contentType)` | Step 2: Upload file data |
886
- | `fileUploads.complete(url)` | Step 3: Mark upload complete |
887
- | `fileUploads.retrieve(id)` | Check upload status |
888
-
889
- **Full example:**
890
-
891
- ```typescript
892
- import { readFileSync } from 'fs';
893
-
894
- // One-step upload
895
- const upload = await notion.fileUploads.uploadFile(
896
- 'document.pdf',
897
- readFileSync('./document.pdf'),
898
- 'application/pdf',
899
- );
900
-
901
- console.log(upload.status); // 'uploaded'
126
+ // NEW (2025-09-03)
127
+ const db = await notion.databases.retrieve('database-id');
128
+ const dataSourceId = db.dataSources[0].id;
902
129
 
903
- // Or multi-step for more control
904
- const init = await notion.fileUploads.initiate({
905
- name: 'doc.pdf',
906
- content_type: 'application/pdf',
130
+ await notion.pages.create({
131
+ parent: parent.dataSource(dataSourceId, db.id),
132
+ properties: { Name: prop.title('Task') },
907
133
  });
908
- await notion.fileUploads.upload(init.uploadUrl, fileData, 'application/pdf');
909
- const completed = await notion.fileUploads.complete(init.completeUrl);
910
134
  ```
911
135
 
912
- ## TypeScript Support
136
+ See the [**Migration Guide**](https://github.com/visus-io/notion-sdk-ts/wiki/Migration-Guide) for complete details.
913
137
 
914
- All Zod schemas and their inferred types are exported:
138
+ ## Development
915
139
 
916
- ```typescript
917
- import type {
918
- NotionPage,
919
- NotionBlock,
920
- NotionDatabase,
921
- NotionUser,
922
- NotionComment,
923
- NotionDataSource,
924
- NotionFileUpload,
925
- NotionRichText,
926
- NotionParent,
927
- NotionFile,
928
- NotionColor,
929
- PaginatedList,
930
- } from '@visus-io/notion-sdk-ts';
140
+ This project uses [Bun](https://bun.sh) as its package manager for faster dependency installation and script execution.
931
141
 
932
- // Model classes
933
- import type {
934
- Page,
935
- Block,
936
- Database,
937
- User,
938
- Comment,
939
- DataSource,
940
- FileUpload,
941
- } from '@visus-io/notion-sdk-ts';
142
+ ### Prerequisites
942
143
 
943
- // Zod schemas for manual validation
944
- import { pageSchema, blockSchema, databaseSchema, userSchema } from '@visus-io/notion-sdk-ts';
144
+ Install Bun if you haven't already:
945
145
 
946
- const validated = pageSchema.parse(rawData);
146
+ ```bash
147
+ curl -fsSL https://bun.sh/install | bash
947
148
  ```
948
149
 
949
- **Supported block types (31):** paragraph, heading_1/2/3, bulleted_list_item, numbered_list_item, to_do, toggle, quote, callout, code, template, image, video, audio, file, pdf, bookmark, embed, child_database, child_page, column_list, column, divider, table_of_contents, breadcrumb, table, table_row, link_preview, synced_block, equation, unsupported
950
-
951
- **Supported property types (21):** title, rich_text, number, checkbox, date, url, email, phone_number, select, multi_select, status, relation, rollup, people, created_by, last_edited_by, created_time, last_edited_time, files, formula, unique_id, verification
952
-
953
- ## Development
150
+ ### Development Commands
954
151
 
955
152
  ```bash
956
- npm install # Install dependencies
957
- npm run build # Compile TypeScript to dist/
153
+ bun install # Install dependencies
154
+ bun run build # Compile TypeScript
958
155
 
959
- npm test # Run tests (Vitest)
960
- npm run test:watch # Watch mode
961
- npm run test:coverage # Coverage report (v8)
156
+ bun run test # Run tests
157
+ bun run test:watch # Watch mode
158
+ bun run test:coverage # Coverage report
962
159
 
963
- npm run lint # ESLint
964
- npm run lint:fix # Auto-fix lint issues
965
- npm run format # Prettier
966
- npm run format:check # Check formatting
160
+ bun run lint # ESLint
161
+ bun run lint:fix # Auto-fix
162
+ bun run format # Prettier
967
163
  ```
968
164
 
969
- ## Project Structure
970
-
971
- ```
972
- src/
973
- ├── index.ts # Entry point — re-exports everything
974
- ├── notion.ts # Notion class (main SDK entry)
975
- ├── client.ts # HTTP client with retry logic
976
- ├── errors.ts # NotionAPIError, NotionNetworkError, NotionRequestTimeoutError
977
- ├── validation.ts # NotionValidationError, LIMITS, size-limit validators
978
- ├── api/
979
- │ ├── blocks.api.ts # Blocks API
980
- │ ├── comments.api.ts # Comments API
981
- │ ├── databases.api.ts # Databases API
982
- │ ├── dataSources.api.ts # Data Sources API
983
- │ ├── fileUploads.api.ts # File Uploads API
984
- │ ├── pages.api.ts # Pages API
985
- │ ├── search.api.ts # Search API
986
- │ └── users.api.ts # Users API
987
- ├── helpers/
988
- │ ├── block.helpers.ts # block.paragraph(), block.heading1(), etc.
989
- │ ├── richText.helpers.ts # richText(), RichTextBuilder
990
- │ ├── filter.helpers.ts # filter.status(), filter.and(), etc.
991
- │ ├── sort.helpers.ts # sort.property(), sort.createdTime()
992
- │ ├── property.helpers.ts # prop.title(), prop.select(), etc.
993
- │ ├── parent.helpers.ts # parent.dataSource(), parent.page(), parent.workspace()
994
- │ └── file.helpers.ts # icon, cover, notionFile
995
- ├── models/
996
- │ ├── base.model.ts # Abstract BaseModel<T> with Zod validation
997
- │ ├── page.model.ts # Page
998
- │ ├── block.model.ts # Block
999
- │ ├── database.model.ts # Database
1000
- │ ├── dataSource.model.ts # DataSource
1001
- │ ├── comment.model.ts # Comment
1002
- │ ├── user.model.ts # User
1003
- │ ├── fileUpload.model.ts # FileUpload
1004
- │ └── richText.model.ts # RichText (toPlainText/toMarkdown/toHTML)
1005
- └── schemas/
1006
- ├── page.schema.ts # pageSchema + NotionPage
1007
- ├── block.schema.ts # blockSchema + NotionBlock (31 types)
1008
- ├── database.schema.ts # databaseSchema + NotionDatabase
1009
- ├── dataSource.schema.ts # dataSourceSchema + NotionDataSource
1010
- ├── comment.schema.ts # commentSchema + NotionComment
1011
- ├── user.schema.ts # userSchema + NotionUser
1012
- ├── fileUpload.schema.ts # fileUploadSchema + NotionFileUpload
1013
- ├── pageProperties.schema.ts # 21 page property value types
1014
- ├── propertyObjects.schema.ts# 21 database property config types
1015
- ├── richText.schema.ts # richTextSchema + 3 types + 6 mention types
1016
- ├── pagination.schema.ts # PaginatedList<T>, PaginationParameters
1017
- ├── parent.schema.ts # 5 parent types
1018
- ├── file.schema.ts # 3 file variants
1019
- ├── emoji.schema.ts # NotionEmoji
1020
- ├── colors.ts # NOTION_COLORS (19 colors)
1021
- └── codeLanguages.ts # CODE_BLOCK_LANGUAGES (75 languages)
1022
- ```
165
+ > **Note:** While this project uses Bun for development, the published package works with both Node.js 18+ and Bun 1.3.10+.
1023
166
 
1024
- **Architecture:** `Notion` (facade) -> `*API` classes (endpoint logic + Zod parsing) -> `NotionClient` (HTTP transport with retry). Every API response is validated through its Zod schema before being wrapped in a model class.
167
+ See [**Development & Contributing**](https://github.com/visus-io/notion-sdk-ts/wiki/Development) for more details.
1025
168
 
1026
169
  ## Links
1027
170
 
1028
- - [Notion API Documentation](https://developers.notion.com/reference/intro)
1029
- - [Notion API Changelog](https://developers.notion.com/page/changelog)
1030
- - [GitHub Repository](https://github.com/visus-io/notion-sdk-ts)
171
+ - [**Documentation Wiki**](https://github.com/visus-io/notion-sdk-ts/wiki)
172
+ - [**GitHub Repository**](https://github.com/visus-io/notion-sdk-ts)
173
+ - [**npm Package**](https://www.npmjs.com/package/@visus-io/notion-sdk-ts)
174
+ - [**Notion API Documentation**](https://developers.notion.com/reference/intro)
175
+ - [**Notion API Changelog**](https://developers.notion.com/page/changelog)