notion-ts-client
Version:
Generates an easy to use and fully typed API to access and modify the data in Notion Databases
217 lines (183 loc) • 6.03 kB
text/typescript
import { capitalizeVarName, makeConstVarName, makeTypeName } from '../../parsers'
import { ConfigFilePropertiesConfig } from '../../types'
export function getQueryTypes(dbTypeName: string, propsConfig: ConfigFilePropertiesConfig) {
const constVarName = makeConstVarName(dbTypeName)
const customFilterTypes = getCustomFilterTypes(dbTypeName, propsConfig)
const customPropFilterType = getDBCustomFilterType(dbTypeName, propsConfig)
return `${customFilterTypes}
${customPropFilterType}
export type ${dbTypeName}Query = Omit<QueryDatabaseBodyParameters, 'filter' | 'sorts'> & {
sorts?: Array<
| {
property: keyof typeof ${constVarName}_PROPS_TO_IDS
direction: 'ascending' | 'descending'
}
| {
timestamp: 'created_time' | 'last_edited_time'
direction: 'ascending' | 'descending'
}
>
filter?:
| {
or: Array<
| ${dbTypeName}PropertyFilter
| TimestampCreatedTimeFilter
| TimestampLastEditedTimeFilter
| {
// or: ${dbTypeName}Query['filter']
or: Array<${dbTypeName}PropertyFilter>
}
| {
// and: ${dbTypeName}Query['filter']
and: Array<${dbTypeName}PropertyFilter>
}
>
}
| {
and: Array<
| ${dbTypeName}PropertyFilter
| TimestampCreatedTimeFilter
| TimestampLastEditedTimeFilter
| {
// or: ${dbTypeName}Query['filter']
or: Array<${dbTypeName}PropertyFilter>
}
| {
// and: ${dbTypeName}Query['filter']
and: Array<${dbTypeName}PropertyFilter>
}
>
}
| ${dbTypeName}PropertyFilter
| TimestampCreatedTimeFilter
| TimestampLastEditedTimeFilter
}
export type ${dbTypeName}QueryFilter = ${dbTypeName}Query['filter']
export type ${dbTypeName}QueryResponse = {
results: ${dbTypeName}Response[]
next_cursor: string | null
has_more: boolean
}
`
}
function getDBCustomFilterType(dbTypeName: string, propsConfig: ConfigFilePropertiesConfig) {
const unionTypes = Object.values(propsConfig)
.map((prop) => {
if (prop._type === 'button') {
return
}
const typePrefix = `${dbTypeName}${makeTypeName(prop.varName)}`
return `{ ${prop.varName}: ${typePrefix}PropertyFilter }`
})
.filter((t) => t !== undefined)
return `export type ${dbTypeName}PropertyFilter = ${unionTypes.join(' | ')}`
}
function getCustomFilterTypes(dbTypeName: string, propsConfig: ConfigFilePropertiesConfig) {
return Object.values(propsConfig)
.map((prop) => {
const typePrefix = `${dbTypeName}${makeTypeName(prop.varName.replace(/_/g, ' '))}`
switch (prop._type) {
case 'status':
case 'select':
let exportStr
if (prop._name === 'Created by') {
exportStr = `export type ${typePrefix}PropertyType = NonNullable<${dbTypeName}Response['properties']['${prop._name}']['${prop._type}']>['name']`
} else {
exportStr = `export type ${typePrefix}PropertyType = ${dbTypeName}Response['properties']['${prop._name}']['${prop._type}']['name']`
}
return `\n${exportStr}
type ${typePrefix}PropertyFilter =
| {
equals: ${typePrefix}PropertyType
}
| {
does_not_equal: ${typePrefix}PropertyType
}
| ExistencePropertyFilter
`
case 'multi_select':
return `\nexport type ${typePrefix}PropertyType = ${dbTypeName}Response['properties']['${prop._name}']['multi_select'][number]['name']
type ${typePrefix}PropertyFilter =
| {
contains: ${typePrefix}PropertyType
}
| {
does_not_contain: ${typePrefix}PropertyType
}
| ExistencePropertyFilter
`
case 'title':
case 'rich_text':
case 'url':
case 'email':
case 'phone_number':
return `type ${typePrefix}PropertyFilter = TextPropertyFilter`
case 'created_by':
case 'last_edited_by':
return `type ${typePrefix}PropertyFilter = PeoplePropertyFilter`
case 'created_time':
case 'last_edited_time':
return `type ${typePrefix}PropertyFilter = DatePropertyFilter`
case 'files':
return `type ${typePrefix}PropertyFilter = ExistencePropertyFilter`
case 'unique_id':
return `type ${typePrefix}PropertyFilter = NumberPropertyFilter`
case 'button':
return
default:
return `type ${typePrefix}PropertyFilter = ${capitalizeVarName(prop._type)}PropertyFilter`
}
})
.filter((t) => t !== undefined)
.join('\n')
}
// ---
export function getQueryFilterTypeImports(propsConfig: ConfigFilePropertiesConfig) {
const imports = Object.values(propsConfig)
.map((prop) => getQueryImportType(prop._type))
.filter((i) => i !== undefined)
const uniqueImports = Array.from(new Set(imports)).sort()
return (
`ExistencePropertyFilter,
QueryDatabaseBodyParameters,
TimestampCreatedTimeFilter,
TimestampLastEditedTimeFilter,
` + uniqueImports.join(',\n')
)
}
function getQueryImportType(type: string) {
switch (type) {
case 'select':
case 'multi_select':
case 'button':
case 'files':
return
case 'title':
case 'rich_text':
case 'url':
case 'email':
case 'phone_number':
return `TextPropertyFilter`
case 'created_by':
case 'last_edited_by':
return `PeoplePropertyFilter`
case 'created_time':
case 'last_edited_time':
return `DatePropertyFilter`
case 'unique_id':
return `NumberPropertyFilter`
case 'status':
return
default:
return `${capitalizeVarName(type)}PropertyFilter`
}
}
// TODO: implement?
// export type AfishaWebHookOptions =
// | {
// trigger: 'prop-updated'
// properties: Array<keyof typeof AFISHA_PROP_VALUES>
// }
// | {
// trigger: 'page-updated' | 'page-added' | 'page-removed'
// }