1
1
// Find the official Notion API client @ https:// github.com/makenotion/notion-sdk-js/
2
2
// npm install @notionhq /client
3
3
import { Client } from "@notionhq/client"
4
+ import {
5
+ CreatePageBodyParameters ,
6
+ CreatePageParameters ,
7
+ GetDatabaseResponse ,
8
+ GetPageResponse ,
9
+ } from "@notionhq/client/build/src/api-endpoints"
4
10
5
11
import * as _ from "lodash"
6
12
7
13
import { config } from "dotenv"
8
14
config ( )
9
15
10
16
import * as faker from "faker"
11
- import {
12
- InputPropertyValueMap ,
13
- PropertyMap ,
14
- } from "@notionhq/client/build/src/api-endpoints"
15
- import {
16
- PropertyValueWithoutId ,
17
- SelectFilter ,
18
- TextFilter ,
19
- UserBase ,
20
- } from "@notionhq/client/build/src/api-types"
21
17
22
18
const notion = new Client ( { auth : process . env [ "NOTION_KEY" ] } )
23
19
24
20
const startTime = new Date ( )
21
+ startTime . setSeconds ( 0 , 0 )
25
22
26
23
// Given the properties of a database, generate an object full of
27
24
// random data that can be used to generate new rows in our Notion database.
28
25
function makeFakePropertiesData (
29
- properties : PropertyMap
30
- ) : InputPropertyValueMap {
31
- const propertyValues : InputPropertyValueMap = { }
26
+ properties : GetDatabaseResponse [ "properties" ]
27
+ ) : Record < string , CreatePageBodyParameters [ "properties" ] > {
28
+ const propertyValues : Record < string , CreatePageBodyParameters [ "properties" ] > =
29
+ { }
32
30
Object . entries ( properties ) . forEach ( ( [ name , property ] ) => {
33
31
if ( property . type === "date" ) {
34
32
propertyValues [ name ] = {
@@ -117,15 +115,17 @@ function assertUnreachable(_x: never): never {
117
115
throw new Error ( "Didn't expect to get here" )
118
116
}
119
117
120
- function userToString ( userBase : UserBase ) {
118
+ function userToString ( userBase : { id : string ; name ?: string | null } ) {
121
119
return `${ userBase . id } : ${ userBase . name || "Unknown Name" } `
122
120
}
123
121
124
- function findRandomSelectColumnNameAndValue ( properties : PropertyMap ) : {
122
+ function findRandomSelectColumnNameAndValue (
123
+ properties : GetDatabaseResponse [ "properties" ]
124
+ ) : {
125
125
name : string
126
126
value : string | undefined
127
127
} {
128
- const options = Object . entries ( properties ) . flatMap ( ( [ name , property ] ) => {
128
+ const options = _ . flatMap ( Object . entries ( properties ) , ( [ name , property ] ) => {
129
129
if ( property . type === "select" ) {
130
130
return [
131
131
{ name, value : _ . sample ( property . select . options . map ( o => o . name ) ) } ,
@@ -141,7 +141,9 @@ function findRandomSelectColumnNameAndValue(properties: PropertyMap): {
141
141
return { name : "" , value : undefined }
142
142
}
143
143
144
- function extractValueToString ( property : PropertyValueWithoutId ) : string {
144
+ function extractValueToString (
145
+ property : GetPageResponse [ "properties" ] [ string ]
146
+ ) : string {
145
147
switch ( property . type ) {
146
148
case "checkbox" :
147
149
return property . checkbox . toString ( )
@@ -160,8 +162,14 @@ function extractValueToString(property: PropertyValueWithoutId): string {
160
162
case "phone_number" :
161
163
return property . phone_number
162
164
case "select" :
165
+ if ( ! property . select ) {
166
+ return ""
167
+ }
163
168
return `${ property . select . id } ${ property . select . name } `
164
169
case "multi_select" :
170
+ if ( ! property . multi_select ) {
171
+ return ""
172
+ }
165
173
return property . multi_select
166
174
. map ( select => `${ select . id } ${ select . name } ` )
167
175
. join ( ", " )
@@ -183,27 +191,43 @@ function extractValueToString(property: PropertyValueWithoutId): string {
183
191
} else if ( property . formula . type === "number" ) {
184
192
return property . formula . number ?. toString ( ) || "???"
185
193
} else if ( property . formula . type === "boolean" ) {
186
- return property . formula . boolean . toString ( )
194
+ return property . formula . boolean ? .toString ( ) || "???"
187
195
} else if ( property . formula . type === "date" ) {
188
- return new Date ( property . formula . date . date . start ) . toISOString ( )
196
+ return (
197
+ ( property . formula . date ?. start &&
198
+ new Date ( property . formula . date . start ) . toISOString ( ) ) ||
199
+ "???"
200
+ )
189
201
} else {
190
202
return assertUnreachable ( property . formula )
191
203
}
192
204
case "rollup" :
193
205
if ( property . rollup . type === "number" ) {
194
- return property . rollup . number . toString ( )
206
+ return property . rollup . number ? .toString ( ) || "???"
195
207
} else if ( property . rollup . type === "date" ) {
196
- return new Date ( property . rollup . date . date . start ) . toISOString ( )
208
+ return (
209
+ ( property . rollup . date ?. start &&
210
+ new Date ( property . rollup . date ?. start ) . toISOString ( ) ) ||
211
+ "???"
212
+ )
197
213
} else if ( property . rollup . type === "array" ) {
198
214
return JSON . stringify ( property . rollup . array )
199
215
} else {
200
216
return assertUnreachable ( property . rollup )
201
217
}
218
+ case "relation" :
219
+ if ( property . relation ) {
220
+ return property . relation . join ( "," )
221
+ }
222
+ return "???"
202
223
}
203
224
return assertUnreachable ( property )
204
225
}
205
226
206
- async function exerciseWriting ( databaseId : string , properties : PropertyMap ) {
227
+ async function exerciseWriting (
228
+ databaseId : string ,
229
+ properties : GetDatabaseResponse [ "properties" ]
230
+ ) {
207
231
console . log ( "\n\n********* Exercising Writing *********\n\n" )
208
232
209
233
const RowsToWrite = 10
@@ -212,18 +236,23 @@ async function exerciseWriting(databaseId: string, properties: PropertyMap) {
212
236
for ( let i = 0 ; i < RowsToWrite ; i ++ ) {
213
237
const propertiesData = makeFakePropertiesData ( properties )
214
238
215
- await notion . pages . create ( {
239
+ const parameters : CreatePageParameters = {
216
240
parent : {
217
241
database_id : databaseId ,
218
242
} ,
219
243
properties : propertiesData ,
220
- } )
244
+ } as CreatePageParameters
245
+
246
+ await notion . pages . create ( parameters )
221
247
}
222
248
223
249
console . log ( `Wrote ${ RowsToWrite } rows after ${ startTime } ` )
224
250
}
225
251
226
- async function exerciseReading ( databaseId : string , _properties : PropertyMap ) {
252
+ async function exerciseReading (
253
+ databaseId : string ,
254
+ _properties : GetDatabaseResponse [ "properties" ]
255
+ ) {
227
256
console . log ( "\n\n********* Exercising Reading *********\n\n" )
228
257
// and read back what we just did
229
258
const queryResponse = await notion . databases . query ( {
@@ -232,7 +261,7 @@ async function exerciseReading(databaseId: string, _properties: PropertyMap) {
232
261
let numOldRows = 0
233
262
queryResponse . results . map ( page => {
234
263
const createdTime = new Date ( page . created_time )
235
- if ( createdTime <= startTime ) {
264
+ if ( startTime > createdTime ) {
236
265
numOldRows ++
237
266
return
238
267
}
@@ -246,11 +275,14 @@ async function exerciseReading(databaseId: string, _properties: PropertyMap) {
246
275
} )
247
276
} )
248
277
console . log (
249
- `Skipped printing ${ numOldRows } rows that were written before this test `
278
+ `Skipped printing ${ numOldRows } rows that were written before ${ startTime } `
250
279
)
251
280
}
252
281
253
- async function exerciseFilters ( databaseId : string , properties : PropertyMap ) {
282
+ async function exerciseFilters (
283
+ databaseId : string ,
284
+ properties : GetDatabaseResponse [ "properties" ]
285
+ ) {
254
286
console . log ( "\n\n********* Exercising Filters *********\n\n" )
255
287
256
288
// get a random select or multi-select column from the collection with a random value for it
@@ -264,7 +296,7 @@ async function exerciseFilters(databaseId: string, properties: PropertyMap) {
264
296
console . log ( `Looking for ${ selectColumnName } =${ selectColumnValue } ` )
265
297
266
298
// Check we can search by name
267
- const queryFilterSelectFilterTypeBased : SelectFilter = {
299
+ const queryFilterSelectFilterTypeBased = {
268
300
property : selectColumnName ,
269
301
select : { equals : selectColumnValue } ,
270
302
}
@@ -288,14 +320,14 @@ async function exerciseFilters(databaseId: string, properties: PropertyMap) {
288
320
"Need a rich_text column for this part of the test, could not find one"
289
321
)
290
322
}
291
- const textColumnId = textColumn . id
323
+ const textColumnId = decodeURIComponent ( textColumn . id )
292
324
const letterToFind = faker . lorem . word ( 1 )
293
325
294
326
console . log (
295
- `\n\nLooking for text column with id ${ textColumnId } contains letter ${ letterToFind } `
327
+ `\n\nLooking for text column with id " ${ textColumnId } " contains letter " ${ letterToFind } " `
296
328
)
297
329
298
- const textFilter : TextFilter = {
330
+ const textFilter = {
299
331
property : textColumnId ,
300
332
text : { contains : letterToFind } ,
301
333
}
@@ -307,7 +339,7 @@ async function exerciseFilters(databaseId: string, properties: PropertyMap) {
307
339
} )
308
340
309
341
console . log (
310
- `Had ${ matchingTextResults . results . length } matching rows in column with ID ${ textColumnId } containing letter ${ letterToFind } `
342
+ `Had ${ matchingTextResults . results . length } matching rows in column with ID " ${ textColumnId } " containing letter " ${ letterToFind } " `
311
343
)
312
344
}
313
345
0 commit comments