Skip to content
← Public packages

@kody/notion

Search, read, query, and safely write Notion pages and databases through the saved notion OAuth integration.

src/create-page.ts

49 lines · 1.6 KB · TypeScript
import { notionRequest, resolveDataSourceId, type JsonRecord } from './request.ts'
import { inputRecord, optionalArray, optionalRecord, requiredRecord } from './validation.ts'

type CreatePageResponse = {
  id?: string
  url?: string
  [key: string]: unknown
}

/**
 * Preview or create a Notion page under a parent page or data source.
 *
 * Database rows need a data source parent: pass
 * `parent: { data_source_id: '...' }`, or `parent: { database_id: '...' }` to
 * auto-resolve the database's single data source.
 */
export default async function createPage(params: Record<string, unknown>) {
  const input = inputRecord(params)

  const parent = { ...requiredRecord(input, 'parent') }
  if (typeof parent.database_id === 'string' && parent.data_source_id === undefined) {
    parent.data_source_id = await resolveDataSourceId(parent.database_id)
    delete parent.database_id
    if (parent.type === 'database_id') parent.type = 'data_source_id'
  }

  const payload: JsonRecord = {
    parent,
    properties: requiredRecord(input, 'properties'),
    children: optionalArray(input, 'children'),
    icon: optionalRecord(input, 'icon'),
    cover: optionalRecord(input, 'cover'),
  }

  if (input.dryRun === true) {
    return { dryRun: true, method: 'POST', path: '/pages', payload }
  }

  if (input.confirm !== true) {
    throw new Error('Creating a Notion page requires confirm: true after explicit user approval of the parent and content. Use dryRun: true to preview.')
  }

  const result = await notionRequest<CreatePageResponse>('/pages', { method: 'POST', body: payload })
  return {
    ok: true,
    id: result.id ?? null,
    url: result.url ?? null,
  }
}