Skip to content

Built for people who want to own their automations. Join the waitlist for an invite.

Package listing

@kentcdodds/notion

src/create-page.ts

56 lines · 1.8 KB · TypeScript
import { notionRequest, resolveDataSourceId, type JsonRecord } from './request.ts'
import { inputRecord, optionalArray, optionalRecord, optionalString, 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 account = optionalString(input, 'account')
  const integration = optionalString(input, 'integration')

  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, { account, integration })
    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,
    account,
    integration,
  })
  return {
    ok: true,
    id: result.id ?? null,
    url: result.url ?? null,
  }
}