notion-ts-client
Version:
Generates an easy to use and fully typed API to access and modify the data in Notion Databases
158 lines (132 loc) • 4.91 kB
text/typescript
import { ConfigFilePropertiesConfig } from '../../types'
import { saveContentToFile } from '../file-utils'
const TYPE_INDENT = ' '
const PATCH_IGNORE_PROPS = ['created_by', 'created_time', 'last_edited_by', 'last_edited_time']
export function createPatchDTOFile(opts: {
dbPath: string
fileName: string
dbTypeName: string
propsConfig: ConfigFilePropertiesConfig
}) {
const imports = getDTOFileImports(opts.dbTypeName, opts.propsConfig)
const type = getDTOFileType(opts.dbTypeName, opts.propsConfig)
const code = getDTOFileCode(opts.propsConfig)
const content = `${imports}
type TypeFromRecord<Obj, Type> = Obj extends Record<string, infer T> ? Extract<T, Type> : never
export type ${opts.dbTypeName}PropertiesPatch = {
${type}}
export class ${opts.dbTypeName}PatchDTO {
__data: UpdatePageBodyParameters
constructor(opts: {
properties?: ${opts.dbTypeName}PropertiesPatch
coverUrl?: string
icon?: UpdatePageBodyParameters['icon']
archived?: UpdatePageBodyParameters['archived']
}) {
const { properties: props, coverUrl, icon, archived } = opts
this.__data = {}
this.__data.properties = {}
this.__data.cover = coverUrl ? { type: 'external', external: { url: coverUrl } } : undefined
this.__data.icon = icon
this.__data.archived = archived
${code} }
}
`
saveContentToFile(content, opts.dbPath, opts.fileName)
}
function getDTOFileImports(dbTypeName: string, propsConfig: ConfigFilePropertiesConfig) {
const imports = Object.values(propsConfig)
.map((prop) => getImportType(prop._type))
.filter((i) => i !== undefined)
const uniqueImports = Array.from(new Set(imports)).sort()
return (
`import { ${dbTypeName}Response } from "./types"
import { UpdatePageBodyParameters,\n` +
uniqueImports.join(',\n') +
`\n} from '../../core/types/notion-api.types'`
)
}
function getImportType(type: string) {
switch (type) {
case 'title':
case 'rich_text':
return 'RichTextItemRequest'
}
}
function getDTOFileType(dbTypeName: string, dbPropsConfig: ConfigFilePropertiesConfig) {
const content = Object.values(dbPropsConfig).reduce((acc, propConfig) => {
let typeValue
if (
PATCH_IGNORE_PROPS.includes(propConfig._type) ||
propConfig.readOnly ||
['button', 'rollup'].includes(propConfig._type)
) {
return acc
}
if (propConfig._type === 'multi_select') {
typeValue = `${dbTypeName}Response['properties']['${propConfig._name}']['multi_select'][number]['name'][]`
} else if (propConfig._type === 'select') {
typeValue = `${dbTypeName}Response['properties']['${propConfig._name}']['select']['name']`
} else if (['rich_text', 'title'].includes(propConfig._type)) {
typeValue = `string | { text: string; url?: string; annotations?: RichTextItemRequest['annotations'] } | RichTextItemRequest[]`
} else {
typeValue = `TypeFromRecord<UpdatePageBodyParameters['properties'], { type?: '${propConfig._type}' }>['${propConfig._type}']`
}
acc += `${TYPE_INDENT}${propConfig.varName}?: ${typeValue}\n`
return acc
}, '')
return content
}
function getDTOFileCode(dbPropsConfig: ConfigFilePropertiesConfig) {
const content = Object.entries(dbPropsConfig).reduce((acc, [propId, propConfig]) => {
let objValue
if (
PATCH_IGNORE_PROPS.includes(propConfig._type) ||
propConfig.readOnly ||
['button', 'rollup'].includes(propConfig._type)
) {
return acc
}
if (propConfig._type === 'multi_select') {
objValue = `
type: 'multi_select',
multi_select: props.${propConfig.varName}?.map((item) => ({ name: item })),`
} else if (propConfig._type === 'select') {
objValue = `
type: 'select',
select: { name: props.${propConfig.varName} },`
} else if (['rich_text', 'title'].includes(propConfig._type)) {
const propsVar = `props.${propConfig.varName}`
objValue = `
type: '${propConfig._type}',
${propConfig._type}: typeof ${propsVar} === 'string'
? [{ type: 'text', text: { content: ${propsVar} } }]
: Array.isArray(${propsVar})
? ${propsVar}
: ${propsVar} === null
? []
: [
{
type: 'text',
text: {
content: ${propsVar}.text,
link: ${propsVar}?.url ? { url: ${propsVar}.url } : undefined
},
annotations: ${propsVar}.annotations
},
]`
} else {
objValue = `
type: '${propConfig._type}',
${propConfig._type}: props.${propConfig.varName},`
}
acc += `
if (props?.${propConfig.varName} !== undefined) {
this.__data.properties['${propId}'] = {${objValue}
}
}
`
return acc
}, '')
return content
}