@andrzejchm/notion-cli 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +66 -8
- package/dist/cli.js +821 -34
- package/dist/cli.js.map +1 -1
- package/docs/README.agents.md +77 -0
- package/docs/demo.gif +0 -0
- package/docs/demo.tape +26 -0
- package/docs/notion-cli-icon.png +0 -0
- package/docs/skills/using-notion-cli/SKILL.md +186 -0
- package/package.json +2 -2
- package/docs/agent-skill.md +0 -474
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/output/color.ts","../src/output/format.ts","../src/commands/init.ts","../src/errors/cli-error.ts","../src/errors/codes.ts","../src/config/config.ts","../src/config/paths.ts","../src/notion/client.ts","../src/output/stderr.ts","../src/errors/error-handler.ts","../src/commands/profile/list.ts","../src/commands/profile/use.ts","../src/commands/profile/remove.ts","../src/commands/completion.ts","../src/commands/search.ts","../src/config/local-config.ts","../src/config/token.ts","../src/commands/ls.ts","../src/commands/open.ts","../src/notion/url-parser.ts","../src/commands/users.ts","../src/output/paginate.ts","../src/commands/comments.ts","../src/commands/read.ts","../src/services/page.service.ts","../src/blocks/rich-text.ts","../src/blocks/converters.ts","../src/blocks/properties.ts","../src/blocks/render.ts","../src/output/markdown.ts","../src/commands/db/schema.ts","../src/services/database.service.ts","../src/commands/db/query.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { fileURLToPath } from 'node:url';\nimport { dirname, join } from 'node:path';\nimport { readFileSync } from 'node:fs';\nimport { setColorForced } from './output/color.js';\nimport { withErrorHandling } from './errors/error-handler.js';\nimport { setOutputMode } from './output/format.js';\nimport { initCommand } from './commands/init.js';\nimport { profileListCommand } from './commands/profile/list.js';\nimport { profileUseCommand } from './commands/profile/use.js';\nimport { profileRemoveCommand } from './commands/profile/remove.js';\nimport { completionCommand } from './commands/completion.js';\nimport { searchCommand } from './commands/search.js';\nimport { lsCommand } from './commands/ls.js';\nimport { openCommand } from './commands/open.js';\nimport { usersCommand } from './commands/users.js';\nimport { commentsCommand } from './commands/comments.js';\nimport { readCommand } from './commands/read.js';\nimport { dbSchemaCommand } from './commands/db/schema.js';\nimport { dbQueryCommand } from './commands/db/query.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// Read version from package.json\nconst pkg = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8')) as { version: string };\n\nconst program = new Command();\n\nprogram\n .name('notion')\n .description('Notion CLI — read Notion pages and databases from the terminal')\n .version(pkg.version);\n\nprogram\n .option('--verbose', 'show API requests/responses')\n .option('--color', 'force color output')\n .option('--json', 'force JSON output (overrides TTY detection)')\n .option('--md', 'force markdown output for page content');\n\nprogram.configureOutput({\n writeOut: (str) => process.stdout.write(str),\n writeErr: (str) => process.stderr.write(str),\n outputError: (str, write) => {\n write(str);\n },\n});\n\n// Apply global options before parsing subcommands\nprogram.hook('preAction', (thisCommand) => {\n const opts = thisCommand.opts<{ color?: boolean; verbose?: boolean; json?: boolean; md?: boolean }>();\n if (opts.color) {\n setColorForced(true);\n }\n if (opts.json) {\n setOutputMode('json');\n } else if (opts.md) {\n setOutputMode('md');\n }\n // else: 'auto' (default) — TTY detection in format.ts handles it\n});\n\n// --- Authentication ---\nprogram.addCommand(initCommand());\n\n// --- Profile Management ---\nconst profileCmd = new Command('profile')\n .description('manage authentication profiles');\n\nprofileCmd.addCommand(profileListCommand());\nprofileCmd.addCommand(profileUseCommand());\nprofileCmd.addCommand(profileRemoveCommand());\n\nprogram.addCommand(profileCmd);\n\n// --- Discovery ---\nprogram.addCommand(searchCommand());\nprogram.addCommand(lsCommand());\nprogram.addCommand(openCommand());\nprogram.addCommand(usersCommand());\nprogram.addCommand(commentsCommand());\nprogram.addCommand(readCommand());\n\n// --- Database ---\nconst dbCmd = new Command('db').description('Database operations');\ndbCmd.addCommand(dbSchemaCommand());\ndbCmd.addCommand(dbQueryCommand());\nprogram.addCommand(dbCmd);\n\n// --- Utilities ---\nprogram.addCommand(completionCommand());\n\nawait program.parseAsync();\n","import { Chalk } from 'chalk';\n\nlet _colorForced = false;\n\nexport function setColorForced(forced: boolean): void {\n _colorForced = forced;\n}\n\nfunction isColorEnabled(): boolean {\n if (process.env.NO_COLOR) return false;\n if (_colorForced) return true;\n return Boolean(process.stderr.isTTY);\n}\n\nexport function createChalk() {\n const level = isColorEnabled() ? undefined : 0;\n return new Chalk({ level });\n}\n\nexport function error(msg: string): string {\n return createChalk().red(msg);\n}\n\nexport function success(msg: string): string {\n return createChalk().green(msg);\n}\n\nexport function dim(msg: string): string {\n return createChalk().dim(msg);\n}\n\nexport function bold(msg: string): string {\n return createChalk().bold(msg);\n}\n","export type OutputMode = 'auto' | 'json' | 'md';\n\nlet _mode: OutputMode = 'auto';\n\nexport function setOutputMode(mode: OutputMode): void {\n _mode = mode;\n}\n\nexport function getOutputMode(): OutputMode {\n return _mode;\n}\n\nexport function isatty(): boolean {\n return Boolean(process.stdout.isTTY);\n}\n\n// Derived: should we show human-readable output?\nexport function isHumanMode(): boolean {\n if (_mode === 'json') return false;\n if (_mode === 'md') return false; // md mode: caller decides rendering\n return true; // 'auto': always human/table; use --json to get JSON\n}\n\nexport function formatJSON(data: unknown): string {\n return JSON.stringify(data, null, 2);\n}\n\n// Column width caps by header name\nconst COLUMN_CAPS: Record<string, number> = {\n TITLE: 50,\n ID: 36,\n};\n\n// Default max width for any column not explicitly capped — prevents long\n// free-text fields (Summary, Description, etc.) from blowing out the table\nconst DEFAULT_MAX_COL_WIDTH = 40;\n\nfunction getColumnCap(header: string): number {\n return COLUMN_CAPS[header.toUpperCase()] ?? DEFAULT_MAX_COL_WIDTH;\n}\n\nfunction truncate(str: string, maxLen: number): string {\n if (str.length <= maxLen) return str;\n return str.slice(0, maxLen - 1) + '…';\n}\n\nexport function formatTable(rows: string[][], headers: string[]): string {\n // Calculate column widths: max of header + all rows, capped per column\n const colWidths = headers.map((header, colIdx) => {\n const cap = getColumnCap(header);\n const headerLen = header.length;\n const maxRowLen = rows.reduce((max, row) => {\n const cell = row[colIdx] ?? '';\n return Math.max(max, cell.length);\n }, 0);\n return Math.min(Math.max(headerLen, maxRowLen), cap);\n });\n\n const sep = '─';\n const colSep = ' ';\n\n // Build header row\n const headerRow = headers\n .map((h, i) => h.padEnd(colWidths[i]))\n .join(colSep);\n\n // Build separator row\n const separatorRow = colWidths\n .map((w) => sep.repeat(w))\n .join(colSep);\n\n // Build data rows\n const dataRows = rows.map((row) =>\n headers\n .map((_, i) => {\n const cell = row[i] ?? '';\n return truncate(cell, colWidths[i]).padEnd(colWidths[i]);\n })\n .join(colSep)\n );\n\n return [headerRow, separatorRow, ...dataRows].join('\\n');\n}\n\nexport function printOutput(\n data: unknown,\n tableHeaders?: string[],\n tableRows?: string[][]\n): void {\n const mode = getOutputMode();\n\n if (mode === 'json') {\n process.stdout.write(formatJSON(data) + '\\n');\n } else if (isHumanMode() && tableHeaders && tableRows) {\n printWithPager(formatTable(tableRows, tableHeaders) + '\\n');\n }\n}\n\nfunction printWithPager(text: string): void {\n process.stdout.write(text);\n}\n","import { Command } from 'commander';\nimport { input, password, confirm } from '@inquirer/prompts';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\nimport { readGlobalConfig, writeGlobalConfig } from '../config/config.js';\nimport { validateToken, createNotionClient } from '../notion/client.js';\nimport { stderrWrite } from '../output/stderr.js';\nimport { success, bold, dim } from '../output/color.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\n\nexport function initCommand(): Command {\n const cmd = new Command('init');\n\n cmd\n .description('authenticate with Notion and save a profile')\n .action(withErrorHandling(async () => {\n // Non-TTY check\n if (!process.stdin.isTTY) {\n throw new CliError(\n ErrorCodes.AUTH_NO_TOKEN,\n 'Cannot run interactive init in non-TTY mode.',\n 'Set NOTION_API_TOKEN environment variable or create .notion.yaml',\n );\n }\n\n // Prompt for profile name\n const profileName = await input({\n message: 'Profile name:',\n default: 'default',\n });\n\n // Prompt for token\n const token = await password({\n message: 'Integration token (from notion.so/profile/integrations/internal):',\n mask: '*',\n });\n\n stderrWrite('Validating token...');\n\n // Validate token\n const { workspaceName, workspaceId } = await validateToken(token);\n\n stderrWrite(success(`✓ Connected to workspace: ${bold(workspaceName)}`));\n\n // Read existing config\n const config = await readGlobalConfig();\n\n // Check for existing profile\n if (config.profiles?.[profileName]) {\n const replace = await confirm({\n message: `Profile \"${profileName}\" already exists. Replace?`,\n default: false,\n });\n if (!replace) {\n stderrWrite('Aborted.');\n return;\n }\n }\n\n // Save profile\n const profiles = config.profiles ?? {};\n profiles[profileName] = {\n token,\n workspace_name: workspaceName,\n workspace_id: workspaceId,\n };\n\n await writeGlobalConfig({\n ...config,\n profiles,\n active_profile: profileName,\n });\n\n stderrWrite(success(`Profile \"${profileName}\" saved and set as active.`));\n\n // Check if the integration has access to any content\n stderrWrite(dim('Checking integration access...'));\n try {\n const notion = createNotionClient(token);\n const probe = await notion.search({ page_size: 1 });\n if (probe.results.length === 0) {\n stderrWrite('');\n stderrWrite('⚠️ Your integration has no pages connected.');\n stderrWrite(' To grant access, open any Notion page or database:');\n stderrWrite(' 1. Click ··· (three dots) in the top-right corner');\n stderrWrite(' 2. Select \"Connect to\"');\n stderrWrite(` 3. Choose \"${workspaceName}\"`);\n stderrWrite(' Then re-run any notion command to confirm access.');\n } else {\n stderrWrite(success(`✓ Integration has access to content in ${bold(workspaceName)}.`));\n }\n } catch {\n // Non-fatal — don't block init if the probe fails for any reason\n stderrWrite(dim('(Could not verify integration access — run `notion ls` to check)'));\n }\n }));\n\n return cmd;\n}\n","import type { ErrorCode } from './codes.js';\n\nexport class CliError extends Error {\n constructor(\n public readonly code: ErrorCode,\n message: string,\n public readonly suggestion?: string,\n ) {\n super(message);\n this.name = 'CliError';\n }\n\n format(): string {\n let output = `[${this.code}] ${this.message}`;\n if (this.suggestion) {\n output += `\\n → ${this.suggestion}`;\n }\n return output;\n }\n}\n","export const ErrorCodes = {\n // Auth errors\n AUTH_NO_TOKEN: 'AUTH_NO_TOKEN',\n AUTH_INVALID: 'AUTH_INVALID',\n AUTH_EXPIRED: 'AUTH_EXPIRED',\n AUTH_PROFILE_NOT_FOUND: 'AUTH_PROFILE_NOT_FOUND',\n // Config errors\n CONFIG_READ_ERROR: 'CONFIG_READ_ERROR',\n CONFIG_WRITE_ERROR: 'CONFIG_WRITE_ERROR',\n CONFIG_INVALID: 'CONFIG_INVALID',\n // Input errors\n INVALID_ID: 'INVALID_ID',\n INVALID_URL: 'INVALID_URL',\n INVALID_ARG: 'INVALID_ARG',\n // API errors\n API_ERROR: 'API_ERROR',\n API_RATE_LIMITED: 'API_RATE_LIMITED',\n API_NOT_FOUND: 'API_NOT_FOUND',\n // General\n UNKNOWN: 'UNKNOWN',\n} as const;\n\nexport type ErrorCode = typeof ErrorCodes[keyof typeof ErrorCodes];\n","import { mkdir, readFile, rename, writeFile } from 'node:fs/promises';\nimport { parse, stringify } from 'yaml';\nimport type { GlobalConfig } from '../types/config.js';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\nimport { getConfigDir, getConfigPath } from './paths.js';\n\n/**\n * Reads the global config file.\n * Returns {} when the file doesn't exist.\n * Throws CliError(CONFIG_READ_ERROR) on YAML parse failure or other read errors.\n */\nexport async function readGlobalConfig(): Promise<GlobalConfig> {\n const configPath = getConfigPath();\n let raw: string;\n try {\n raw = await readFile(configPath, 'utf-8');\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n return {};\n }\n throw new CliError(\n ErrorCodes.CONFIG_READ_ERROR,\n `Failed to read config file: ${configPath}`,\n 'Check file permissions or run \"notion init\" to create a new config',\n );\n }\n\n try {\n const parsed = parse(raw) as GlobalConfig;\n return parsed ?? {};\n } catch {\n throw new CliError(\n ErrorCodes.CONFIG_READ_ERROR,\n `Failed to parse config file: ${configPath}`,\n 'The config file may be corrupted. Delete it and run \"notion init\" to start fresh',\n );\n }\n}\n\n/**\n * Writes the global config file atomically.\n * Steps:\n * 1. Creates the config directory with 0o700 permissions\n * 2. Writes to a temp file (config.yaml.tmp) with 0o600 permissions\n * 3. Renames tmp to config.yaml (atomic)\n * Throws CliError(CONFIG_WRITE_ERROR) on failure.\n */\nexport async function writeGlobalConfig(config: GlobalConfig): Promise<void> {\n const configDir = getConfigDir();\n const configPath = getConfigPath();\n const tmpPath = `${configPath}.tmp`;\n\n try {\n await mkdir(configDir, { recursive: true, mode: 0o700 });\n } catch {\n throw new CliError(\n ErrorCodes.CONFIG_WRITE_ERROR,\n `Failed to create config directory: ${configDir}`,\n 'Check that you have write permissions to your home directory',\n );\n }\n\n const content = stringify(config);\n\n try {\n await writeFile(tmpPath, content, { mode: 0o600 });\n await rename(tmpPath, configPath);\n } catch {\n throw new CliError(\n ErrorCodes.CONFIG_WRITE_ERROR,\n `Failed to write config file: ${configPath}`,\n 'Check file permissions in the config directory',\n );\n }\n}\n","import { homedir } from 'node:os';\nimport { join } from 'node:path';\n\n/**\n * Returns the XDG-aware config directory for notion-cli.\n * Uses $XDG_CONFIG_HOME if set, otherwise falls back to ~/.config/notion-cli.\n */\nexport function getConfigDir(): string {\n const xdgConfigHome = process.env['XDG_CONFIG_HOME'];\n const base = xdgConfigHome ? xdgConfigHome : join(homedir(), '.config');\n return join(base, 'notion-cli');\n}\n\n/**\n * Returns the full path to the global config file.\n * Path: <configDir>/config.yaml\n */\nexport function getConfigPath(): string {\n return join(getConfigDir(), 'config.yaml');\n}\n","import { Client, APIErrorCode, isNotionClientError } from '@notionhq/client';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\n\nexport interface WorkspaceInfo {\n workspaceName: string;\n workspaceId: string;\n}\n\n/**\n * Validates a Notion integration token by calling users.me().\n * Returns workspace name and ID on success.\n * Throws CliError(AUTH_INVALID) on unauthorized error.\n */\nexport async function validateToken(token: string): Promise<WorkspaceInfo> {\n const notion = new Client({ auth: token });\n\n try {\n const me = await notion.users.me({});\n // Bot user response contains workspace_name and workspace_id\n const bot = me as unknown as {\n type: string;\n bot?: { workspace_name?: string; workspace_id?: string };\n };\n\n const workspaceName = bot.bot?.workspace_name ?? 'Unknown Workspace';\n const workspaceId = bot.bot?.workspace_id ?? '';\n\n return { workspaceName, workspaceId };\n } catch (error) {\n if (isNotionClientError(error) && error.code === APIErrorCode.Unauthorized) {\n throw new CliError(\n ErrorCodes.AUTH_INVALID,\n 'Invalid integration token.',\n 'Check your token at notion.so/profile/integrations/internal',\n );\n }\n throw error;\n }\n}\n\n/**\n * Creates an authenticated Notion client.\n * Used by all commands that need to interact with the Notion API.\n */\nexport function createNotionClient(token: string): Client {\n return new Client({ auth: token, timeoutMs: 120_000 });\n}\n","import type { CliError } from '../errors/cli-error.js';\nimport type { TokenResult } from '../types/config.js';\nimport { dim, error as colorError } from './color.js';\n\nexport function stderrWrite(msg: string): void {\n process.stderr.write(msg + '\\n');\n}\n\nexport function reportTokenSource(source: TokenResult['source']): void {\n stderrWrite(dim(`Using token from ${source}`));\n}\n\nexport function reportError(err: CliError): void {\n stderrWrite(colorError(err.format()));\n}\n","import { CliError } from './cli-error.js';\nimport { ErrorCodes } from './codes.js';\n\nfunction mapNotionErrorCode(code: string): string {\n switch (code) {\n case 'unauthorized':\n return ErrorCodes.AUTH_INVALID;\n case 'rate_limited':\n return ErrorCodes.API_RATE_LIMITED;\n case 'object_not_found':\n return ErrorCodes.API_NOT_FOUND;\n default:\n return ErrorCodes.API_ERROR;\n }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function withErrorHandling<T extends (...args: any[]) => Promise<void>>(fn: T): T {\n return (async (...args: Parameters<T>) => {\n try {\n await fn(...args);\n } catch (error) {\n if (error instanceof CliError) {\n process.stderr.write(error.format() + '\\n');\n process.exit(1);\n }\n\n // Lazy import to keep startup fast\n const { isNotionClientError } = await import('@notionhq/client');\n if (isNotionClientError(error)) {\n const code = mapNotionErrorCode(error.code);\n const mappedError = new CliError(\n code as CliError['code'],\n error.message,\n code === ErrorCodes.AUTH_INVALID\n ? 'Run \"notion init\" to reconfigure your integration token'\n : undefined,\n );\n process.stderr.write(mappedError.format() + '\\n');\n process.exit(1);\n }\n\n const message = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[${ErrorCodes.UNKNOWN}] ${message}\\n`);\n process.exit(1);\n }\n }) as T;\n}\n","import { Command } from 'commander';\nimport { readGlobalConfig } from '../../config/config.js';\nimport { bold, dim } from '../../output/color.js';\nimport { withErrorHandling } from '../../errors/error-handler.js';\n\nexport function profileListCommand(): Command {\n const cmd = new Command('list');\n\n cmd\n .description('list all authentication profiles')\n .action(withErrorHandling(async () => {\n const config = await readGlobalConfig();\n const profiles = config.profiles ?? {};\n const profileNames = Object.keys(profiles);\n\n if (profileNames.length === 0) {\n process.stdout.write('No profiles configured. Run `notion init` to get started.\\n');\n return;\n }\n\n for (const name of profileNames) {\n const profile = profiles[name];\n const isActive = config.active_profile === name;\n const marker = isActive ? bold('* ') : ' ';\n const activeLabel = isActive ? ' (active)' : '';\n const workspaceInfo = profile.workspace_name ? dim(` — ${profile.workspace_name}`) : '';\n\n process.stdout.write(`${marker}${name}${activeLabel}${workspaceInfo}\\n`);\n }\n }));\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { CliError } from '../../errors/cli-error.js';\nimport { ErrorCodes } from '../../errors/codes.js';\nimport { readGlobalConfig, writeGlobalConfig } from '../../config/config.js';\nimport { stderrWrite } from '../../output/stderr.js';\nimport { success } from '../../output/color.js';\nimport { withErrorHandling } from '../../errors/error-handler.js';\n\nexport function profileUseCommand(): Command {\n const cmd = new Command('use');\n\n cmd\n .description('switch the active profile')\n .argument('<name>', 'profile name to activate')\n .action(withErrorHandling(async (name: string) => {\n const config = await readGlobalConfig();\n const profiles = config.profiles ?? {};\n\n if (!profiles[name]) {\n throw new CliError(\n ErrorCodes.AUTH_PROFILE_NOT_FOUND,\n `Profile \"${name}\" not found.`,\n `Run \"notion profile list\" to see available profiles`,\n );\n }\n\n await writeGlobalConfig({\n ...config,\n active_profile: name,\n });\n\n stderrWrite(success(`Switched to profile \"${name}\".`));\n }));\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { CliError } from '../../errors/cli-error.js';\nimport { ErrorCodes } from '../../errors/codes.js';\nimport { readGlobalConfig, writeGlobalConfig } from '../../config/config.js';\nimport { stderrWrite } from '../../output/stderr.js';\nimport { success } from '../../output/color.js';\nimport { withErrorHandling } from '../../errors/error-handler.js';\n\nexport function profileRemoveCommand(): Command {\n const cmd = new Command('remove');\n\n cmd\n .description('remove an authentication profile')\n .argument('<name>', 'profile name to remove')\n .action(withErrorHandling(async (name: string) => {\n const config = await readGlobalConfig();\n const profiles = { ...(config.profiles ?? {}) };\n\n if (!profiles[name]) {\n throw new CliError(\n ErrorCodes.AUTH_PROFILE_NOT_FOUND,\n `Profile \"${name}\" not found.`,\n `Run \"notion profile list\" to see available profiles`,\n );\n }\n\n delete profiles[name];\n\n // Unset active_profile if it was the removed profile\n const newActiveProfile =\n config.active_profile === name ? undefined : config.active_profile;\n\n await writeGlobalConfig({\n ...config,\n profiles,\n active_profile: newActiveProfile,\n });\n\n stderrWrite(success(`Profile \"${name}\" removed.`));\n }));\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\n\nconst BASH_COMPLETION = `# notion bash completion\n_notion_completion() {\n local cur prev words cword\n _init_completion || return\n\n local commands=\"init profile completion --help --version --verbose --color\"\n local profile_commands=\"list use remove\"\n\n case \"$prev\" in\n notion)\n COMPREPLY=($(compgen -W \"$commands\" -- \"$cur\"))\n return 0\n ;;\n profile)\n COMPREPLY=($(compgen -W \"$profile_commands\" -- \"$cur\"))\n return 0\n ;;\n completion)\n COMPREPLY=($(compgen -W \"bash zsh fish\" -- \"$cur\"))\n return 0\n ;;\n esac\n\n COMPREPLY=($(compgen -W \"$commands\" -- \"$cur\"))\n}\n\ncomplete -F _notion_completion notion\n`;\n\nconst ZSH_COMPLETION = `#compdef notion\n# notion zsh completion\n\n_notion() {\n local -a commands\n\n commands=(\n 'init:authenticate with Notion and save a profile'\n 'profile:manage authentication profiles'\n 'completion:output shell completion script'\n )\n\n local -a global_opts\n global_opts=(\n '--help[display help]'\n '--version[output version]'\n '--verbose[show API requests/responses]'\n '--color[force color output]'\n )\n\n if (( CURRENT == 2 )); then\n _describe 'command' commands\n _arguments $global_opts\n return\n fi\n\n case $words[2] in\n profile)\n local -a profile_cmds\n profile_cmds=(\n 'list:list all authentication profiles'\n 'use:switch the active profile'\n 'remove:remove an authentication profile'\n )\n _describe 'profile command' profile_cmds\n ;;\n completion)\n local -a shells\n shells=('bash' 'zsh' 'fish')\n _describe 'shell' shells\n ;;\n esac\n}\n\n_notion \"$@\"\n`;\n\nconst FISH_COMPLETION = `# notion fish completion\n\n# Disable file completion by default\ncomplete -c notion -f\n\n# Global options\ncomplete -c notion -l help -d 'display help'\ncomplete -c notion -l version -d 'output version'\ncomplete -c notion -l verbose -d 'show API requests/responses'\ncomplete -c notion -l color -d 'force color output'\n\n# Top-level commands\ncomplete -c notion -n '__fish_use_subcommand' -a init -d 'authenticate with Notion and save a profile'\ncomplete -c notion -n '__fish_use_subcommand' -a profile -d 'manage authentication profiles'\ncomplete -c notion -n '__fish_use_subcommand' -a completion -d 'output shell completion script'\n\n# profile subcommands\ncomplete -c notion -n '__fish_seen_subcommand_from profile' -a list -d 'list all authentication profiles'\ncomplete -c notion -n '__fish_seen_subcommand_from profile' -a use -d 'switch the active profile'\ncomplete -c notion -n '__fish_seen_subcommand_from profile' -a remove -d 'remove an authentication profile'\n\n# completion shells\ncomplete -c notion -n '__fish_seen_subcommand_from completion' -a bash -d 'bash completion script'\ncomplete -c notion -n '__fish_seen_subcommand_from completion' -a zsh -d 'zsh completion script'\ncomplete -c notion -n '__fish_seen_subcommand_from completion' -a fish -d 'fish completion script'\n`;\n\nexport function completionCommand(): Command {\n const cmd = new Command('completion');\n\n cmd\n .description('output shell completion script')\n .argument('<shell>', 'shell type (bash, zsh, fish)')\n .action(withErrorHandling(async (shell: string) => {\n switch (shell) {\n case 'bash':\n process.stdout.write(BASH_COMPLETION);\n break;\n case 'zsh':\n process.stdout.write(ZSH_COMPLETION);\n break;\n case 'fish':\n process.stdout.write(FISH_COMPLETION);\n break;\n default:\n throw new CliError(\n ErrorCodes.UNKNOWN,\n `Unknown shell: \"${shell}\".`,\n 'Supported shells: bash, zsh, fish',\n );\n }\n }));\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { isFullPage, isFullPageOrDataSource } from '@notionhq/client';\nimport type { PageObjectResponse, DataSourceObjectResponse } from '@notionhq/client/build/src/api-endpoints.js';\nimport { resolveToken } from '../config/token.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { reportTokenSource } from '../output/stderr.js';\nimport { setOutputMode, printOutput } from '../output/format.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\n\nfunction getTitle(item: PageObjectResponse | DataSourceObjectResponse): string {\n if (item.object === 'data_source') {\n return item.title.map((t) => t.plain_text).join('') || '(untitled)';\n }\n const titleProp = Object.values(item.properties).find((p) => p.type === 'title');\n if (titleProp?.type === 'title') {\n return titleProp.title.map((t) => t.plain_text).join('') || '(untitled)';\n }\n return '(untitled)';\n}\n\n// Map user-facing type to SDK filter value\nfunction toSdkFilterValue(type: 'page' | 'database'): 'page' | 'data_source' {\n return type === 'database' ? 'data_source' : 'page';\n}\n\n// Display label for object type (data_source shown as \"database\" to users)\nfunction displayType(item: PageObjectResponse | DataSourceObjectResponse): string {\n return item.object === 'data_source' ? 'database' : item.object;\n}\n\nexport function searchCommand(): Command {\n const cmd = new Command('search');\n\n cmd\n .description('search Notion workspace by keyword')\n .argument('<query>', 'search keyword')\n .option('--type <type>', 'filter by object type (page or database)', (val) => {\n if (val !== 'page' && val !== 'database') {\n throw new Error('--type must be \"page\" or \"database\"');\n }\n return val as 'page' | 'database';\n })\n .option('--cursor <cursor>', 'start from this pagination cursor (from a previous --next hint)')\n .option('--json', 'force JSON output')\n .action(\n withErrorHandling(async (query: string, opts: { type?: 'page' | 'database'; cursor?: string; json?: boolean }) => {\n if (opts.json) {\n setOutputMode('json');\n }\n\n const { token, source } = await resolveToken();\n reportTokenSource(source);\n const notion = createNotionClient(token);\n\n const response = await notion.search({\n query,\n filter: opts.type\n ? { property: 'object', value: toSdkFilterValue(opts.type) }\n : undefined,\n start_cursor: opts.cursor,\n page_size: 20,\n });\n\n const fullResults = response.results.filter((r) => isFullPageOrDataSource(r)) as (\n | PageObjectResponse\n | DataSourceObjectResponse\n )[];\n\n if (fullResults.length === 0) {\n process.stdout.write(`No results found for \"${query}\"\\n`);\n return;\n }\n\n const headers = ['TYPE', 'TITLE', 'ID', 'MODIFIED'];\n const rows = fullResults.map((item) => [\n displayType(item),\n getTitle(item),\n item.id,\n item.last_edited_time.split('T')[0],\n ]);\n\n printOutput(fullResults, headers, rows);\n\n if (response.has_more && response.next_cursor) {\n process.stderr.write(`\\n --next: notion search \"${query}\" --cursor ${response.next_cursor}\\n`);\n }\n })\n );\n\n return cmd;\n}\n","import { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { parse } from 'yaml';\nimport type { LocalConfig } from '../types/config.js';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\n\n/**\n * Reads the local .notion.yaml file from the current working directory.\n * Returns null if the file doesn't exist.\n * Throws CliError(CONFIG_INVALID) if both `profile` and `token` are specified.\n */\nexport async function readLocalConfig(): Promise<LocalConfig | null> {\n const localConfigPath = join(process.cwd(), '.notion.yaml');\n let raw: string;\n\n try {\n raw = await readFile(localConfigPath, 'utf-8');\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n return null;\n }\n throw new CliError(\n ErrorCodes.CONFIG_READ_ERROR,\n `Failed to read local config: ${localConfigPath}`,\n 'Check file permissions',\n );\n }\n\n let parsed: LocalConfig;\n try {\n parsed = (parse(raw) as LocalConfig) ?? {};\n } catch {\n throw new CliError(\n ErrorCodes.CONFIG_INVALID,\n `Failed to parse .notion.yaml`,\n 'Check that the file contains valid YAML',\n );\n }\n\n if (parsed.profile !== undefined && parsed.token !== undefined) {\n throw new CliError(\n ErrorCodes.CONFIG_INVALID,\n '.notion.yaml cannot specify both \"profile\" and \"token\"',\n 'Use either \"profile: <name>\" to reference a saved profile, or \"token: <value>\" for a direct token',\n );\n }\n\n return parsed;\n}\n","import type { TokenResult } from '../types/config.js';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\nimport { readGlobalConfig } from './config.js';\nimport { readLocalConfig } from './local-config.js';\n\n/**\n * Resolves the Notion API token using a layered lookup chain:\n * 1. NOTION_API_TOKEN environment variable\n * 2. .notion.yaml token field (direct token)\n * 3. .notion.yaml profile field (look up that profile in global config)\n * 4. active_profile from global config\n *\n * Throws CliError(AUTH_NO_TOKEN) if no token is found anywhere.\n */\nexport async function resolveToken(): Promise<TokenResult> {\n // 1. Check env var first\n const envToken = process.env['NOTION_API_TOKEN'];\n if (envToken) {\n return { token: envToken, source: 'NOTION_API_TOKEN' };\n }\n\n // 2. Check .notion.yaml\n const localConfig = await readLocalConfig();\n\n if (localConfig !== null) {\n // 2a. Direct token in local config\n if (localConfig.token) {\n return { token: localConfig.token, source: '.notion.yaml' };\n }\n\n // 2b. Profile name in local config → look up in global config\n if (localConfig.profile) {\n const globalConfig = await readGlobalConfig();\n const profileToken = globalConfig.profiles?.[localConfig.profile]?.token;\n if (profileToken) {\n return { token: profileToken, source: `profile: ${localConfig.profile}` };\n }\n }\n }\n\n // 3. Fall back to active profile in global config\n const globalConfig = await readGlobalConfig();\n if (globalConfig.active_profile) {\n const profileToken = globalConfig.profiles?.[globalConfig.active_profile]?.token;\n if (profileToken) {\n return { token: profileToken, source: `profile: ${globalConfig.active_profile}` };\n }\n }\n\n // 4. Nothing found\n throw new CliError(\n ErrorCodes.AUTH_NO_TOKEN,\n 'No authentication token found.',\n 'Run \"notion init\" to set up a profile',\n );\n}\n","import { Command } from 'commander';\nimport { isFullPageOrDataSource } from '@notionhq/client';\nimport type { PageObjectResponse, DataSourceObjectResponse } from '@notionhq/client/build/src/api-endpoints.js';\nimport { resolveToken } from '../config/token.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { reportTokenSource } from '../output/stderr.js';\nimport { setOutputMode, printOutput } from '../output/format.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\n\nfunction getTitle(item: PageObjectResponse | DataSourceObjectResponse): string {\n if (item.object === 'data_source') {\n return item.title.map((t) => t.plain_text).join('') || '(untitled)';\n }\n const titleProp = Object.values(item.properties).find((p) => p.type === 'title');\n if (titleProp?.type === 'title') {\n return titleProp.title.map((t) => t.plain_text).join('') || '(untitled)';\n }\n return '(untitled)';\n}\n\n// Display label for object type (data_source shown as \"database\" to users)\nfunction displayType(item: PageObjectResponse | DataSourceObjectResponse): string {\n return item.object === 'data_source' ? 'database' : item.object;\n}\n\nexport function lsCommand(): Command {\n const cmd = new Command('ls');\n\n cmd\n .description('list accessible Notion pages and databases')\n .option('--type <type>', 'filter by object type (page or database)', (val) => {\n if (val !== 'page' && val !== 'database') {\n throw new Error('--type must be \"page\" or \"database\"');\n }\n return val as 'page' | 'database';\n })\n .option('--cursor <cursor>', 'start from this pagination cursor (from a previous --next hint)')\n .option('--json', 'force JSON output')\n .action(\n withErrorHandling(async (opts: { type?: 'page' | 'database'; cursor?: string; json?: boolean }) => {\n if (opts.json) {\n setOutputMode('json');\n }\n\n const { token, source } = await resolveToken();\n reportTokenSource(source);\n const notion = createNotionClient(token);\n\n const response = await notion.search({\n start_cursor: opts.cursor,\n page_size: 20,\n });\n\n let items = response.results.filter((r) => isFullPageOrDataSource(r)) as (\n | PageObjectResponse\n | DataSourceObjectResponse\n )[];\n\n if (opts.type) {\n const filterType = opts.type;\n items = items.filter((r) =>\n filterType === 'database' ? r.object === 'data_source' : r.object === filterType\n );\n }\n\n if (items.length === 0) {\n process.stdout.write('No accessible content found\\n');\n return;\n }\n\n const headers = ['TYPE', 'TITLE', 'ID', 'MODIFIED'];\n const rows = items.map((item) => [\n displayType(item),\n getTitle(item),\n item.id,\n item.last_edited_time.split('T')[0],\n ]);\n\n printOutput(items, headers, rows);\n\n if (response.has_more && response.next_cursor) {\n process.stderr.write(`\\n --next: notion ls --cursor ${response.next_cursor}\\n`);\n }\n })\n );\n\n return cmd;\n}\n","import { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { Command } from 'commander';\nimport { parseNotionId } from '../notion/url-parser.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\n\nconst execAsync = promisify(exec);\n\nexport function openCommand(): Command {\n const cmd = new Command('open');\n\n cmd\n .description('open a Notion page in the default browser')\n .argument('<id/url>', 'Notion page ID or URL')\n .action(withErrorHandling(async (idOrUrl: string) => {\n const id = parseNotionId(idOrUrl);\n const url = `https://www.notion.so/${id}`;\n\n const platform = process.platform;\n const opener =\n platform === 'darwin' ? 'open'\n : platform === 'win32' ? 'start'\n : 'xdg-open'; // Linux\n\n await execAsync(`${opener} \"${url}\"`);\n process.stdout.write(`Opening ${url}\\n`);\n }));\n\n return cmd;\n}\n","import { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\n\n/** Matches a raw 32-character hex ID (no dashes) */\nconst NOTION_ID_REGEX = /^[0-9a-f]{32}$/i;\n\n/** Matches a UUID with dashes (8-4-4-4-12) */\nconst UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n/**\n * Matches a 32-char hex ID embedded in a Notion URL path.\n * Handles notion.so and notion.site domains, with optional workspace, page title,\n * query parameters, and fragments.\n * Uses lazy matching to find the first 32-char hex ID in the path.\n */\nconst NOTION_URL_REGEX = /https?:\\/\\/(?:[a-zA-Z0-9-]+\\.)?notion\\.(?:so|site)\\/.*?([0-9a-f]{32})(?:[?#]|$)/i;\n\nfunction throwInvalidId(input: string): never {\n throw new CliError(\n ErrorCodes.INVALID_ID,\n `Cannot parse Notion ID from: ${input}`,\n 'Provide a valid Notion URL or page/database ID',\n );\n}\n\n/**\n * Parse any Notion URL or ID string into the normalized 32-char hex format.\n *\n * Accepts:\n * - Raw 32-char hex IDs (pass-through)\n * - UUIDs with dashes (strips dashes)\n * - notion.so and notion.site URLs with embedded 32-char hex IDs\n *\n * @throws {CliError} with code INVALID_ID if the input cannot be parsed\n */\nexport function parseNotionId(input: string): string {\n if (!input) throwInvalidId(input);\n\n // 1. Raw 32-char hex ID — pass through\n if (NOTION_ID_REGEX.test(input)) {\n return input.toLowerCase();\n }\n\n // 2. UUID with dashes — strip dashes\n if (UUID_REGEX.test(input)) {\n return input.replace(/-/g, '').toLowerCase();\n }\n\n // 3. Notion URL — extract embedded 32-char hex ID\n const urlMatch = NOTION_URL_REGEX.exec(input);\n if (urlMatch) {\n return urlMatch[1].toLowerCase();\n }\n\n throwInvalidId(input);\n}\n\n/**\n * Convert a 32-char hex Notion ID to standard UUID format (8-4-4-4-12 with dashes).\n */\nexport function toUuid(id: string): string {\n return `${id.slice(0, 8)}-${id.slice(8, 12)}-${id.slice(12, 16)}-${id.slice(16, 20)}-${id.slice(20)}`;\n}\n","import { Command } from 'commander';\nimport type { UserObjectResponse } from '@notionhq/client/build/src/api-endpoints.js';\nimport { resolveToken } from '../config/token.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { reportTokenSource } from '../output/stderr.js';\nimport { paginateResults } from '../output/paginate.js';\nimport { setOutputMode, printOutput } from '../output/format.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\n\nfunction getEmailOrWorkspace(user: UserObjectResponse): string {\n if (user.type === 'person') {\n return user.person.email ?? '—';\n }\n if (user.type === 'bot') {\n const bot = user.bot as { workspace_name?: string | null } | Record<string, never>;\n return ('workspace_name' in bot && bot.workspace_name) ? bot.workspace_name : '—';\n }\n return '—';\n}\n\nexport function usersCommand(): Command {\n const cmd = new Command('users');\n\n cmd\n .description('list all users in the workspace')\n .option('--json', 'output as JSON')\n .action(withErrorHandling(async (opts: { json?: boolean }) => {\n if (opts.json) setOutputMode('json');\n\n const { token, source } = await resolveToken();\n reportTokenSource(source);\n const notion = createNotionClient(token);\n\n const allUsers = await paginateResults((cursor) =>\n notion.users.list({ start_cursor: cursor }),\n );\n\n // Filter to full user objects (those with name field defined)\n const users = (allUsers as UserObjectResponse[]).filter((u) => u.name !== undefined);\n\n const rows = users.map((user) => [\n user.type,\n user.name ?? '(unnamed)',\n getEmailOrWorkspace(user),\n user.id,\n ]);\n\n printOutput(users, ['TYPE', 'NAME', 'EMAIL / WORKSPACE', 'ID'], rows);\n }));\n\n return cmd;\n}\n","export async function paginateResults<T>(\n fetcher: (cursor?: string) => Promise<{ results: T[]; next_cursor: string | null; has_more: boolean }>\n): Promise<T[]> {\n const allResults: T[] = [];\n let cursor: string | undefined;\n let hasMore = true;\n\n while (hasMore) {\n const response = await fetcher(cursor);\n allResults.push(...response.results);\n cursor = response.next_cursor ?? undefined;\n hasMore = response.has_more;\n }\n\n return allResults;\n}\n","import { Command } from 'commander';\nimport type { CommentObjectResponse } from '@notionhq/client/build/src/api-endpoints.js';\nimport { parseNotionId, toUuid } from '../notion/url-parser.js';\nimport { resolveToken } from '../config/token.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { reportTokenSource } from '../output/stderr.js';\nimport { paginateResults } from '../output/paginate.js';\nimport { setOutputMode, printOutput } from '../output/format.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\n\nexport function commentsCommand(): Command {\n const cmd = new Command('comments');\n\n cmd\n .description('list comments on a Notion page')\n .argument('<id/url>', 'Notion page ID or URL')\n .option('--json', 'output as JSON')\n .action(withErrorHandling(async (idOrUrl: string, opts: { json?: boolean }) => {\n if (opts.json) setOutputMode('json');\n\n const id = parseNotionId(idOrUrl);\n const uuid = toUuid(id);\n\n const { token, source } = await resolveToken();\n reportTokenSource(source);\n const notion = createNotionClient(token);\n\n const comments = await paginateResults((cursor) =>\n notion.comments.list({ block_id: uuid, start_cursor: cursor }),\n ) as CommentObjectResponse[];\n\n if (comments.length === 0) {\n process.stdout.write('No comments found on this page\\n');\n return;\n }\n\n const rows = comments.map((comment) => {\n const text = comment.rich_text.map((t) => t.plain_text).join('');\n return [\n comment.created_time.split('T')[0],\n comment.created_by.id.slice(0, 8) + '...',\n text.slice(0, 80) + (text.length > 80 ? '…' : ''),\n ];\n });\n\n printOutput(comments, ['DATE', 'AUTHOR ID', 'COMMENT'], rows);\n }));\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { withErrorHandling } from '../errors/error-handler.js';\nimport { resolveToken } from '../config/token.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { parseNotionId } from '../notion/url-parser.js';\nimport { fetchPageWithBlocks } from '../services/page.service.js';\nimport { renderPageMarkdown } from '../blocks/render.js';\nimport { renderMarkdown } from '../output/markdown.js';\nimport { isatty } from '../output/format.js';\n\n\nexport function readCommand(): Command {\n return new Command('read')\n .description('Read a Notion page as markdown')\n .argument('<id>', 'Notion page ID or URL')\n .option('--json', 'Output raw JSON instead of markdown')\n .option('--md', 'Output raw markdown (no terminal styling)')\n .action(\n withErrorHandling(async (id: string, options: { json?: boolean; md?: boolean }) => {\n const { token } = await resolveToken();\n const client = createNotionClient(token);\n const pageId = parseNotionId(id);\n const pageWithBlocks = await fetchPageWithBlocks(client, pageId);\n\n if (options.json) {\n process.stdout.write(JSON.stringify(pageWithBlocks, null, 2) + '\\n');\n } else {\n const markdown = renderPageMarkdown(pageWithBlocks);\n if (options.md || !isatty()) {\n // Raw markdown — piped output or explicit --md flag\n process.stdout.write(markdown);\n } else {\n // TTY: render with terminal styling, write directly to stdout\n process.stdout.write(renderMarkdown(markdown));\n }\n }\n }),\n );\n}\n","import { Client, collectPaginatedAPI, isFullBlock } from '@notionhq/client';\nimport type {\n BlockObjectResponse,\n PageObjectResponse,\n} from '@notionhq/client/build/src/api-endpoints.js';\n\nexport interface BlockNode {\n block: BlockObjectResponse;\n children: BlockNode[];\n}\n\nexport interface PageWithBlocks {\n page: PageObjectResponse;\n blocks: BlockNode[];\n}\n\nconst MAX_CONCURRENT_REQUESTS = 3;\n\nasync function fetchBlockTree(\n client: Client,\n blockId: string,\n depth: number,\n maxDepth: number,\n): Promise<BlockNode[]> {\n if (depth >= maxDepth) return [];\n\n const rawBlocks = await collectPaginatedAPI(client.blocks.children.list, {\n block_id: blockId,\n });\n\n const blocks = rawBlocks.filter(isFullBlock);\n\n // child_page and child_database are separate Notion pages — never recurse into them.\n // They render as headings/links; the user can `notion read <id>` them individually.\n const SKIP_RECURSE = new Set(['child_page', 'child_database']);\n\n const nodes: BlockNode[] = [];\n for (let i = 0; i < blocks.length; i += MAX_CONCURRENT_REQUESTS) {\n const batch = blocks.slice(i, i + MAX_CONCURRENT_REQUESTS);\n const batchNodes = await Promise.all(\n batch.map(async (block) => {\n const children = block.has_children && !SKIP_RECURSE.has(block.type)\n ? await fetchBlockTree(client, block.id, depth + 1, maxDepth)\n : [];\n return { block, children };\n }),\n );\n nodes.push(...batchNodes);\n }\n\n return nodes;\n}\n\nexport async function fetchPageWithBlocks(\n client: Client,\n pageId: string,\n): Promise<PageWithBlocks> {\n const page = (await client.pages.retrieve({ page_id: pageId })) as PageObjectResponse;\n const blocks = await fetchBlockTree(client, pageId, 0, 10);\n return { page, blocks };\n}\n","import type { RichTextItemResponse } from '@notionhq/client/build/src/api-endpoints.js';\n\nexport function richTextToMd(richText: RichTextItemResponse[]): string {\n return richText.map(segmentToMd).join('');\n}\n\nfunction segmentToMd(segment: RichTextItemResponse): string {\n if (segment.type === 'equation') {\n return `$${segment.equation.expression}$`;\n }\n\n if (segment.type === 'mention') {\n const text = segment.plain_text;\n return segment.href ? `[${text}](${segment.href})` : text;\n }\n\n // type === 'text'\n const annotated = applyAnnotations(segment.text.content, segment.annotations);\n return segment.text.link ? `[${annotated}](${segment.text.link.url})` : annotated;\n}\n\nfunction applyAnnotations(\n text: string,\n annotations: RichTextItemResponse['annotations']\n): string {\n let result = text;\n\n // Apply inner-to-outer: code → strikethrough → italic → bold\n if (annotations.code) result = `\\`${result}\\``;\n if (annotations.strikethrough) result = `~~${result}~~`;\n if (annotations.italic) result = `_${result}_`;\n if (annotations.bold) result = `**${result}**`;\n\n return result;\n}\n","import type { BlockObjectResponse } from '@notionhq/client/build/src/api-endpoints.js';\nimport { richTextToMd } from './rich-text.js';\n\nexport interface BlockConverterContext {\n listNumber?: number; // For numbered_list_item: the 1-based position in the list\n childrenMd?: string; // Pre-rendered children markdown (render.ts provides this)\n}\n\ntype BlockConverter = (block: BlockObjectResponse, ctx?: BlockConverterContext) => string;\n\nfunction indentChildren(childrenMd: string): string {\n return childrenMd\n .split('\\n')\n .filter(Boolean)\n .map(line => ' ' + line)\n .join('\\n') + '\\n';\n}\n\nconst converters: Record<string, BlockConverter> = {\n paragraph(block) {\n const b = block as Extract<BlockObjectResponse, { type: 'paragraph' }>;\n return `${richTextToMd(b.paragraph.rich_text)}\\n`;\n },\n\n heading_1(block) {\n const b = block as Extract<BlockObjectResponse, { type: 'heading_1' }>;\n return `# ${richTextToMd(b.heading_1.rich_text)}\\n`;\n },\n\n heading_2(block) {\n const b = block as Extract<BlockObjectResponse, { type: 'heading_2' }>;\n return `## ${richTextToMd(b.heading_2.rich_text)}\\n`;\n },\n\n heading_3(block) {\n const b = block as Extract<BlockObjectResponse, { type: 'heading_3' }>;\n return `### ${richTextToMd(b.heading_3.rich_text)}\\n`;\n },\n\n bulleted_list_item(block, ctx) {\n const b = block as Extract<BlockObjectResponse, { type: 'bulleted_list_item' }>;\n const text = richTextToMd(b.bulleted_list_item.rich_text);\n const header = `- ${text}\\n`;\n if (ctx?.childrenMd) {\n return header + indentChildren(ctx.childrenMd);\n }\n return header;\n },\n\n numbered_list_item(block, ctx) {\n const b = block as Extract<BlockObjectResponse, { type: 'numbered_list_item' }>;\n const num = ctx?.listNumber ?? 1;\n return `${num}. ${richTextToMd(b.numbered_list_item.rich_text)}\\n`;\n },\n\n to_do(block) {\n const b = block as Extract<BlockObjectResponse, { type: 'to_do' }>;\n const checkbox = b.to_do.checked ? '[x]' : '[ ]';\n return `- ${checkbox} ${richTextToMd(b.to_do.rich_text)}\\n`;\n },\n\n code(block) {\n const b = block as Extract<BlockObjectResponse, { type: 'code' }>;\n const lang = b.code.language === 'plain text' ? '' : b.code.language;\n const content = richTextToMd(b.code.rich_text);\n return `\\`\\`\\`${lang}\\n${content}\\n\\`\\`\\`\\n`;\n },\n\n quote(block) {\n const b = block as Extract<BlockObjectResponse, { type: 'quote' }>;\n return `> ${richTextToMd(b.quote.rich_text)}\\n`;\n },\n\n divider() {\n return '---\\n';\n },\n\n callout(block) {\n const b = block as Extract<BlockObjectResponse, { type: 'callout' }>;\n const text = richTextToMd(b.callout.rich_text);\n const icon = b.callout.icon;\n if (icon?.type === 'emoji') {\n return `> ${icon.emoji} ${text}\\n`;\n }\n return `> ${text}\\n`;\n },\n\n toggle(block, ctx) {\n const b = block as Extract<BlockObjectResponse, { type: 'toggle' }>;\n const header = `**${richTextToMd(b.toggle.rich_text)}**\\n`;\n if (ctx?.childrenMd) {\n return header + ctx.childrenMd;\n }\n return header;\n },\n\n image(block) {\n const b = block as Extract<BlockObjectResponse, { type: 'image' }>;\n const caption = richTextToMd(b.image.caption);\n if (b.image.type === 'file') {\n const url = b.image.file.url;\n const expiry = b.image.file.expiry_time;\n return ` <!-- expires: ${expiry} -->\\n`;\n }\n const url = b.image.external.url;\n return `\\n`;\n },\n\n bookmark(block) {\n const b = block as Extract<BlockObjectResponse, { type: 'bookmark' }>;\n const caption = richTextToMd(b.bookmark.caption);\n const text = caption || b.bookmark.url;\n return `[${text}](${b.bookmark.url})\\n`;\n },\n\n child_page(block) {\n const b = block as Extract<BlockObjectResponse, { type: 'child_page' }>;\n return `### ${b.child_page.title}\\n`;\n },\n\n child_database(block) {\n const b = block as Extract<BlockObjectResponse, { type: 'child_database' }>;\n return `### ${b.child_database.title}\\n`;\n },\n\n link_preview(block) {\n const b = block as Extract<BlockObjectResponse, { type: 'link_preview' }>;\n return `[${b.link_preview.url}](${b.link_preview.url})\\n`;\n },\n};\n\nexport function blockToMd(block: BlockObjectResponse, ctx?: BlockConverterContext): string {\n const converter = converters[block.type];\n if (converter) {\n return converter(block, ctx);\n }\n return `<!-- unsupported block: ${block.type} -->\\n`;\n}\n","import type { PageObjectResponse } from '@notionhq/client/build/src/api-endpoints.js';\n\ntype PropertyValue = PageObjectResponse['properties'][string];\n\nexport function formatPropertyValue(name: string, prop: PropertyValue): string {\n switch (prop.type) {\n case 'title':\n return prop.title.map((rt) => rt.plain_text).join('');\n\n case 'rich_text':\n return prop.rich_text.map((rt) => rt.plain_text).join('');\n\n case 'number':\n return prop.number !== null ? String(prop.number) : '';\n\n case 'select':\n return prop.select?.name ?? '';\n\n case 'status':\n return prop.status?.name ?? '';\n\n case 'multi_select':\n return prop.multi_select.map((s) => s.name).join(', ');\n\n case 'date':\n if (!prop.date) return '';\n return prop.date.end ? `${prop.date.start} → ${prop.date.end}` : prop.date.start;\n\n case 'checkbox':\n return prop.checkbox ? 'true' : 'false';\n\n case 'url':\n return prop.url ?? '';\n\n case 'email':\n return prop.email ?? '';\n\n case 'phone_number':\n return prop.phone_number ?? '';\n\n case 'people':\n return prop.people\n .map((p) => ('name' in p && p.name ? p.name : p.id))\n .join(', ');\n\n case 'relation':\n return prop.relation.map((r) => r.id).join(', ');\n\n case 'formula': {\n const f = prop.formula;\n if (f.type === 'string') return f.string ?? '';\n if (f.type === 'number') return f.number !== null ? String(f.number) : '';\n if (f.type === 'boolean') return String(f.boolean);\n if (f.type === 'date') return f.date?.start ?? '';\n return '';\n }\n\n case 'rollup': {\n const r = prop.rollup;\n if (r.type === 'number') return r.number !== null ? String(r.number) : '';\n if (r.type === 'date') return r.date?.start ?? '';\n if (r.type === 'array') return `[${r.array.length} items]`;\n return '';\n }\n\n case 'created_time':\n return prop.created_time;\n\n case 'last_edited_time':\n return prop.last_edited_time;\n\n case 'created_by':\n return 'name' in prop.created_by\n ? (prop.created_by.name ?? prop.created_by.id)\n : prop.created_by.id;\n\n case 'last_edited_by':\n return 'name' in prop.last_edited_by\n ? (prop.last_edited_by.name ?? prop.last_edited_by.id)\n : prop.last_edited_by.id;\n\n case 'files':\n return prop.files\n .map((f) => {\n if (f.type === 'external') return f.external.url;\n return f.name;\n })\n .join(', ');\n\n case 'unique_id':\n return prop.unique_id.prefix\n ? `${prop.unique_id.prefix}-${prop.unique_id.number}`\n : String(prop.unique_id.number ?? '');\n\n default:\n return '';\n }\n}\n\nexport function extractPageTitle(page: PageObjectResponse): string {\n const titleProp = Object.values(page.properties).find((p) => p.type === 'title');\n if (!titleProp || titleProp.type !== 'title') return page.id;\n return titleProp.title.map((rt) => rt.plain_text).join('') || page.id;\n}\n\n","import type { PageObjectResponse } from '@notionhq/client/build/src/api-endpoints.js';\nimport type { BlockNode, PageWithBlocks } from '../services/page.service.js';\nimport { blockToMd } from './converters.js';\nimport { formatPropertyValue } from './properties.js';\n\nfunction buildPropertiesHeader(page: PageObjectResponse): string {\n const lines: string[] = ['---'];\n for (const [name, prop] of Object.entries(page.properties)) {\n const value = formatPropertyValue(name, prop);\n if (value) {\n lines.push(`${name}: ${value}`);\n }\n }\n lines.push('---', '');\n return lines.join('\\n');\n}\n\nfunction renderBlockTree(blocks: BlockNode[]): string {\n const parts: string[] = [];\n let listCounter = 0; // tracks consecutive numbered_list_item\n\n for (const node of blocks) {\n // Track numbered list position\n if (node.block.type === 'numbered_list_item') {\n listCounter++;\n } else {\n listCounter = 0; // reset on any non-numbered block\n }\n\n // Recursively render children first\n const childrenMd = node.children.length > 0\n ? renderBlockTree(node.children)\n : '';\n\n const md = blockToMd(node.block, {\n listNumber: node.block.type === 'numbered_list_item' ? listCounter : undefined,\n childrenMd: childrenMd || undefined,\n });\n\n parts.push(md);\n }\n\n return parts.join('');\n}\n\nexport function renderPageMarkdown({ page, blocks }: PageWithBlocks): string {\n const header = buildPropertiesHeader(page);\n const content = renderBlockTree(blocks);\n return header + content;\n}\n","import { Chalk } from 'chalk';\nimport { isatty } from './format.js';\n\n// Use a Chalk instance that always produces color — we only call this when stdout is a TTY\nconst c = new Chalk({ level: 3 });\n\n/**\n * Render markdown text with terminal ANSI styling.\n * Only call when stdout is a TTY — returns raw markdown otherwise.\n */\nexport function renderMarkdown(md: string): string {\n if (!isatty()) return md;\n\n const lines = md.split('\\n');\n const out: string[] = [];\n let inFence = false;\n let fenceLang = '';\n let fenceLines: string[] = [];\n\n for (const line of lines) {\n // --- Fenced code blocks ---\n const fenceMatch = line.match(/^```(\\w*)$/);\n if (fenceMatch && !inFence) {\n inFence = true;\n fenceLang = fenceMatch[1] ?? '';\n fenceLines = [];\n continue;\n }\n if (line === '```' && inFence) {\n inFence = false;\n const header = fenceLang ? c.dim(`[${fenceLang}]`) : '';\n if (header) out.push(header);\n for (const fl of fenceLines) {\n out.push(c.green(' ' + fl));\n }\n out.push('');\n continue;\n }\n if (inFence) {\n fenceLines.push(line);\n continue;\n }\n\n // --- YAML frontmatter block (--- ... ---) ---\n if (line === '---') {\n out.push(c.dim('─'.repeat(40)));\n continue;\n }\n\n // --- HTML comments (unsupported blocks) — suppress ---\n if (/^<!--.*-->$/.test(line.trim())) {\n continue;\n }\n\n // --- Headings ---\n const h1 = line.match(/^# (.+)/);\n if (h1) { out.push('\\n' + c.bold.cyan(h1[1])); continue; }\n\n const h2 = line.match(/^## (.+)/);\n if (h2) { out.push('\\n' + c.bold.blue(h2[1])); continue; }\n\n const h3 = line.match(/^### (.+)/);\n if (h3) { out.push('\\n' + c.bold(h3[1])); continue; }\n\n const h4 = line.match(/^#### (.+)/);\n if (h4) { out.push(c.bold.underline(h4[1])); continue; }\n\n // --- Blockquotes / callouts ---\n if (line.startsWith('> ')) {\n out.push(c.yellow('▎ ') + renderInline(line.slice(2)));\n continue;\n }\n\n // --- Horizontal rule ---\n if (line === '---') {\n out.push(c.dim('─'.repeat(40)));\n continue;\n }\n\n // --- Frontmatter properties (key: value) ---\n const propMatch = line.match(/^([A-Za-z_][A-Za-z0-9_ ]*): (.+)$/);\n if (propMatch) {\n out.push(c.dim(propMatch[1] + ': ') + c.white(propMatch[2]));\n continue;\n }\n\n // --- Bullet list ---\n const bulletMatch = line.match(/^(\\s*)- (\\[[ x]\\] )?(.+)/);\n if (bulletMatch) {\n const indent = bulletMatch[1] ?? '';\n const checkbox = bulletMatch[2];\n const text = bulletMatch[3] ?? '';\n if (checkbox) {\n const checked = checkbox.trim() === '[x]';\n const box = checked ? c.green('☑') : c.dim('☐');\n out.push(indent + box + ' ' + renderInline(text));\n } else {\n out.push(indent + c.cyan('•') + ' ' + renderInline(text));\n }\n continue;\n }\n\n // --- Numbered list ---\n const numMatch = line.match(/^(\\s*)(\\d+)\\. (.+)/);\n if (numMatch) {\n const indent = numMatch[1] ?? '';\n const num = numMatch[2] ?? '';\n const text = numMatch[3] ?? '';\n out.push(indent + c.cyan(num + '.') + ' ' + renderInline(text));\n continue;\n }\n\n // --- Regular paragraph ---\n out.push(renderInline(line));\n }\n\n return out.join('\\n') + '\\n';\n}\n\n/** Apply inline markdown styles: bold, italic, code, strikethrough, links */\nfunction renderInline(text: string): string {\n // Use placeholders for inline code spans so other regexes don't touch their contents\n const codeSpans: string[] = [];\n let result = text.replace(/`([^`]+)`/g, (_, code) => {\n codeSpans.push(c.green(code));\n return `\\x00CODE${codeSpans.length - 1}\\x00`;\n });\n\n result = result\n // images (before links, since ![...] would match link pattern)\n .replace(/!\\[([^\\]]*)\\]\\([^)]+\\)/g, (_, alt) => alt ? c.dim(`[image: ${alt}]`) : c.dim('[image]'))\n // links [text](url)\n .replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (_, t, url) => c.cyan.underline(t) + c.dim(` (${url})`))\n // bold+italic\n .replace(/\\*\\*\\*(.+?)\\*\\*\\*/g, (_, t) => c.bold.italic(t))\n // bold\n .replace(/\\*\\*(.+?)\\*\\*/g, (_, t) => c.bold(t))\n // italic (both * and _)\n .replace(/(?<!\\*)\\*(?!\\*)(.+?)(?<!\\*)\\*(?!\\*)/g, (_, t) => c.italic(t))\n .replace(/(?<!_)_(?!_)(.+?)(?<!_)_(?!_)/g, (_, t) => c.italic(t))\n // strikethrough\n .replace(/~~(.+?)~~/g, (_, t) => c.strikethrough(t));\n\n // Restore code spans\n result = result.replace(/\\x00CODE(\\d+)\\x00/g, (_, i) => codeSpans[Number(i)] ?? '');\n\n return result;\n}\n","import { Command } from 'commander';\nimport { withErrorHandling } from '../../errors/error-handler.js';\nimport { resolveToken } from '../../config/token.js';\nimport { createNotionClient } from '../../notion/client.js';\nimport { parseNotionId } from '../../notion/url-parser.js';\nimport { fetchDatabaseSchema } from '../../services/database.service.js';\nimport { formatTable, formatJSON, isHumanMode } from '../../output/format.js';\n\nexport function dbSchemaCommand(): Command {\n return new Command('schema')\n .description('Show database schema (property names, types, and options)')\n .argument('<id>', 'Notion database ID or URL')\n .option('--json', 'Output raw JSON')\n .action(\n withErrorHandling(async (id: string, options: { json?: boolean }) => {\n const { token } = await resolveToken();\n const client = createNotionClient(token);\n const dbId = parseNotionId(id);\n const schema = await fetchDatabaseSchema(client, dbId);\n\n if (options.json) {\n process.stdout.write(formatJSON(schema) + '\\n');\n return;\n }\n\n // TTY: render as table — one row per property\n const headers = ['PROPERTY', 'TYPE', 'OPTIONS'];\n const rows = Object.values(schema.properties).map((prop) => [\n prop.name,\n prop.type,\n prop.options ? prop.options.map((o) => o.name).join(', ') : '',\n ]);\n process.stdout.write(formatTable(rows, headers) + '\\n');\n }),\n );\n}\n","import { Client, isFullPage } from '@notionhq/client';\nimport type {\n PageObjectResponse,\n QueryDataSourceParameters,\n} from '@notionhq/client/build/src/api-endpoints.js';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\nimport { paginateResults } from '../output/paginate.js';\n\nexport interface DatabaseSchema {\n id: string;\n title: string;\n // Property configs from schema — maps prop name to its type and options\n properties: Record<string, DatabasePropertyConfig>;\n}\n\nexport interface DatabasePropertyConfig {\n id: string;\n name: string;\n type: string; // 'select' | 'status' | 'number' | 'title' | 'rich_text' | 'date' | etc.\n // For select/status/multi_select: available options\n options?: Array<{ name: string; color?: string }>;\n}\n\nexport interface DatabaseEntry {\n id: string;\n // Property values — maps prop name to display string\n properties: Record<string, string>;\n // Raw page object for JSON output\n raw: PageObjectResponse;\n}\n\nexport interface DatabaseQueryOptions {\n filter?: QueryDataSourceParameters['filter'];\n sorts?: QueryDataSourceParameters['sorts'];\n // Subset of property names to include (undefined = all)\n columns?: string[];\n}\n\nexport async function fetchDatabaseSchema(\n client: Client,\n dbId: string,\n): Promise<DatabaseSchema> {\n // In Notion SDK v5, databases are exposed as \"data sources\"\n // client.dataSources.retrieve() returns DataSourceObjectResponse with .properties\n const ds = await client.dataSources.retrieve({ data_source_id: dbId });\n\n // Only full data sources have title and properties\n const title =\n 'title' in ds ? ds.title.map((rt) => rt.plain_text).join('') || dbId : dbId;\n\n const properties: Record<string, DatabasePropertyConfig> = {};\n\n if ('properties' in ds) {\n for (const [name, prop] of Object.entries(ds.properties)) {\n const config: DatabasePropertyConfig = {\n id: prop.id,\n name,\n type: prop.type,\n };\n // Extract options for enumerable types\n if (prop.type === 'select' && 'select' in prop) {\n config.options = prop.select.options;\n } else if (prop.type === 'status' && 'status' in prop) {\n config.options = prop.status.options;\n } else if (prop.type === 'multi_select' && 'multi_select' in prop) {\n config.options = prop.multi_select.options;\n }\n properties[name] = config;\n }\n }\n\n return { id: dbId, title, properties };\n}\n\nexport async function queryDatabase(\n client: Client,\n dbId: string,\n opts: DatabaseQueryOptions = {},\n): Promise<DatabaseEntry[]> {\n // In Notion SDK v5, querying a database uses client.dataSources.query()\n const rawPages = await paginateResults((cursor) =>\n client.dataSources.query({\n data_source_id: dbId,\n filter: opts.filter,\n sorts: opts.sorts,\n start_cursor: cursor,\n page_size: 100,\n }),\n );\n\n return rawPages.filter(isFullPage).map((page) => {\n const propValues: Record<string, string> = {};\n for (const [name, prop] of Object.entries(page.properties)) {\n // Skip columns not requested (if --columns specified)\n if (opts.columns && !opts.columns.includes(name)) continue;\n propValues[name] = displayPropertyValue(prop);\n }\n return { id: page.id, properties: propValues, raw: page };\n });\n}\n\nexport function buildFilter(\n filterStrings: string[],\n schema: DatabaseSchema,\n): QueryDataSourceParameters['filter'] | undefined {\n if (!filterStrings.length) return undefined;\n\n const filters = filterStrings.map((raw) => {\n const eqIdx = raw.indexOf('=');\n if (eqIdx === -1) {\n throw new CliError(\n ErrorCodes.INVALID_ARG,\n `Invalid filter syntax: \"${raw}\"`,\n 'Use format: --filter \"PropertyName=Value\"',\n );\n }\n const propName = raw.slice(0, eqIdx).trim();\n const value = raw.slice(eqIdx + 1).trim();\n const propConfig = schema.properties[propName];\n if (!propConfig) {\n const available = Object.keys(schema.properties).join(', ');\n throw new CliError(\n ErrorCodes.INVALID_ARG,\n `Property \"${propName}\" not found`,\n `Available properties: ${available}`,\n );\n }\n return buildPropertyFilter(propName, propConfig.type, value);\n });\n\n return filters.length === 1\n ? (filters[0] as QueryDataSourceParameters['filter'])\n : ({ and: filters } as QueryDataSourceParameters['filter']);\n}\n\nfunction buildPropertyFilter(\n property: string,\n type: string,\n value: string,\n): object {\n switch (type) {\n case 'select':\n return { property, select: { equals: value } };\n case 'status':\n return { property, status: { equals: value } };\n case 'multi_select':\n return { property, multi_select: { contains: value } };\n case 'checkbox':\n return { property, checkbox: { equals: value.toLowerCase() === 'true' } };\n case 'number':\n return { property, number: { equals: Number(value) } };\n case 'title':\n return { property, title: { contains: value } };\n case 'rich_text':\n return { property, rich_text: { contains: value } };\n case 'url':\n return { property, url: { contains: value } };\n case 'email':\n return { property, email: { contains: value } };\n default:\n throw new CliError(\n ErrorCodes.INVALID_ARG,\n `Filtering by property type \"${type}\" is not supported`,\n );\n }\n}\n\nexport function buildSorts(\n sortStrings: string[],\n): NonNullable<QueryDataSourceParameters['sorts']> {\n return sortStrings.map((raw) => {\n const colonIdx = raw.lastIndexOf(':');\n if (colonIdx === -1) {\n return { property: raw.trim(), direction: 'ascending' as const };\n }\n const property = raw.slice(0, colonIdx).trim();\n const dir = raw.slice(colonIdx + 1).trim().toLowerCase();\n return {\n property,\n direction:\n dir === 'desc' || dir === 'descending'\n ? ('descending' as const)\n : ('ascending' as const),\n };\n });\n}\n\nexport function displayPropertyValue(\n prop: PageObjectResponse['properties'][string],\n): string {\n switch (prop.type) {\n case 'title':\n return prop.title.map((r) => r.plain_text).join('').replace(/\\n/g, ' ');\n case 'rich_text':\n return prop.rich_text.map((r) => r.plain_text).join('').replace(/\\n/g, ' ');\n case 'number':\n return prop.number !== null && prop.number !== undefined\n ? String(prop.number)\n : '';\n case 'select':\n return prop.select?.name ?? '';\n case 'status':\n return prop.status?.name ?? '';\n case 'multi_select':\n return prop.multi_select.map((s) => s.name).join(', ');\n case 'date':\n return prop.date\n ? prop.date.end\n ? `${prop.date.start} → ${prop.date.end}`\n : prop.date.start\n : '';\n case 'checkbox':\n return prop.checkbox ? '✓' : '✗';\n case 'url':\n return prop.url ?? '';\n case 'email':\n return prop.email ?? '';\n case 'phone_number':\n return prop.phone_number ?? '';\n case 'people':\n return prop.people\n .map((p) => ('name' in p && p.name ? p.name : p.id))\n .join(', ');\n case 'relation':\n return prop.relation.length > 0 ? `[${prop.relation.length}]` : '';\n case 'formula': {\n const f = prop.formula;\n if (f.type === 'string') return f.string ?? '';\n if (f.type === 'number')\n return f.number !== null && f.number !== undefined\n ? String(f.number)\n : '';\n if (f.type === 'boolean') return f.boolean ? 'true' : 'false';\n if (f.type === 'date') return f.date?.start ?? '';\n return '';\n }\n case 'created_time':\n return prop.created_time;\n case 'last_edited_time':\n return prop.last_edited_time;\n case 'unique_id':\n return prop.unique_id.prefix\n ? `${prop.unique_id.prefix}-${prop.unique_id.number}`\n : String(prop.unique_id.number ?? '');\n default:\n return '';\n }\n}\n","import { Command } from 'commander';\nimport { withErrorHandling } from '../../errors/error-handler.js';\nimport { resolveToken } from '../../config/token.js';\nimport { createNotionClient } from '../../notion/client.js';\nimport { parseNotionId } from '../../notion/url-parser.js';\nimport {\n DatabaseSchema,\n fetchDatabaseSchema,\n queryDatabase,\n buildFilter,\n buildSorts,\n} from '../../services/database.service.js';\nimport { formatTable, formatJSON, isHumanMode } from '../../output/format.js';\n\n// Types that produce poor table output — skip in auto-column selection\nconst SKIP_TYPES_IN_AUTO = new Set(['relation', 'rich_text', 'people']);\n\n/**\n * Pick columns that fit within the terminal width.\n * - Skips relation/rich_text/people by default (noisy in tables)\n * - Stops adding columns once estimated width would exceed terminal width\n */\nfunction autoSelectColumns(schema: DatabaseSchema, entries: { properties: Record<string, string> }[]): string[] {\n const termWidth = process.stdout.columns || 120;\n const COL_SEP = 2; // two spaces between columns\n\n // Candidate columns: skip low-value types\n const candidates = Object.values(schema.properties)\n .filter((p) => !SKIP_TYPES_IN_AUTO.has(p.type))\n .map((p) => p.name);\n\n // Estimate each column's display width (max of header vs data)\n const widths = candidates.map((col) => {\n const header = col.toUpperCase().length;\n const maxData = entries.reduce((max, e) => Math.max(max, (e.properties[col] ?? '').length), 0);\n return Math.min(Math.max(header, maxData), 40); // respect DEFAULT_MAX_COL_WIDTH\n });\n\n // Greedily add columns until we'd exceed terminal width\n const selected: string[] = [];\n let usedWidth = 0;\n for (let i = 0; i < candidates.length; i++) {\n const needed = (selected.length > 0 ? COL_SEP : 0) + widths[i];\n if (usedWidth + needed > termWidth) break;\n selected.push(candidates[i]);\n usedWidth += needed;\n }\n\n // Always include at least the first column (title) even if it's wide\n if (selected.length === 0 && candidates.length > 0) {\n selected.push(candidates[0]);\n }\n\n return selected;\n}\n\nexport function dbQueryCommand(): Command {\n return new Command('query')\n .description('Query database entries with optional filtering and sorting')\n .argument('<id>', 'Notion database ID or URL')\n .option('--filter <filter>', 'Filter entries (repeatable): --filter \"Status=Done\"', collect, [])\n .option('--sort <sort>', 'Sort entries (repeatable): --sort \"Name:asc\"', collect, [])\n .option('--columns <columns>', 'Comma-separated list of columns to display: --columns \"Title,Status\"')\n .option('--json', 'Output raw JSON')\n .action(\n withErrorHandling(\n async (\n id: string,\n options: { filter: string[]; sort: string[]; columns?: string; json?: boolean },\n ) => {\n const { token } = await resolveToken();\n const client = createNotionClient(token);\n const dbId = parseNotionId(id);\n\n // Always fetch schema first (needed for filter building + column ordering)\n const schema = await fetchDatabaseSchema(client, dbId);\n\n const columns = options.columns\n ? options.columns.split(',').map((c) => c.trim())\n : undefined;\n\n const filter = options.filter.length\n ? buildFilter(options.filter, schema)\n : undefined;\n\n const sorts = options.sort.length ? buildSorts(options.sort) : undefined;\n\n const entries = await queryDatabase(client, dbId, { filter, sorts, columns });\n\n if (options.json) {\n process.stdout.write(formatJSON(entries.map((e) => e.raw)) + '\\n');\n return;\n }\n\n if (entries.length === 0) {\n process.stdout.write('No entries found.\\n');\n return;\n }\n\n // TTY: render as table\n // Use requested columns, or auto-select columns that fit the terminal\n const displayColumns = columns ?? autoSelectColumns(schema, entries);\n const headers = displayColumns.map((c) => c.toUpperCase());\n const rows = entries.map((entry) =>\n displayColumns.map((col) => entry.properties[col] ?? ''),\n );\n process.stdout.write(formatTable(rows, headers) + '\\n');\n process.stderr.write(`${entries.length} entries\\n`);\n },\n ),\n );\n}\n\n// Commander value collector helper for repeatable flags\nfunction collect(value: string, previous: string[]): string[] {\n return previous.concat([value]);\n}\n"],"mappings":"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","names":["Command","join","error","error","isNotionClientError","Command","Command","Command","Command","Command","Command","Command","Command","Command","readFile","join","parse","join","readFile","parse","globalConfig","Command","Command","isFullPageOrDataSource","getTitle","displayType","Command","isFullPageOrDataSource","Command","input","Command","Command","Command","Command","Command","Command","url","Chalk","Chalk","Command","Command","isFullPage","isFullPage","Command","Command","Command","c","join","Command"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/output/color.ts","../src/output/format.ts","../src/commands/init.ts","../src/errors/cli-error.ts","../src/errors/codes.ts","../src/config/config.ts","../src/config/paths.ts","../src/notion/client.ts","../src/output/stderr.ts","../src/errors/error-handler.ts","../src/commands/auth/login.ts","../src/oauth/oauth-client.ts","../src/oauth/oauth-flow.ts","../src/oauth/token-store.ts","../src/commands/auth/logout.ts","../src/commands/auth/status.ts","../src/commands/profile/list.ts","../src/commands/profile/use.ts","../src/commands/profile/remove.ts","../src/commands/completion.ts","../src/commands/search.ts","../src/config/local-config.ts","../src/config/token.ts","../src/commands/ls.ts","../src/commands/open.ts","../src/notion/url-parser.ts","../src/commands/users.ts","../src/output/paginate.ts","../src/commands/comments.ts","../src/commands/read.ts","../src/services/page.service.ts","../src/blocks/rich-text.ts","../src/blocks/converters.ts","../src/blocks/properties.ts","../src/blocks/render.ts","../src/output/markdown.ts","../src/commands/db/schema.ts","../src/services/database.service.ts","../src/commands/db/query.ts","../src/commands/comment-add.ts","../src/services/write.service.ts","../src/commands/append.ts","../src/blocks/md-to-blocks.ts","../src/commands/create-page.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { fileURLToPath } from 'node:url';\nimport { dirname, join } from 'node:path';\nimport { readFileSync } from 'node:fs';\nimport { setColorForced } from './output/color.js';\nimport { withErrorHandling } from './errors/error-handler.js';\nimport { setOutputMode } from './output/format.js';\nimport { initCommand } from './commands/init.js';\nimport { loginCommand } from './commands/auth/login.js';\nimport { logoutCommand } from './commands/auth/logout.js';\nimport { statusCommand } from './commands/auth/status.js';\nimport { profileListCommand } from './commands/profile/list.js';\nimport { profileUseCommand } from './commands/profile/use.js';\nimport { profileRemoveCommand } from './commands/profile/remove.js';\nimport { completionCommand } from './commands/completion.js';\nimport { searchCommand } from './commands/search.js';\nimport { lsCommand } from './commands/ls.js';\nimport { openCommand } from './commands/open.js';\nimport { usersCommand } from './commands/users.js';\nimport { commentsCommand } from './commands/comments.js';\nimport { readCommand } from './commands/read.js';\nimport { dbSchemaCommand } from './commands/db/schema.js';\nimport { dbQueryCommand } from './commands/db/query.js';\nimport { commentAddCommand } from './commands/comment-add.js';\nimport { appendCommand } from './commands/append.js';\nimport { createPageCommand } from './commands/create-page.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// Read version from package.json\nconst pkg = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8')) as { version: string };\n\nconst program = new Command();\n\nprogram\n .name('notion')\n .description('Notion CLI — read Notion pages and databases from the terminal')\n .version(pkg.version);\n\nprogram\n .option('--verbose', 'show API requests/responses')\n .option('--color', 'force color output')\n .option('--json', 'force JSON output (overrides TTY detection)')\n .option('--md', 'force markdown output for page content');\n\nprogram.configureOutput({\n writeOut: (str) => process.stdout.write(str),\n writeErr: (str) => process.stderr.write(str),\n outputError: (str, write) => {\n write(str);\n },\n});\n\n// Apply global options before parsing subcommands\nprogram.hook('preAction', (thisCommand) => {\n const opts = thisCommand.opts<{ color?: boolean; verbose?: boolean; json?: boolean; md?: boolean }>();\n if (opts.color) {\n setColorForced(true);\n }\n if (opts.json) {\n setOutputMode('json');\n } else if (opts.md) {\n setOutputMode('md');\n }\n // else: 'auto' (default) — TTY detection in format.ts handles it\n});\n\n// --- Authentication ---\nprogram.addCommand(initCommand());\n\n// auth subcommand group\nconst authCmd = new Command('auth').description('manage Notion authentication');\nauthCmd.addCommand(loginCommand());\nauthCmd.addCommand(logoutCommand());\nauthCmd.addCommand(statusCommand());\nprogram.addCommand(authCmd);\n\n// --- Profile Management ---\nconst profileCmd = new Command('profile')\n .description('manage authentication profiles');\n\nprofileCmd.addCommand(profileListCommand());\nprofileCmd.addCommand(profileUseCommand());\nprofileCmd.addCommand(profileRemoveCommand());\n\nprogram.addCommand(profileCmd);\n\n// --- Discovery ---\nprogram.addCommand(searchCommand());\nprogram.addCommand(lsCommand());\nprogram.addCommand(openCommand());\nprogram.addCommand(usersCommand());\nprogram.addCommand(commentsCommand());\nprogram.addCommand(readCommand());\nprogram.addCommand(commentAddCommand());\nprogram.addCommand(appendCommand());\nprogram.addCommand(createPageCommand());\n\n// --- Database ---\nconst dbCmd = new Command('db').description('Database operations');\ndbCmd.addCommand(dbSchemaCommand());\ndbCmd.addCommand(dbQueryCommand());\nprogram.addCommand(dbCmd);\n\n// --- Utilities ---\nprogram.addCommand(completionCommand());\n\nawait program.parseAsync();\n","import { Chalk } from 'chalk';\n\nlet _colorForced = false;\n\nexport function setColorForced(forced: boolean): void {\n _colorForced = forced;\n}\n\nfunction isColorEnabled(): boolean {\n if (process.env.NO_COLOR) return false;\n if (_colorForced) return true;\n return Boolean(process.stderr.isTTY);\n}\n\nexport function createChalk() {\n const level = isColorEnabled() ? undefined : 0;\n return new Chalk({ level });\n}\n\nexport function error(msg: string): string {\n return createChalk().red(msg);\n}\n\nexport function success(msg: string): string {\n return createChalk().green(msg);\n}\n\nexport function dim(msg: string): string {\n return createChalk().dim(msg);\n}\n\nexport function bold(msg: string): string {\n return createChalk().bold(msg);\n}\n","export type OutputMode = 'auto' | 'json' | 'md';\n\nlet _mode: OutputMode = 'auto';\n\nexport function setOutputMode(mode: OutputMode): void {\n _mode = mode;\n}\n\nexport function getOutputMode(): OutputMode {\n return _mode;\n}\n\nexport function isatty(): boolean {\n return Boolean(process.stdout.isTTY);\n}\n\n// Derived: should we show human-readable output?\nexport function isHumanMode(): boolean {\n if (_mode === 'json') return false;\n if (_mode === 'md') return false; // md mode: caller decides rendering\n return true; // 'auto': always human/table; use --json to get JSON\n}\n\nexport function formatJSON(data: unknown): string {\n return JSON.stringify(data, null, 2);\n}\n\n// Column width caps by header name\nconst COLUMN_CAPS: Record<string, number> = {\n TITLE: 50,\n ID: 36,\n};\n\n// Default max width for any column not explicitly capped — prevents long\n// free-text fields (Summary, Description, etc.) from blowing out the table\nconst DEFAULT_MAX_COL_WIDTH = 40;\n\nfunction getColumnCap(header: string): number {\n return COLUMN_CAPS[header.toUpperCase()] ?? DEFAULT_MAX_COL_WIDTH;\n}\n\nfunction truncate(str: string, maxLen: number): string {\n if (str.length <= maxLen) return str;\n return str.slice(0, maxLen - 1) + '…';\n}\n\nexport function formatTable(rows: string[][], headers: string[]): string {\n // Calculate column widths: max of header + all rows, capped per column\n const colWidths = headers.map((header, colIdx) => {\n const cap = getColumnCap(header);\n const headerLen = header.length;\n const maxRowLen = rows.reduce((max, row) => {\n const cell = row[colIdx] ?? '';\n return Math.max(max, cell.length);\n }, 0);\n return Math.min(Math.max(headerLen, maxRowLen), cap);\n });\n\n const sep = '─';\n const colSep = ' ';\n\n // Build header row\n const headerRow = headers\n .map((h, i) => h.padEnd(colWidths[i]))\n .join(colSep);\n\n // Build separator row\n const separatorRow = colWidths\n .map((w) => sep.repeat(w))\n .join(colSep);\n\n // Build data rows\n const dataRows = rows.map((row) =>\n headers\n .map((_, i) => {\n const cell = row[i] ?? '';\n return truncate(cell, colWidths[i]).padEnd(colWidths[i]);\n })\n .join(colSep)\n );\n\n return [headerRow, separatorRow, ...dataRows].join('\\n');\n}\n\nexport function printOutput(\n data: unknown,\n tableHeaders?: string[],\n tableRows?: string[][]\n): void {\n const mode = getOutputMode();\n\n if (mode === 'json') {\n process.stdout.write(formatJSON(data) + '\\n');\n } else if (isHumanMode() && tableHeaders && tableRows) {\n printWithPager(formatTable(tableRows, tableHeaders) + '\\n');\n }\n}\n\nfunction printWithPager(text: string): void {\n process.stdout.write(text);\n}\n","import { Command } from 'commander';\nimport { input, password, confirm } from '@inquirer/prompts';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\nimport { readGlobalConfig, writeGlobalConfig } from '../config/config.js';\nimport { validateToken, createNotionClient } from '../notion/client.js';\nimport { stderrWrite } from '../output/stderr.js';\nimport { success, bold, dim } from '../output/color.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\n\nexport function initCommand(): Command {\n const cmd = new Command('init');\n\n cmd\n .description('authenticate with Notion and save a profile')\n .action(withErrorHandling(async () => {\n // Non-TTY check\n if (!process.stdin.isTTY) {\n throw new CliError(\n ErrorCodes.AUTH_NO_TOKEN,\n 'Cannot run interactive init in non-TTY mode.',\n 'Set NOTION_API_TOKEN environment variable or create .notion.yaml',\n );\n }\n\n // Prompt for profile name\n const profileName = await input({\n message: 'Profile name:',\n default: 'default',\n });\n\n // Prompt for token\n const token = await password({\n message: 'Integration token (from notion.so/profile/integrations/internal):',\n mask: '*',\n });\n\n stderrWrite('Validating token...');\n\n // Validate token\n const { workspaceName, workspaceId } = await validateToken(token);\n\n stderrWrite(success(`✓ Connected to workspace: ${bold(workspaceName)}`));\n\n // Read existing config\n const config = await readGlobalConfig();\n\n // Check for existing profile\n if (config.profiles?.[profileName]) {\n const replace = await confirm({\n message: `Profile \"${profileName}\" already exists. Replace?`,\n default: false,\n });\n if (!replace) {\n stderrWrite('Aborted.');\n return;\n }\n }\n\n // Save profile\n const profiles = config.profiles ?? {};\n profiles[profileName] = {\n token,\n workspace_name: workspaceName,\n workspace_id: workspaceId,\n };\n\n await writeGlobalConfig({\n ...config,\n profiles,\n active_profile: profileName,\n });\n\n stderrWrite(success(`Profile \"${profileName}\" saved and set as active.`));\n\n // Check if the integration has access to any content\n stderrWrite(dim('Checking integration access...'));\n try {\n const notion = createNotionClient(token);\n const probe = await notion.search({ page_size: 1 });\n if (probe.results.length === 0) {\n stderrWrite('');\n stderrWrite('⚠️ Your integration has no pages connected.');\n stderrWrite(' To grant access, open any Notion page or database:');\n stderrWrite(' 1. Click ··· (three dots) in the top-right corner');\n stderrWrite(' 2. Select \"Connect to\"');\n stderrWrite(` 3. Choose \"${workspaceName}\"`);\n stderrWrite(' Then re-run any notion command to confirm access.');\n } else {\n stderrWrite(success(`✓ Integration has access to content in ${bold(workspaceName)}.`));\n }\n } catch {\n // Non-fatal — don't block init if the probe fails for any reason\n stderrWrite(dim('(Could not verify integration access — run `notion ls` to check)'));\n }\n\n stderrWrite('');\n stderrWrite(dim('Write commands (comment, append, create-page) require additional'));\n stderrWrite(dim('capabilities in your integration settings:'));\n stderrWrite(dim(' notion.so/profile/integrations/internal → your integration →'));\n stderrWrite(dim(' Capabilities: enable \"Read content\", \"Insert content\", \"Read comments\", \"Insert comments\"'));\n stderrWrite('');\n stderrWrite(dim('To post comments and create pages attributed to your user account:'));\n stderrWrite(dim(' notion auth login'));\n }));\n\n return cmd;\n}\n","import type { ErrorCode } from './codes.js';\n\nexport class CliError extends Error {\n constructor(\n public readonly code: ErrorCode,\n message: string,\n public readonly suggestion?: string,\n ) {\n super(message);\n this.name = 'CliError';\n }\n\n format(): string {\n let output = `[${this.code}] ${this.message}`;\n if (this.suggestion) {\n output += `\\n → ${this.suggestion}`;\n }\n return output;\n }\n}\n","export const ErrorCodes = {\n // Auth errors\n AUTH_NO_TOKEN: 'AUTH_NO_TOKEN',\n AUTH_INVALID: 'AUTH_INVALID',\n AUTH_EXPIRED: 'AUTH_EXPIRED',\n AUTH_PROFILE_NOT_FOUND: 'AUTH_PROFILE_NOT_FOUND',\n // Config errors\n CONFIG_READ_ERROR: 'CONFIG_READ_ERROR',\n CONFIG_WRITE_ERROR: 'CONFIG_WRITE_ERROR',\n CONFIG_INVALID: 'CONFIG_INVALID',\n // Input errors\n INVALID_ID: 'INVALID_ID',\n INVALID_URL: 'INVALID_URL',\n INVALID_ARG: 'INVALID_ARG',\n // API errors\n API_ERROR: 'API_ERROR',\n API_RATE_LIMITED: 'API_RATE_LIMITED',\n API_NOT_FOUND: 'API_NOT_FOUND',\n // General\n UNKNOWN: 'UNKNOWN',\n} as const;\n\nexport type ErrorCode = typeof ErrorCodes[keyof typeof ErrorCodes];\n","import { mkdir, readFile, rename, writeFile } from 'node:fs/promises';\nimport { parse, stringify } from 'yaml';\nimport type { GlobalConfig } from '../types/config.js';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\nimport { getConfigDir, getConfigPath } from './paths.js';\n\n/**\n * Reads the global config file.\n * Returns {} when the file doesn't exist.\n * Throws CliError(CONFIG_READ_ERROR) on YAML parse failure or other read errors.\n */\nexport async function readGlobalConfig(): Promise<GlobalConfig> {\n const configPath = getConfigPath();\n let raw: string;\n try {\n raw = await readFile(configPath, 'utf-8');\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n return {};\n }\n throw new CliError(\n ErrorCodes.CONFIG_READ_ERROR,\n `Failed to read config file: ${configPath}`,\n 'Check file permissions or run \"notion init\" to create a new config',\n );\n }\n\n try {\n const parsed = parse(raw) as GlobalConfig;\n return parsed ?? {};\n } catch {\n throw new CliError(\n ErrorCodes.CONFIG_READ_ERROR,\n `Failed to parse config file: ${configPath}`,\n 'The config file may be corrupted. Delete it and run \"notion init\" to start fresh',\n );\n }\n}\n\n/**\n * Writes the global config file atomically.\n * Steps:\n * 1. Creates the config directory with 0o700 permissions\n * 2. Writes to a temp file (config.yaml.tmp) with 0o600 permissions\n * 3. Renames tmp to config.yaml (atomic)\n * Throws CliError(CONFIG_WRITE_ERROR) on failure.\n */\nexport async function writeGlobalConfig(config: GlobalConfig): Promise<void> {\n const configDir = getConfigDir();\n const configPath = getConfigPath();\n const tmpPath = `${configPath}.tmp`;\n\n try {\n await mkdir(configDir, { recursive: true, mode: 0o700 });\n } catch {\n throw new CliError(\n ErrorCodes.CONFIG_WRITE_ERROR,\n `Failed to create config directory: ${configDir}`,\n 'Check that you have write permissions to your home directory',\n );\n }\n\n const content = stringify(config);\n\n try {\n await writeFile(tmpPath, content, { mode: 0o600 });\n await rename(tmpPath, configPath);\n } catch {\n throw new CliError(\n ErrorCodes.CONFIG_WRITE_ERROR,\n `Failed to write config file: ${configPath}`,\n 'Check file permissions in the config directory',\n );\n }\n}\n","import { homedir } from 'node:os';\nimport { join } from 'node:path';\n\n/**\n * Returns the XDG-aware config directory for notion-cli.\n * Uses $XDG_CONFIG_HOME if set, otherwise falls back to ~/.config/notion-cli.\n */\nexport function getConfigDir(): string {\n const xdgConfigHome = process.env['XDG_CONFIG_HOME'];\n const base = xdgConfigHome ? xdgConfigHome : join(homedir(), '.config');\n return join(base, 'notion-cli');\n}\n\n/**\n * Returns the full path to the global config file.\n * Path: <configDir>/config.yaml\n */\nexport function getConfigPath(): string {\n return join(getConfigDir(), 'config.yaml');\n}\n","import { Client, APIErrorCode, isNotionClientError } from '@notionhq/client';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\n\nexport interface WorkspaceInfo {\n workspaceName: string;\n workspaceId: string;\n}\n\n/**\n * Validates a Notion integration token by calling users.me().\n * Returns workspace name and ID on success.\n * Throws CliError(AUTH_INVALID) on unauthorized error.\n */\nexport async function validateToken(token: string): Promise<WorkspaceInfo> {\n const notion = new Client({ auth: token });\n\n try {\n const me = await notion.users.me({});\n // Bot user response contains workspace_name and workspace_id\n const bot = me as unknown as {\n type: string;\n bot?: { workspace_name?: string; workspace_id?: string };\n };\n\n const workspaceName = bot.bot?.workspace_name ?? 'Unknown Workspace';\n const workspaceId = bot.bot?.workspace_id ?? '';\n\n return { workspaceName, workspaceId };\n } catch (error) {\n if (isNotionClientError(error) && error.code === APIErrorCode.Unauthorized) {\n throw new CliError(\n ErrorCodes.AUTH_INVALID,\n 'Invalid integration token.',\n 'Check your token at notion.so/profile/integrations/internal',\n );\n }\n throw error;\n }\n}\n\n/**\n * Creates an authenticated Notion client.\n * Used by all commands that need to interact with the Notion API.\n */\nexport function createNotionClient(token: string): Client {\n return new Client({ auth: token, timeoutMs: 120_000 });\n}\n","import type { CliError } from '../errors/cli-error.js';\nimport type { TokenResult } from '../types/config.js';\nimport { dim, error as colorError } from './color.js';\n\nexport function stderrWrite(msg: string): void {\n process.stderr.write(msg + '\\n');\n}\n\nexport function reportTokenSource(source: TokenResult['source']): void {\n stderrWrite(dim(`Using token from ${source}`));\n}\n\nexport function reportError(err: CliError): void {\n stderrWrite(colorError(err.format()));\n}\n","import { CliError } from './cli-error.js';\nimport { ErrorCodes } from './codes.js';\n\nfunction mapNotionErrorCode(code: string): string {\n switch (code) {\n case 'unauthorized':\n return ErrorCodes.AUTH_INVALID;\n case 'rate_limited':\n return ErrorCodes.API_RATE_LIMITED;\n case 'object_not_found':\n return ErrorCodes.API_NOT_FOUND;\n default:\n return ErrorCodes.API_ERROR;\n }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function withErrorHandling<T extends (...args: any[]) => Promise<void>>(fn: T): T {\n return (async (...args: Parameters<T>) => {\n try {\n await fn(...args);\n } catch (error) {\n if (error instanceof CliError) {\n process.stderr.write(error.format() + '\\n');\n process.exit(1);\n }\n\n // Lazy import to keep startup fast\n const { isNotionClientError } = await import('@notionhq/client');\n if (isNotionClientError(error)) {\n const code = mapNotionErrorCode(error.code);\n const mappedError = new CliError(\n code as CliError['code'],\n error.message,\n code === ErrorCodes.AUTH_INVALID\n ? 'Run \"notion init\" to reconfigure your integration token'\n : undefined,\n );\n process.stderr.write(mappedError.format() + '\\n');\n process.exit(1);\n }\n\n const message = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[${ErrorCodes.UNKNOWN}] ${message}\\n`);\n process.exit(1);\n }\n }) as T;\n}\n","import { Command } from 'commander';\nimport { CliError } from '../../errors/cli-error.js';\nimport { ErrorCodes } from '../../errors/codes.js';\nimport { withErrorHandling } from '../../errors/error-handler.js';\nimport { readGlobalConfig } from '../../config/config.js';\nimport { exchangeCode } from '../../oauth/oauth-client.js';\nimport { runOAuthFlow } from '../../oauth/oauth-flow.js';\nimport { saveOAuthTokens } from '../../oauth/token-store.js';\nimport { stderrWrite } from '../../output/stderr.js';\nimport { success, dim } from '../../output/color.js';\n\ninterface LoginOptions {\n profile?: string;\n manual?: boolean;\n}\n\nexport function loginCommand(): Command {\n const cmd = new Command('login');\n\n cmd\n .description('authenticate with Notion via OAuth browser flow')\n .option('--profile <name>', 'profile name to store credentials in')\n .option('--manual', 'print auth URL instead of opening browser (for headless environments)')\n .action(\n withErrorHandling(async (opts: LoginOptions) => {\n // TTY check for interactive OAuth (unless manual mode)\n if (!process.stdin.isTTY && !opts.manual) {\n throw new CliError(\n ErrorCodes.AUTH_NO_TOKEN,\n 'Cannot run interactive OAuth login in non-TTY mode.',\n 'Use --manual flag to get an auth URL you can open in a browser',\n );\n }\n\n // Resolve profile name\n let profileName = opts.profile;\n if (!profileName) {\n const config = await readGlobalConfig();\n profileName = config.active_profile ?? 'default';\n }\n\n // Run the OAuth browser flow\n const result = await runOAuthFlow({ manual: opts.manual });\n\n // Exchange the authorization code for tokens\n const response = await exchangeCode(result.code);\n\n // Persist tokens\n await saveOAuthTokens(profileName, response);\n\n // Display success\n const userName = response.owner?.user?.name ?? 'unknown user';\n const workspaceName = response.workspace_name ?? 'unknown workspace';\n\n stderrWrite(success(`✓ Logged in as ${userName} to workspace ${workspaceName}`));\n stderrWrite(dim('Your comments and pages will now be attributed to your Notion account.'));\n }),\n );\n\n return cmd;\n}\n","import { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\n\n// OAuth credentials are injected at build time via tsup `define` from env vars:\n// NOTION_OAUTH_CLIENT_ID and NOTION_OAUTH_CLIENT_SECRET\n// They are never stored in source control. Locally, set them in .env before building.\n// In GitHub Actions, they are stored as repository secrets.\ndeclare const __OAUTH_CLIENT_ID__: string;\ndeclare const __OAUTH_CLIENT_SECRET__: string;\n\nconst OAUTH_CLIENT_ID: string = __OAUTH_CLIENT_ID__;\nconst OAUTH_CLIENT_SECRET: string = __OAUTH_CLIENT_SECRET__;\n\nexport const OAUTH_REDIRECT_URI = 'http://localhost:54321/oauth/callback';\n\nexport interface OAuthTokenResponse {\n access_token: string;\n refresh_token: string;\n bot_id: string;\n workspace_id: string;\n workspace_name: string;\n owner?: {\n type: string;\n user?: { id: string; name?: string };\n };\n}\n\n/**\n * Returns the Notion OAuth authorization URL.\n * state: random hex string to prevent CSRF.\n */\nexport function buildAuthUrl(state: string): string {\n const params = new URLSearchParams({\n client_id: OAUTH_CLIENT_ID,\n redirect_uri: OAUTH_REDIRECT_URI,\n response_type: 'code',\n owner: 'user',\n state,\n });\n return `https://api.notion.com/v1/oauth/authorize?${params.toString()}`;\n}\n\nfunction basicAuth(): string {\n return Buffer.from(`${OAUTH_CLIENT_ID}:${OAUTH_CLIENT_SECRET}`).toString('base64');\n}\n\n/**\n * Exchanges an authorization code for access_token + refresh_token.\n * Throws CliError(AUTH_INVALID) on failure.\n */\nexport async function exchangeCode(\n code: string,\n redirectUri: string = OAUTH_REDIRECT_URI,\n): Promise<OAuthTokenResponse> {\n const response = await fetch('https://api.notion.com/v1/oauth/token', {\n method: 'POST',\n headers: {\n 'Authorization': `Basic ${basicAuth()}`,\n 'Content-Type': 'application/json',\n 'Notion-Version': '2022-06-28',\n },\n body: JSON.stringify({\n grant_type: 'authorization_code',\n code,\n redirect_uri: redirectUri,\n }),\n });\n\n if (!response.ok) {\n let errorMessage = `OAuth token exchange failed (HTTP ${response.status})`;\n try {\n const body = (await response.json()) as { error?: string; error_description?: string };\n if (body.error_description) errorMessage = body.error_description;\n else if (body.error) errorMessage = body.error;\n } catch {\n // Ignore JSON parse errors — use generic message\n }\n throw new CliError(\n ErrorCodes.AUTH_INVALID,\n errorMessage,\n 'Run \"notion auth login\" to restart the OAuth flow',\n );\n }\n\n const data = (await response.json()) as OAuthTokenResponse;\n return data;\n}\n\n/**\n * Refreshes an expired access_token using the stored refresh_token.\n * Returns new OAuthTokenResponse on success.\n * Throws CliError(AUTH_INVALID) if refresh fails (token revoked).\n */\nexport async function refreshAccessToken(refreshToken: string): Promise<OAuthTokenResponse> {\n const response = await fetch('https://api.notion.com/v1/oauth/token', {\n method: 'POST',\n headers: {\n 'Authorization': `Basic ${basicAuth()}`,\n 'Content-Type': 'application/json',\n 'Notion-Version': '2022-06-28',\n },\n body: JSON.stringify({\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n }),\n });\n\n if (!response.ok) {\n let errorMessage = `OAuth token refresh failed (HTTP ${response.status})`;\n try {\n const body = (await response.json()) as { error?: string; error_description?: string };\n if (body.error_description) errorMessage = body.error_description;\n else if (body.error) errorMessage = body.error;\n } catch {\n // Ignore JSON parse errors — use generic message\n }\n throw new CliError(\n ErrorCodes.AUTH_INVALID,\n errorMessage,\n 'Run \"notion auth login\" to re-authenticate',\n );\n }\n\n const data = (await response.json()) as OAuthTokenResponse;\n return data;\n}\n","import { createServer } from 'node:http';\nimport { randomBytes } from 'node:crypto';\nimport { spawn } from 'node:child_process';\nimport { createInterface } from 'node:readline';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\nimport { buildAuthUrl, OAUTH_REDIRECT_URI } from './oauth-client.js';\n\nexport interface OAuthFlowResult {\n code: string;\n state: string;\n}\n\n/**\n * Opens the URL in the user's default browser using a platform-aware command.\n * Returns false if spawning the browser failed (triggers manual flow fallback).\n */\nfunction openBrowser(url: string): boolean {\n const platform = process.platform;\n let cmd: string;\n let args: string[];\n\n if (platform === 'darwin') {\n cmd = 'open';\n args = [url];\n } else if (platform === 'win32') {\n cmd = 'cmd';\n args = ['/c', 'start', url];\n } else {\n cmd = 'xdg-open';\n args = [url];\n }\n\n try {\n const child = spawn(cmd, args, {\n detached: true,\n stdio: 'ignore',\n });\n child.unref();\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Prompts the user to paste the full redirect URL in manual mode.\n * Parses the code and state from the pasted URL.\n */\nasync function manualFlow(url: string): Promise<OAuthFlowResult> {\n process.stderr.write(\n `\\nOpening browser to:\\n ${url}\\n\\nPaste the full redirect URL here (${OAUTH_REDIRECT_URI}?code=...):\\n> `,\n );\n\n const rl = createInterface({\n input: process.stdin,\n output: process.stderr,\n terminal: false,\n });\n\n return new Promise<OAuthFlowResult>((resolve, reject) => {\n rl.once('line', (line) => {\n rl.close();\n try {\n const parsed = new URL(line.trim());\n const code = parsed.searchParams.get('code');\n const state = parsed.searchParams.get('state');\n const errorParam = parsed.searchParams.get('error');\n\n if (errorParam === 'access_denied') {\n reject(\n new CliError(\n ErrorCodes.AUTH_INVALID,\n 'Notion OAuth access was denied.',\n 'Run \"notion auth login\" to try again',\n ),\n );\n return;\n }\n\n if (!code || !state) {\n reject(\n new CliError(\n ErrorCodes.AUTH_INVALID,\n 'Invalid redirect URL — missing code or state parameter.',\n 'Make sure you paste the full redirect URL from the browser address bar',\n ),\n );\n return;\n }\n\n resolve({ code, state });\n } catch {\n reject(\n new CliError(\n ErrorCodes.AUTH_INVALID,\n 'Could not parse the pasted URL.',\n 'Make sure you paste the full redirect URL from the browser address bar',\n ),\n );\n }\n });\n\n rl.once('close', () => {\n // Handle stdin close without a line (e.g. EOF)\n reject(\n new CliError(\n ErrorCodes.AUTH_INVALID,\n 'No redirect URL received.',\n 'Run \"notion auth login\" to try again',\n ),\n );\n });\n });\n}\n\n/**\n * Runs the full OAuth browser flow:\n * 1. Generates random state (16 hex bytes via crypto.randomBytes)\n * 2. Starts a temporary HTTP server on localhost:54321\n * 3. Opens the Notion auth URL in the user's browser (or prints it for manual flow)\n * 4. Waits for the callback redirect with ?code=&state=\n * 5. Validates state matches, responds with a success/error HTML page\n * 6. Closes the server and returns { code, state }\n *\n * If --manual flag is set or browser open fails, prints the URL and prompts\n * user to paste the full redirect URL back into the terminal.\n *\n * Throws CliError(AUTH_INVALID) if:\n * - state mismatch (CSRF attempt)\n * - Notion returns ?error=access_denied\n * - Timeout after 120 seconds with no callback\n */\nexport async function runOAuthFlow(options?: { manual?: boolean }): Promise<OAuthFlowResult> {\n const state = randomBytes(16).toString('hex');\n const authUrl = buildAuthUrl(state);\n\n // If manual mode explicitly requested, skip the loopback server entirely\n if (options?.manual) {\n return manualFlow(authUrl);\n }\n\n return new Promise<OAuthFlowResult>((resolve, reject) => {\n let settled = false;\n let timeoutHandle: ReturnType<typeof setTimeout> | null = null;\n\n const server = createServer((req, res) => {\n if (settled) {\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end('<html><body><h1>Already handled. You can close this tab.</h1></body></html>');\n return;\n }\n\n try {\n const reqUrl = new URL(req.url ?? '/', `http://localhost:54321`);\n const code = reqUrl.searchParams.get('code');\n const returnedState = reqUrl.searchParams.get('state');\n const errorParam = reqUrl.searchParams.get('error');\n\n if (errorParam === 'access_denied') {\n settled = true;\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(\n '<html><body><h1>Access Denied</h1><p>You cancelled the Notion OAuth request. You can close this tab.</p></body></html>',\n );\n if (timeoutHandle) clearTimeout(timeoutHandle);\n server.close(() => {\n reject(\n new CliError(\n ErrorCodes.AUTH_INVALID,\n 'Notion OAuth access was denied.',\n 'Run \"notion auth login\" to try again',\n ),\n );\n });\n return;\n }\n\n if (!code || !returnedState) {\n // Probably a favicon request or other unrelated GET — ignore\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end('<html><body><p>Waiting for OAuth callback...</p></body></html>');\n return;\n }\n\n if (returnedState !== state) {\n settled = true;\n res.writeHead(400, { 'Content-Type': 'text/html' });\n res.end(\n '<html><body><h1>Security Error</h1><p>State mismatch — possible CSRF attempt. You can close this tab.</p></body></html>',\n );\n if (timeoutHandle) clearTimeout(timeoutHandle);\n server.close(() => {\n reject(\n new CliError(\n ErrorCodes.AUTH_INVALID,\n 'OAuth state mismatch — possible CSRF attempt. Aborting.',\n 'Run \"notion auth login\" to start a fresh OAuth flow',\n ),\n );\n });\n return;\n }\n\n // Success!\n settled = true;\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(\n '<html><body><h1>Authenticated!</h1><p>You can close this tab and return to the terminal.</p></body></html>',\n );\n if (timeoutHandle) clearTimeout(timeoutHandle);\n server.close(() => {\n resolve({ code, state: returnedState });\n });\n } catch {\n res.writeHead(500, { 'Content-Type': 'text/html' });\n res.end('<html><body><h1>Error processing callback</h1></body></html>');\n }\n });\n\n server.on('error', (err) => {\n if (settled) return;\n settled = true;\n if (timeoutHandle) clearTimeout(timeoutHandle);\n reject(\n new CliError(\n ErrorCodes.AUTH_INVALID,\n `Failed to start OAuth callback server: ${err.message}`,\n 'Make sure port 54321 is not in use, or use --manual flag',\n ),\n );\n });\n\n server.listen(54321, '127.0.0.1', () => {\n // Try to open browser; fall back to manual if it fails\n const browserOpened = openBrowser(authUrl);\n\n if (!browserOpened) {\n // Browser failed — switch to manual flow by closing server and using manual path\n server.close();\n settled = true;\n if (timeoutHandle) clearTimeout(timeoutHandle);\n manualFlow(authUrl).then(resolve, reject);\n return;\n }\n\n process.stderr.write(\n `\\nOpening browser for Notion OAuth...\\nIf your browser didn't open, visit:\\n ${authUrl}\\n\\nWaiting for callback (up to 120 seconds)...\\n`,\n );\n\n // 120-second timeout\n timeoutHandle = setTimeout(() => {\n if (settled) return;\n settled = true;\n server.close(() => {\n reject(\n new CliError(\n ErrorCodes.AUTH_INVALID,\n 'OAuth login timed out after 120 seconds.',\n 'Run \"notion auth login\" to try again, or use --manual flag',\n ),\n );\n });\n }, 120_000);\n });\n });\n}\n","import { readGlobalConfig, writeGlobalConfig } from '../config/config.js';\nimport type { OAuthTokenResponse } from './oauth-client.js';\n\n// Conservative 1-hour expiry: Notion doesn't currently return expires_in for\n// public integrations, so we proactively refresh after 1 hour.\nconst OAUTH_EXPIRY_DURATION_MS = 60 * 60 * 1000;\n\n/**\n * Saves OAuth tokens into the named profile in global config.\n * Merges with existing profile data (preserves .token if present).\n */\nexport async function saveOAuthTokens(\n profileName: string,\n response: OAuthTokenResponse,\n): Promise<void> {\n const config = await readGlobalConfig();\n const existing = config.profiles?.[profileName] ?? {};\n\n const updatedProfile = {\n ...existing,\n oauth_access_token: response.access_token,\n oauth_refresh_token: response.refresh_token,\n oauth_expiry_ms: Date.now() + OAUTH_EXPIRY_DURATION_MS,\n workspace_id: response.workspace_id,\n workspace_name: response.workspace_name,\n ...(response.owner?.user?.id != null && { oauth_user_id: response.owner.user.id }),\n ...(response.owner?.user?.name != null && { oauth_user_name: response.owner.user.name }),\n };\n\n config.profiles = {\n ...config.profiles,\n [profileName]: updatedProfile,\n };\n\n await writeGlobalConfig(config);\n}\n\n/**\n * Clears OAuth tokens from a profile (logout).\n * Leaves internal .token field intact if present.\n */\nexport async function clearOAuthTokens(profileName: string): Promise<void> {\n const config = await readGlobalConfig();\n const existing = config.profiles?.[profileName];\n if (!existing) return;\n\n const {\n oauth_access_token: _access,\n oauth_refresh_token: _refresh,\n oauth_expiry_ms: _expiry,\n oauth_user_id: _userId,\n oauth_user_name: _userName,\n ...rest\n } = existing;\n\n config.profiles = {\n ...config.profiles,\n [profileName]: rest,\n };\n\n await writeGlobalConfig(config);\n}\n","import { Command } from 'commander';\nimport { withErrorHandling } from '../../errors/error-handler.js';\nimport { readGlobalConfig } from '../../config/config.js';\nimport { clearOAuthTokens } from '../../oauth/token-store.js';\nimport { stderrWrite } from '../../output/stderr.js';\nimport { success, dim } from '../../output/color.js';\n\ninterface LogoutOptions {\n profile?: string;\n}\n\nexport function logoutCommand(): Command {\n const cmd = new Command('logout');\n\n cmd\n .description('remove OAuth tokens from the active profile')\n .option('--profile <name>', 'profile name to log out from')\n .action(\n withErrorHandling(async (opts: LogoutOptions) => {\n // Resolve profile name\n let profileName = opts.profile;\n if (!profileName) {\n const config = await readGlobalConfig();\n profileName = config.active_profile ?? 'default';\n }\n\n // Check if profile has OAuth tokens\n const config = await readGlobalConfig();\n const profile = config.profiles?.[profileName];\n\n if (!profile?.oauth_access_token) {\n stderrWrite(`No OAuth session found for profile '${profileName}'.`);\n return;\n }\n\n // Clear OAuth tokens\n await clearOAuthTokens(profileName);\n\n stderrWrite(success(`✓ Logged out. OAuth tokens removed from profile '${profileName}'.`));\n stderrWrite(\n dim(\n `Internal integration token (if any) is still active. Run 'notion init' to change it.`,\n ),\n );\n }),\n );\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { withErrorHandling } from '../../errors/error-handler.js';\nimport { readGlobalConfig } from '../../config/config.js';\nimport { stderrWrite } from '../../output/stderr.js';\nimport { success, error as colorError, dim } from '../../output/color.js';\n\ninterface StatusOptions {\n profile?: string;\n}\n\nexport function statusCommand(): Command {\n const cmd = new Command('status');\n\n cmd\n .description('show authentication status for the active profile')\n .option('--profile <name>', 'profile name to check')\n .action(\n withErrorHandling(async (opts: StatusOptions) => {\n // Resolve profile name\n let profileName = opts.profile;\n const config = await readGlobalConfig();\n if (!profileName) {\n profileName = config.active_profile ?? 'default';\n }\n\n const profile = config.profiles?.[profileName];\n\n stderrWrite(`Profile: ${profileName}`);\n\n if (!profile) {\n stderrWrite(` ${colorError('✗')} No profile found (run 'notion init' to create one)`);\n return;\n }\n\n // OAuth status\n if (profile.oauth_access_token) {\n const userName = profile.oauth_user_name ?? 'unknown';\n const userId = profile.oauth_user_id ?? 'unknown';\n stderrWrite(` OAuth: ${success('✓')} Logged in as ${userName} (user: ${userId})`);\n\n if (profile.oauth_expiry_ms != null) {\n const expiryDate = new Date(profile.oauth_expiry_ms).toISOString();\n stderrWrite(dim(` Access token expires: ${expiryDate}`));\n }\n } else {\n stderrWrite(\n ` OAuth: ${colorError('✗')} Not logged in (run 'notion auth login')`,\n );\n }\n\n // Internal token status\n if (profile.token) {\n const tokenPreview = profile.token.substring(0, 10) + '...';\n stderrWrite(` Internal token: ${success('✓')} Configured (${tokenPreview})`);\n } else {\n stderrWrite(` Internal token: ${colorError('✗')} Not configured`);\n }\n\n // Active method\n if (profile.oauth_access_token) {\n stderrWrite(` Active method: OAuth (user-attributed)`);\n } else if (profile.token) {\n stderrWrite(` Active method: Internal integration token (bot-attributed)`);\n } else {\n stderrWrite(\n dim(` Active method: None (run 'notion auth login' or 'notion init')`),\n );\n }\n }),\n );\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { readGlobalConfig } from '../../config/config.js';\nimport { bold, dim } from '../../output/color.js';\nimport { withErrorHandling } from '../../errors/error-handler.js';\n\nexport function profileListCommand(): Command {\n const cmd = new Command('list');\n\n cmd\n .description('list all authentication profiles')\n .action(withErrorHandling(async () => {\n const config = await readGlobalConfig();\n const profiles = config.profiles ?? {};\n const profileNames = Object.keys(profiles);\n\n if (profileNames.length === 0) {\n process.stdout.write('No profiles configured. Run `notion init` to get started.\\n');\n return;\n }\n\n for (const name of profileNames) {\n const profile = profiles[name];\n const isActive = config.active_profile === name;\n const marker = isActive ? bold('* ') : ' ';\n const activeLabel = isActive ? ' (active)' : '';\n const workspaceInfo = profile.workspace_name ? dim(` — ${profile.workspace_name}`) : '';\n\n process.stdout.write(`${marker}${name}${activeLabel}${workspaceInfo}\\n`);\n }\n }));\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { CliError } from '../../errors/cli-error.js';\nimport { ErrorCodes } from '../../errors/codes.js';\nimport { readGlobalConfig, writeGlobalConfig } from '../../config/config.js';\nimport { stderrWrite } from '../../output/stderr.js';\nimport { success } from '../../output/color.js';\nimport { withErrorHandling } from '../../errors/error-handler.js';\n\nexport function profileUseCommand(): Command {\n const cmd = new Command('use');\n\n cmd\n .description('switch the active profile')\n .argument('<name>', 'profile name to activate')\n .action(withErrorHandling(async (name: string) => {\n const config = await readGlobalConfig();\n const profiles = config.profiles ?? {};\n\n if (!profiles[name]) {\n throw new CliError(\n ErrorCodes.AUTH_PROFILE_NOT_FOUND,\n `Profile \"${name}\" not found.`,\n `Run \"notion profile list\" to see available profiles`,\n );\n }\n\n await writeGlobalConfig({\n ...config,\n active_profile: name,\n });\n\n stderrWrite(success(`Switched to profile \"${name}\".`));\n }));\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { CliError } from '../../errors/cli-error.js';\nimport { ErrorCodes } from '../../errors/codes.js';\nimport { readGlobalConfig, writeGlobalConfig } from '../../config/config.js';\nimport { stderrWrite } from '../../output/stderr.js';\nimport { success } from '../../output/color.js';\nimport { withErrorHandling } from '../../errors/error-handler.js';\n\nexport function profileRemoveCommand(): Command {\n const cmd = new Command('remove');\n\n cmd\n .description('remove an authentication profile')\n .argument('<name>', 'profile name to remove')\n .action(withErrorHandling(async (name: string) => {\n const config = await readGlobalConfig();\n const profiles = { ...(config.profiles ?? {}) };\n\n if (!profiles[name]) {\n throw new CliError(\n ErrorCodes.AUTH_PROFILE_NOT_FOUND,\n `Profile \"${name}\" not found.`,\n `Run \"notion profile list\" to see available profiles`,\n );\n }\n\n delete profiles[name];\n\n // Unset active_profile if it was the removed profile\n const newActiveProfile =\n config.active_profile === name ? undefined : config.active_profile;\n\n await writeGlobalConfig({\n ...config,\n profiles,\n active_profile: newActiveProfile,\n });\n\n stderrWrite(success(`Profile \"${name}\" removed.`));\n }));\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\n\nconst BASH_COMPLETION = `# notion bash completion\n_notion_completion() {\n local cur prev words cword\n _init_completion || return\n\n local commands=\"init profile completion --help --version --verbose --color\"\n local profile_commands=\"list use remove\"\n\n case \"$prev\" in\n notion)\n COMPREPLY=($(compgen -W \"$commands\" -- \"$cur\"))\n return 0\n ;;\n profile)\n COMPREPLY=($(compgen -W \"$profile_commands\" -- \"$cur\"))\n return 0\n ;;\n completion)\n COMPREPLY=($(compgen -W \"bash zsh fish\" -- \"$cur\"))\n return 0\n ;;\n esac\n\n COMPREPLY=($(compgen -W \"$commands\" -- \"$cur\"))\n}\n\ncomplete -F _notion_completion notion\n`;\n\nconst ZSH_COMPLETION = `#compdef notion\n# notion zsh completion\n\n_notion() {\n local -a commands\n\n commands=(\n 'init:authenticate with Notion and save a profile'\n 'profile:manage authentication profiles'\n 'completion:output shell completion script'\n )\n\n local -a global_opts\n global_opts=(\n '--help[display help]'\n '--version[output version]'\n '--verbose[show API requests/responses]'\n '--color[force color output]'\n )\n\n if (( CURRENT == 2 )); then\n _describe 'command' commands\n _arguments $global_opts\n return\n fi\n\n case $words[2] in\n profile)\n local -a profile_cmds\n profile_cmds=(\n 'list:list all authentication profiles'\n 'use:switch the active profile'\n 'remove:remove an authentication profile'\n )\n _describe 'profile command' profile_cmds\n ;;\n completion)\n local -a shells\n shells=('bash' 'zsh' 'fish')\n _describe 'shell' shells\n ;;\n esac\n}\n\n_notion \"$@\"\n`;\n\nconst FISH_COMPLETION = `# notion fish completion\n\n# Disable file completion by default\ncomplete -c notion -f\n\n# Global options\ncomplete -c notion -l help -d 'display help'\ncomplete -c notion -l version -d 'output version'\ncomplete -c notion -l verbose -d 'show API requests/responses'\ncomplete -c notion -l color -d 'force color output'\n\n# Top-level commands\ncomplete -c notion -n '__fish_use_subcommand' -a init -d 'authenticate with Notion and save a profile'\ncomplete -c notion -n '__fish_use_subcommand' -a profile -d 'manage authentication profiles'\ncomplete -c notion -n '__fish_use_subcommand' -a completion -d 'output shell completion script'\n\n# profile subcommands\ncomplete -c notion -n '__fish_seen_subcommand_from profile' -a list -d 'list all authentication profiles'\ncomplete -c notion -n '__fish_seen_subcommand_from profile' -a use -d 'switch the active profile'\ncomplete -c notion -n '__fish_seen_subcommand_from profile' -a remove -d 'remove an authentication profile'\n\n# completion shells\ncomplete -c notion -n '__fish_seen_subcommand_from completion' -a bash -d 'bash completion script'\ncomplete -c notion -n '__fish_seen_subcommand_from completion' -a zsh -d 'zsh completion script'\ncomplete -c notion -n '__fish_seen_subcommand_from completion' -a fish -d 'fish completion script'\n`;\n\nexport function completionCommand(): Command {\n const cmd = new Command('completion');\n\n cmd\n .description('output shell completion script')\n .argument('<shell>', 'shell type (bash, zsh, fish)')\n .action(withErrorHandling(async (shell: string) => {\n switch (shell) {\n case 'bash':\n process.stdout.write(BASH_COMPLETION);\n break;\n case 'zsh':\n process.stdout.write(ZSH_COMPLETION);\n break;\n case 'fish':\n process.stdout.write(FISH_COMPLETION);\n break;\n default:\n throw new CliError(\n ErrorCodes.UNKNOWN,\n `Unknown shell: \"${shell}\".`,\n 'Supported shells: bash, zsh, fish',\n );\n }\n }));\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { isFullPage, isFullPageOrDataSource } from '@notionhq/client';\nimport type { PageObjectResponse, DataSourceObjectResponse } from '@notionhq/client/build/src/api-endpoints.js';\nimport { resolveToken } from '../config/token.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { reportTokenSource } from '../output/stderr.js';\nimport { setOutputMode, printOutput } from '../output/format.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\n\nfunction getTitle(item: PageObjectResponse | DataSourceObjectResponse): string {\n if (item.object === 'data_source') {\n return item.title.map((t) => t.plain_text).join('') || '(untitled)';\n }\n const titleProp = Object.values(item.properties).find((p) => p.type === 'title');\n if (titleProp?.type === 'title') {\n return titleProp.title.map((t) => t.plain_text).join('') || '(untitled)';\n }\n return '(untitled)';\n}\n\n// Map user-facing type to SDK filter value\nfunction toSdkFilterValue(type: 'page' | 'database'): 'page' | 'data_source' {\n return type === 'database' ? 'data_source' : 'page';\n}\n\n// Display label for object type (data_source shown as \"database\" to users)\nfunction displayType(item: PageObjectResponse | DataSourceObjectResponse): string {\n return item.object === 'data_source' ? 'database' : item.object;\n}\n\nexport function searchCommand(): Command {\n const cmd = new Command('search');\n\n cmd\n .description('search Notion workspace by keyword')\n .argument('<query>', 'search keyword')\n .option('--type <type>', 'filter by object type (page or database)', (val) => {\n if (val !== 'page' && val !== 'database') {\n throw new Error('--type must be \"page\" or \"database\"');\n }\n return val as 'page' | 'database';\n })\n .option('--cursor <cursor>', 'start from this pagination cursor (from a previous --next hint)')\n .option('--json', 'force JSON output')\n .action(\n withErrorHandling(async (query: string, opts: { type?: 'page' | 'database'; cursor?: string; json?: boolean }) => {\n if (opts.json) {\n setOutputMode('json');\n }\n\n const { token, source } = await resolveToken();\n reportTokenSource(source);\n const notion = createNotionClient(token);\n\n const response = await notion.search({\n query,\n filter: opts.type\n ? { property: 'object', value: toSdkFilterValue(opts.type) }\n : undefined,\n start_cursor: opts.cursor,\n page_size: 20,\n });\n\n const fullResults = response.results.filter((r) => isFullPageOrDataSource(r)) as (\n | PageObjectResponse\n | DataSourceObjectResponse\n )[];\n\n if (fullResults.length === 0) {\n process.stdout.write(`No results found for \"${query}\"\\n`);\n return;\n }\n\n const headers = ['TYPE', 'TITLE', 'ID', 'MODIFIED'];\n const rows = fullResults.map((item) => [\n displayType(item),\n getTitle(item),\n item.id,\n item.last_edited_time.split('T')[0],\n ]);\n\n printOutput(fullResults, headers, rows);\n\n if (response.has_more && response.next_cursor) {\n process.stderr.write(`\\n --next: notion search \"${query}\" --cursor ${response.next_cursor}\\n`);\n }\n })\n );\n\n return cmd;\n}\n","import { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { parse } from 'yaml';\nimport type { LocalConfig } from '../types/config.js';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\n\n/**\n * Reads the local .notion.yaml file from the current working directory.\n * Returns null if the file doesn't exist.\n * Throws CliError(CONFIG_INVALID) if both `profile` and `token` are specified.\n */\nexport async function readLocalConfig(): Promise<LocalConfig | null> {\n const localConfigPath = join(process.cwd(), '.notion.yaml');\n let raw: string;\n\n try {\n raw = await readFile(localConfigPath, 'utf-8');\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n return null;\n }\n throw new CliError(\n ErrorCodes.CONFIG_READ_ERROR,\n `Failed to read local config: ${localConfigPath}`,\n 'Check file permissions',\n );\n }\n\n let parsed: LocalConfig;\n try {\n parsed = (parse(raw) as LocalConfig) ?? {};\n } catch {\n throw new CliError(\n ErrorCodes.CONFIG_INVALID,\n `Failed to parse .notion.yaml`,\n 'Check that the file contains valid YAML',\n );\n }\n\n if (parsed.profile !== undefined && parsed.token !== undefined) {\n throw new CliError(\n ErrorCodes.CONFIG_INVALID,\n '.notion.yaml cannot specify both \"profile\" and \"token\"',\n 'Use either \"profile: <name>\" to reference a saved profile, or \"token: <value>\" for a direct token',\n );\n }\n\n return parsed;\n}\n","import type { ProfileConfig, TokenResult } from '../types/config.js';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\nimport { readGlobalConfig } from './config.js';\nimport { readLocalConfig } from './local-config.js';\nimport { refreshAccessToken } from '../oauth/oauth-client.js';\nimport { clearOAuthTokens, saveOAuthTokens } from '../oauth/token-store.js';\n\n/**\n * Returns true when an OAuth access token is present but past its expiry timestamp.\n */\nfunction isOAuthExpired(profile: ProfileConfig): boolean {\n if (profile.oauth_expiry_ms == null) return false;\n return Date.now() >= profile.oauth_expiry_ms;\n}\n\n/**\n * Attempts to resolve an OAuth access token from a profile.\n * - If oauth_access_token is present and not expired, returns it immediately.\n * - If oauth_access_token is present but expired, transparently refreshes via\n * refreshAccessToken() and persists the new tokens before returning.\n * - If refresh fails (token revoked), clears OAuth tokens and throws AUTH_NO_TOKEN.\n * Returns null if the profile has no oauth_access_token.\n */\nasync function resolveOAuthToken(\n profileName: string,\n profile: ProfileConfig,\n): Promise<string | null> {\n if (!profile.oauth_access_token) return null;\n\n if (!isOAuthExpired(profile)) {\n return profile.oauth_access_token;\n }\n\n // Token expired — try to refresh\n if (!profile.oauth_refresh_token) {\n await clearOAuthTokens(profileName);\n throw new CliError(\n ErrorCodes.AUTH_NO_TOKEN,\n 'OAuth session expired and no refresh token is available.',\n 'Run \"notion auth login\" to re-authenticate',\n );\n }\n\n try {\n const refreshed = await refreshAccessToken(profile.oauth_refresh_token);\n await saveOAuthTokens(profileName, refreshed);\n return refreshed.access_token;\n } catch {\n await clearOAuthTokens(profileName);\n throw new CliError(\n ErrorCodes.AUTH_NO_TOKEN,\n 'OAuth session expired. Run \"notion auth login\" to re-authenticate.',\n 'Your session was revoked or the refresh token has expired',\n );\n }\n}\n\n/**\n * Resolves the Notion API token using a layered lookup chain:\n * 1. NOTION_API_TOKEN environment variable\n * 2. .notion.yaml token field (direct token)\n * 3. .notion.yaml profile field → look up in global config → prefer oauth_access_token\n * (auto-refreshes if expired); falls back to .token if no OAuth tokens\n * 4. active_profile from global config → same OAuth preference logic\n *\n * Throws CliError(AUTH_NO_TOKEN) if no token is found anywhere.\n */\nexport async function resolveToken(): Promise<TokenResult> {\n // 1. Check env var first\n const envToken = process.env['NOTION_API_TOKEN'];\n if (envToken) {\n return { token: envToken, source: 'NOTION_API_TOKEN' };\n }\n\n // 2. Check .notion.yaml\n const localConfig = await readLocalConfig();\n\n if (localConfig !== null) {\n // 2a. Direct token in local config\n if (localConfig.token) {\n return { token: localConfig.token, source: '.notion.yaml' };\n }\n\n // 2b. Profile name in local config → look up in global config\n if (localConfig.profile) {\n const globalConfig = await readGlobalConfig();\n const profile = globalConfig.profiles?.[localConfig.profile];\n if (profile) {\n // Prefer OAuth access token over internal integration token\n const oauthToken = await resolveOAuthToken(localConfig.profile, profile);\n if (oauthToken) {\n return { token: oauthToken, source: 'oauth' };\n }\n if (profile.token) {\n return { token: profile.token, source: `profile: ${localConfig.profile}` };\n }\n }\n }\n }\n\n // 3. Fall back to active profile in global config\n const globalConfig = await readGlobalConfig();\n if (globalConfig.active_profile) {\n const profile = globalConfig.profiles?.[globalConfig.active_profile];\n if (profile) {\n // Prefer OAuth access token over internal integration token\n const oauthToken = await resolveOAuthToken(globalConfig.active_profile, profile);\n if (oauthToken) {\n return { token: oauthToken, source: 'oauth' };\n }\n if (profile.token) {\n return { token: profile.token, source: `profile: ${globalConfig.active_profile}` };\n }\n }\n }\n\n // 4. Nothing found\n throw new CliError(\n ErrorCodes.AUTH_NO_TOKEN,\n 'No authentication token found.',\n 'Run \"notion init\" to set up a profile',\n );\n}\n","import { Command } from 'commander';\nimport { isFullPageOrDataSource } from '@notionhq/client';\nimport type { PageObjectResponse, DataSourceObjectResponse } from '@notionhq/client/build/src/api-endpoints.js';\nimport { resolveToken } from '../config/token.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { reportTokenSource } from '../output/stderr.js';\nimport { setOutputMode, printOutput } from '../output/format.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\n\nfunction getTitle(item: PageObjectResponse | DataSourceObjectResponse): string {\n if (item.object === 'data_source') {\n return item.title.map((t) => t.plain_text).join('') || '(untitled)';\n }\n const titleProp = Object.values(item.properties).find((p) => p.type === 'title');\n if (titleProp?.type === 'title') {\n return titleProp.title.map((t) => t.plain_text).join('') || '(untitled)';\n }\n return '(untitled)';\n}\n\n// Display label for object type (data_source shown as \"database\" to users)\nfunction displayType(item: PageObjectResponse | DataSourceObjectResponse): string {\n return item.object === 'data_source' ? 'database' : item.object;\n}\n\nexport function lsCommand(): Command {\n const cmd = new Command('ls');\n\n cmd\n .description('list accessible Notion pages and databases')\n .option('--type <type>', 'filter by object type (page or database)', (val) => {\n if (val !== 'page' && val !== 'database') {\n throw new Error('--type must be \"page\" or \"database\"');\n }\n return val as 'page' | 'database';\n })\n .option('--cursor <cursor>', 'start from this pagination cursor (from a previous --next hint)')\n .option('--json', 'force JSON output')\n .action(\n withErrorHandling(async (opts: { type?: 'page' | 'database'; cursor?: string; json?: boolean }) => {\n if (opts.json) {\n setOutputMode('json');\n }\n\n const { token, source } = await resolveToken();\n reportTokenSource(source);\n const notion = createNotionClient(token);\n\n const response = await notion.search({\n start_cursor: opts.cursor,\n page_size: 20,\n });\n\n let items = response.results.filter((r) => isFullPageOrDataSource(r)) as (\n | PageObjectResponse\n | DataSourceObjectResponse\n )[];\n\n if (opts.type) {\n const filterType = opts.type;\n items = items.filter((r) =>\n filterType === 'database' ? r.object === 'data_source' : r.object === filterType\n );\n }\n\n if (items.length === 0) {\n process.stdout.write('No accessible content found\\n');\n return;\n }\n\n const headers = ['TYPE', 'TITLE', 'ID', 'MODIFIED'];\n const rows = items.map((item) => [\n displayType(item),\n getTitle(item),\n item.id,\n item.last_edited_time.split('T')[0],\n ]);\n\n printOutput(items, headers, rows);\n\n if (response.has_more && response.next_cursor) {\n process.stderr.write(`\\n --next: notion ls --cursor ${response.next_cursor}\\n`);\n }\n })\n );\n\n return cmd;\n}\n","import { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { Command } from 'commander';\nimport { parseNotionId } from '../notion/url-parser.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\n\nconst execAsync = promisify(exec);\n\nexport function openCommand(): Command {\n const cmd = new Command('open');\n\n cmd\n .description('open a Notion page in the default browser')\n .argument('<id/url>', 'Notion page ID or URL')\n .action(withErrorHandling(async (idOrUrl: string) => {\n const id = parseNotionId(idOrUrl);\n const url = `https://www.notion.so/${id}`;\n\n const platform = process.platform;\n const opener =\n platform === 'darwin' ? 'open'\n : platform === 'win32' ? 'start'\n : 'xdg-open'; // Linux\n\n await execAsync(`${opener} \"${url}\"`);\n process.stdout.write(`Opening ${url}\\n`);\n }));\n\n return cmd;\n}\n","import { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\n\n/** Matches a raw 32-character hex ID (no dashes) */\nconst NOTION_ID_REGEX = /^[0-9a-f]{32}$/i;\n\n/** Matches a UUID with dashes (8-4-4-4-12) */\nconst UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n/**\n * Matches a 32-char hex ID embedded in a Notion URL path.\n * Handles notion.so and notion.site domains, with optional workspace, page title,\n * query parameters, and fragments.\n * Uses lazy matching to find the first 32-char hex ID in the path.\n */\nconst NOTION_URL_REGEX = /https?:\\/\\/(?:[a-zA-Z0-9-]+\\.)?notion\\.(?:so|site)\\/.*?([0-9a-f]{32})(?:[?#]|$)/i;\n\nfunction throwInvalidId(input: string): never {\n throw new CliError(\n ErrorCodes.INVALID_ID,\n `Cannot parse Notion ID from: ${input}`,\n 'Provide a valid Notion URL or page/database ID',\n );\n}\n\n/**\n * Parse any Notion URL or ID string into the normalized 32-char hex format.\n *\n * Accepts:\n * - Raw 32-char hex IDs (pass-through)\n * - UUIDs with dashes (strips dashes)\n * - notion.so and notion.site URLs with embedded 32-char hex IDs\n *\n * @throws {CliError} with code INVALID_ID if the input cannot be parsed\n */\nexport function parseNotionId(input: string): string {\n if (!input) throwInvalidId(input);\n\n // 1. Raw 32-char hex ID — pass through\n if (NOTION_ID_REGEX.test(input)) {\n return input.toLowerCase();\n }\n\n // 2. UUID with dashes — strip dashes\n if (UUID_REGEX.test(input)) {\n return input.replace(/-/g, '').toLowerCase();\n }\n\n // 3. Notion URL — extract embedded 32-char hex ID\n const urlMatch = NOTION_URL_REGEX.exec(input);\n if (urlMatch) {\n return urlMatch[1].toLowerCase();\n }\n\n throwInvalidId(input);\n}\n\n/**\n * Convert a 32-char hex Notion ID to standard UUID format (8-4-4-4-12 with dashes).\n */\nexport function toUuid(id: string): string {\n return `${id.slice(0, 8)}-${id.slice(8, 12)}-${id.slice(12, 16)}-${id.slice(16, 20)}-${id.slice(20)}`;\n}\n","import { Command } from 'commander';\nimport type { UserObjectResponse } from '@notionhq/client/build/src/api-endpoints.js';\nimport { resolveToken } from '../config/token.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { reportTokenSource } from '../output/stderr.js';\nimport { paginateResults } from '../output/paginate.js';\nimport { setOutputMode, printOutput } from '../output/format.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\n\nfunction getEmailOrWorkspace(user: UserObjectResponse): string {\n if (user.type === 'person') {\n return user.person.email ?? '—';\n }\n if (user.type === 'bot') {\n const bot = user.bot as { workspace_name?: string | null } | Record<string, never>;\n return ('workspace_name' in bot && bot.workspace_name) ? bot.workspace_name : '—';\n }\n return '—';\n}\n\nexport function usersCommand(): Command {\n const cmd = new Command('users');\n\n cmd\n .description('list all users in the workspace')\n .option('--json', 'output as JSON')\n .action(withErrorHandling(async (opts: { json?: boolean }) => {\n if (opts.json) setOutputMode('json');\n\n const { token, source } = await resolveToken();\n reportTokenSource(source);\n const notion = createNotionClient(token);\n\n const allUsers = await paginateResults((cursor) =>\n notion.users.list({ start_cursor: cursor }),\n );\n\n // Filter to full user objects (those with name field defined)\n const users = (allUsers as UserObjectResponse[]).filter((u) => u.name !== undefined);\n\n const rows = users.map((user) => [\n user.type,\n user.name ?? '(unnamed)',\n getEmailOrWorkspace(user),\n user.id,\n ]);\n\n printOutput(users, ['TYPE', 'NAME', 'EMAIL / WORKSPACE', 'ID'], rows);\n }));\n\n return cmd;\n}\n","export async function paginateResults<T>(\n fetcher: (cursor?: string) => Promise<{ results: T[]; next_cursor: string | null; has_more: boolean }>\n): Promise<T[]> {\n const allResults: T[] = [];\n let cursor: string | undefined;\n let hasMore = true;\n\n while (hasMore) {\n const response = await fetcher(cursor);\n allResults.push(...response.results);\n cursor = response.next_cursor ?? undefined;\n hasMore = response.has_more;\n }\n\n return allResults;\n}\n","import { Command } from 'commander';\nimport type { CommentObjectResponse } from '@notionhq/client/build/src/api-endpoints.js';\nimport { parseNotionId, toUuid } from '../notion/url-parser.js';\nimport { resolveToken } from '../config/token.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { reportTokenSource } from '../output/stderr.js';\nimport { paginateResults } from '../output/paginate.js';\nimport { setOutputMode, printOutput } from '../output/format.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\n\nexport function commentsCommand(): Command {\n const cmd = new Command('comments');\n\n cmd\n .description('list comments on a Notion page')\n .argument('<id/url>', 'Notion page ID or URL')\n .option('--json', 'output as JSON')\n .action(withErrorHandling(async (idOrUrl: string, opts: { json?: boolean }) => {\n if (opts.json) setOutputMode('json');\n\n const id = parseNotionId(idOrUrl);\n const uuid = toUuid(id);\n\n const { token, source } = await resolveToken();\n reportTokenSource(source);\n const notion = createNotionClient(token);\n\n const comments = await paginateResults((cursor) =>\n notion.comments.list({ block_id: uuid, start_cursor: cursor }),\n ) as CommentObjectResponse[];\n\n if (comments.length === 0) {\n process.stdout.write('No comments found on this page\\n');\n return;\n }\n\n const rows = comments.map((comment) => {\n const text = comment.rich_text.map((t) => t.plain_text).join('');\n return [\n comment.created_time.split('T')[0],\n comment.created_by.id.slice(0, 8) + '...',\n text.slice(0, 80) + (text.length > 80 ? '…' : ''),\n ];\n });\n\n printOutput(comments, ['DATE', 'AUTHOR ID', 'COMMENT'], rows);\n }));\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { withErrorHandling } from '../errors/error-handler.js';\nimport { resolveToken } from '../config/token.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { parseNotionId } from '../notion/url-parser.js';\nimport { fetchPageWithBlocks } from '../services/page.service.js';\nimport { renderPageMarkdown } from '../blocks/render.js';\nimport { renderMarkdown } from '../output/markdown.js';\nimport { isatty } from '../output/format.js';\n\n\nexport function readCommand(): Command {\n return new Command('read')\n .description('Read a Notion page as markdown')\n .argument('<id>', 'Notion page ID or URL')\n .option('--json', 'Output raw JSON instead of markdown')\n .option('--md', 'Output raw markdown (no terminal styling)')\n .action(\n withErrorHandling(async (id: string, options: { json?: boolean; md?: boolean }) => {\n const { token } = await resolveToken();\n const client = createNotionClient(token);\n const pageId = parseNotionId(id);\n const pageWithBlocks = await fetchPageWithBlocks(client, pageId);\n\n if (options.json) {\n process.stdout.write(JSON.stringify(pageWithBlocks, null, 2) + '\\n');\n } else {\n const markdown = renderPageMarkdown(pageWithBlocks);\n if (options.md || !isatty()) {\n // Raw markdown — piped output or explicit --md flag\n process.stdout.write(markdown);\n } else {\n // TTY: render with terminal styling, write directly to stdout\n process.stdout.write(renderMarkdown(markdown));\n }\n }\n }),\n );\n}\n","import { Client, collectPaginatedAPI, isFullBlock } from '@notionhq/client';\nimport type {\n BlockObjectResponse,\n PageObjectResponse,\n} from '@notionhq/client/build/src/api-endpoints.js';\n\nexport interface BlockNode {\n block: BlockObjectResponse;\n children: BlockNode[];\n}\n\nexport interface PageWithBlocks {\n page: PageObjectResponse;\n blocks: BlockNode[];\n}\n\nconst MAX_CONCURRENT_REQUESTS = 3;\n\nasync function fetchBlockTree(\n client: Client,\n blockId: string,\n depth: number,\n maxDepth: number,\n): Promise<BlockNode[]> {\n if (depth >= maxDepth) return [];\n\n const rawBlocks = await collectPaginatedAPI(client.blocks.children.list, {\n block_id: blockId,\n });\n\n const blocks = rawBlocks.filter(isFullBlock);\n\n // child_page and child_database are separate Notion pages — never recurse into them.\n // They render as headings/links; the user can `notion read <id>` them individually.\n const SKIP_RECURSE = new Set(['child_page', 'child_database']);\n\n const nodes: BlockNode[] = [];\n for (let i = 0; i < blocks.length; i += MAX_CONCURRENT_REQUESTS) {\n const batch = blocks.slice(i, i + MAX_CONCURRENT_REQUESTS);\n const batchNodes = await Promise.all(\n batch.map(async (block) => {\n const children = block.has_children && !SKIP_RECURSE.has(block.type)\n ? await fetchBlockTree(client, block.id, depth + 1, maxDepth)\n : [];\n return { block, children };\n }),\n );\n nodes.push(...batchNodes);\n }\n\n return nodes;\n}\n\nexport async function fetchPageWithBlocks(\n client: Client,\n pageId: string,\n): Promise<PageWithBlocks> {\n const page = (await client.pages.retrieve({ page_id: pageId })) as PageObjectResponse;\n const blocks = await fetchBlockTree(client, pageId, 0, 10);\n return { page, blocks };\n}\n","import type { RichTextItemResponse } from '@notionhq/client/build/src/api-endpoints.js';\n\nexport function richTextToMd(richText: RichTextItemResponse[]): string {\n return richText.map(segmentToMd).join('');\n}\n\nfunction segmentToMd(segment: RichTextItemResponse): string {\n if (segment.type === 'equation') {\n return `$${segment.equation.expression}$`;\n }\n\n if (segment.type === 'mention') {\n const text = segment.plain_text;\n return segment.href ? `[${text}](${segment.href})` : text;\n }\n\n // type === 'text'\n const annotated = applyAnnotations(segment.text.content, segment.annotations);\n return segment.text.link ? `[${annotated}](${segment.text.link.url})` : annotated;\n}\n\nfunction applyAnnotations(\n text: string,\n annotations: RichTextItemResponse['annotations']\n): string {\n let result = text;\n\n // Apply inner-to-outer: code → strikethrough → italic → bold\n if (annotations.code) result = `\\`${result}\\``;\n if (annotations.strikethrough) result = `~~${result}~~`;\n if (annotations.italic) result = `_${result}_`;\n if (annotations.bold) result = `**${result}**`;\n\n return result;\n}\n","import type { BlockObjectResponse } from '@notionhq/client/build/src/api-endpoints.js';\nimport { richTextToMd } from './rich-text.js';\n\nexport interface BlockConverterContext {\n listNumber?: number; // For numbered_list_item: the 1-based position in the list\n childrenMd?: string; // Pre-rendered children markdown (render.ts provides this)\n}\n\ntype BlockConverter = (block: BlockObjectResponse, ctx?: BlockConverterContext) => string;\n\nfunction indentChildren(childrenMd: string): string {\n return childrenMd\n .split('\\n')\n .filter(Boolean)\n .map(line => ' ' + line)\n .join('\\n') + '\\n';\n}\n\nconst converters: Record<string, BlockConverter> = {\n paragraph(block) {\n const b = block as Extract<BlockObjectResponse, { type: 'paragraph' }>;\n return `${richTextToMd(b.paragraph.rich_text)}\\n`;\n },\n\n heading_1(block) {\n const b = block as Extract<BlockObjectResponse, { type: 'heading_1' }>;\n return `# ${richTextToMd(b.heading_1.rich_text)}\\n`;\n },\n\n heading_2(block) {\n const b = block as Extract<BlockObjectResponse, { type: 'heading_2' }>;\n return `## ${richTextToMd(b.heading_2.rich_text)}\\n`;\n },\n\n heading_3(block) {\n const b = block as Extract<BlockObjectResponse, { type: 'heading_3' }>;\n return `### ${richTextToMd(b.heading_3.rich_text)}\\n`;\n },\n\n bulleted_list_item(block, ctx) {\n const b = block as Extract<BlockObjectResponse, { type: 'bulleted_list_item' }>;\n const text = richTextToMd(b.bulleted_list_item.rich_text);\n const header = `- ${text}\\n`;\n if (ctx?.childrenMd) {\n return header + indentChildren(ctx.childrenMd);\n }\n return header;\n },\n\n numbered_list_item(block, ctx) {\n const b = block as Extract<BlockObjectResponse, { type: 'numbered_list_item' }>;\n const num = ctx?.listNumber ?? 1;\n return `${num}. ${richTextToMd(b.numbered_list_item.rich_text)}\\n`;\n },\n\n to_do(block) {\n const b = block as Extract<BlockObjectResponse, { type: 'to_do' }>;\n const checkbox = b.to_do.checked ? '[x]' : '[ ]';\n return `- ${checkbox} ${richTextToMd(b.to_do.rich_text)}\\n`;\n },\n\n code(block) {\n const b = block as Extract<BlockObjectResponse, { type: 'code' }>;\n const lang = b.code.language === 'plain text' ? '' : b.code.language;\n const content = richTextToMd(b.code.rich_text);\n return `\\`\\`\\`${lang}\\n${content}\\n\\`\\`\\`\\n`;\n },\n\n quote(block) {\n const b = block as Extract<BlockObjectResponse, { type: 'quote' }>;\n return `> ${richTextToMd(b.quote.rich_text)}\\n`;\n },\n\n divider() {\n return '---\\n';\n },\n\n callout(block) {\n const b = block as Extract<BlockObjectResponse, { type: 'callout' }>;\n const text = richTextToMd(b.callout.rich_text);\n const icon = b.callout.icon;\n if (icon?.type === 'emoji') {\n return `> ${icon.emoji} ${text}\\n`;\n }\n return `> ${text}\\n`;\n },\n\n toggle(block, ctx) {\n const b = block as Extract<BlockObjectResponse, { type: 'toggle' }>;\n const header = `**${richTextToMd(b.toggle.rich_text)}**\\n`;\n if (ctx?.childrenMd) {\n return header + ctx.childrenMd;\n }\n return header;\n },\n\n image(block) {\n const b = block as Extract<BlockObjectResponse, { type: 'image' }>;\n const caption = richTextToMd(b.image.caption);\n if (b.image.type === 'file') {\n const url = b.image.file.url;\n const expiry = b.image.file.expiry_time;\n return ` <!-- expires: ${expiry} -->\\n`;\n }\n const url = b.image.external.url;\n return `\\n`;\n },\n\n bookmark(block) {\n const b = block as Extract<BlockObjectResponse, { type: 'bookmark' }>;\n const caption = richTextToMd(b.bookmark.caption);\n const text = caption || b.bookmark.url;\n return `[${text}](${b.bookmark.url})\\n`;\n },\n\n child_page(block) {\n const b = block as Extract<BlockObjectResponse, { type: 'child_page' }>;\n return `### ${b.child_page.title}\\n`;\n },\n\n child_database(block) {\n const b = block as Extract<BlockObjectResponse, { type: 'child_database' }>;\n return `### ${b.child_database.title}\\n`;\n },\n\n link_preview(block) {\n const b = block as Extract<BlockObjectResponse, { type: 'link_preview' }>;\n return `[${b.link_preview.url}](${b.link_preview.url})\\n`;\n },\n};\n\nexport function blockToMd(block: BlockObjectResponse, ctx?: BlockConverterContext): string {\n const converter = converters[block.type];\n if (converter) {\n return converter(block, ctx);\n }\n return `<!-- unsupported block: ${block.type} -->\\n`;\n}\n","import type { PageObjectResponse } from '@notionhq/client/build/src/api-endpoints.js';\n\ntype PropertyValue = PageObjectResponse['properties'][string];\n\nexport function formatPropertyValue(name: string, prop: PropertyValue): string {\n switch (prop.type) {\n case 'title':\n return prop.title.map((rt) => rt.plain_text).join('');\n\n case 'rich_text':\n return prop.rich_text.map((rt) => rt.plain_text).join('');\n\n case 'number':\n return prop.number !== null ? String(prop.number) : '';\n\n case 'select':\n return prop.select?.name ?? '';\n\n case 'status':\n return prop.status?.name ?? '';\n\n case 'multi_select':\n return prop.multi_select.map((s) => s.name).join(', ');\n\n case 'date':\n if (!prop.date) return '';\n return prop.date.end ? `${prop.date.start} → ${prop.date.end}` : prop.date.start;\n\n case 'checkbox':\n return prop.checkbox ? 'true' : 'false';\n\n case 'url':\n return prop.url ?? '';\n\n case 'email':\n return prop.email ?? '';\n\n case 'phone_number':\n return prop.phone_number ?? '';\n\n case 'people':\n return prop.people\n .map((p) => ('name' in p && p.name ? p.name : p.id))\n .join(', ');\n\n case 'relation':\n return prop.relation.map((r) => r.id).join(', ');\n\n case 'formula': {\n const f = prop.formula;\n if (f.type === 'string') return f.string ?? '';\n if (f.type === 'number') return f.number !== null ? String(f.number) : '';\n if (f.type === 'boolean') return String(f.boolean);\n if (f.type === 'date') return f.date?.start ?? '';\n return '';\n }\n\n case 'rollup': {\n const r = prop.rollup;\n if (r.type === 'number') return r.number !== null ? String(r.number) : '';\n if (r.type === 'date') return r.date?.start ?? '';\n if (r.type === 'array') return `[${r.array.length} items]`;\n return '';\n }\n\n case 'created_time':\n return prop.created_time;\n\n case 'last_edited_time':\n return prop.last_edited_time;\n\n case 'created_by':\n return 'name' in prop.created_by\n ? (prop.created_by.name ?? prop.created_by.id)\n : prop.created_by.id;\n\n case 'last_edited_by':\n return 'name' in prop.last_edited_by\n ? (prop.last_edited_by.name ?? prop.last_edited_by.id)\n : prop.last_edited_by.id;\n\n case 'files':\n return prop.files\n .map((f) => {\n if (f.type === 'external') return f.external.url;\n return f.name;\n })\n .join(', ');\n\n case 'unique_id':\n return prop.unique_id.prefix\n ? `${prop.unique_id.prefix}-${prop.unique_id.number}`\n : String(prop.unique_id.number ?? '');\n\n default:\n return '';\n }\n}\n\nexport function extractPageTitle(page: PageObjectResponse): string {\n const titleProp = Object.values(page.properties).find((p) => p.type === 'title');\n if (!titleProp || titleProp.type !== 'title') return page.id;\n return titleProp.title.map((rt) => rt.plain_text).join('') || page.id;\n}\n\n","import type { PageObjectResponse } from '@notionhq/client/build/src/api-endpoints.js';\nimport type { BlockNode, PageWithBlocks } from '../services/page.service.js';\nimport { blockToMd } from './converters.js';\nimport { formatPropertyValue } from './properties.js';\n\nfunction buildPropertiesHeader(page: PageObjectResponse): string {\n const lines: string[] = ['---'];\n for (const [name, prop] of Object.entries(page.properties)) {\n const value = formatPropertyValue(name, prop);\n if (value) {\n lines.push(`${name}: ${value}`);\n }\n }\n lines.push('---', '');\n return lines.join('\\n');\n}\n\nfunction renderBlockTree(blocks: BlockNode[]): string {\n const parts: string[] = [];\n let listCounter = 0; // tracks consecutive numbered_list_item\n\n for (const node of blocks) {\n // Track numbered list position\n if (node.block.type === 'numbered_list_item') {\n listCounter++;\n } else {\n listCounter = 0; // reset on any non-numbered block\n }\n\n // Recursively render children first\n const childrenMd = node.children.length > 0\n ? renderBlockTree(node.children)\n : '';\n\n const md = blockToMd(node.block, {\n listNumber: node.block.type === 'numbered_list_item' ? listCounter : undefined,\n childrenMd: childrenMd || undefined,\n });\n\n parts.push(md);\n }\n\n return parts.join('');\n}\n\nexport function renderPageMarkdown({ page, blocks }: PageWithBlocks): string {\n const header = buildPropertiesHeader(page);\n const content = renderBlockTree(blocks);\n return header + content;\n}\n","import { Chalk } from 'chalk';\nimport { isatty } from './format.js';\n\n// Use a Chalk instance that always produces color — we only call this when stdout is a TTY\nconst c = new Chalk({ level: 3 });\n\n/**\n * Render markdown text with terminal ANSI styling.\n * Only call when stdout is a TTY — returns raw markdown otherwise.\n */\nexport function renderMarkdown(md: string): string {\n if (!isatty()) return md;\n\n const lines = md.split('\\n');\n const out: string[] = [];\n let inFence = false;\n let fenceLang = '';\n let fenceLines: string[] = [];\n\n for (const line of lines) {\n // --- Fenced code blocks ---\n const fenceMatch = line.match(/^```(\\w*)$/);\n if (fenceMatch && !inFence) {\n inFence = true;\n fenceLang = fenceMatch[1] ?? '';\n fenceLines = [];\n continue;\n }\n if (line === '```' && inFence) {\n inFence = false;\n const header = fenceLang ? c.dim(`[${fenceLang}]`) : '';\n if (header) out.push(header);\n for (const fl of fenceLines) {\n out.push(c.green(' ' + fl));\n }\n out.push('');\n continue;\n }\n if (inFence) {\n fenceLines.push(line);\n continue;\n }\n\n // --- YAML frontmatter block (--- ... ---) ---\n if (line === '---') {\n out.push(c.dim('─'.repeat(40)));\n continue;\n }\n\n // --- HTML comments (unsupported blocks) — suppress ---\n if (/^<!--.*-->$/.test(line.trim())) {\n continue;\n }\n\n // --- Headings ---\n const h1 = line.match(/^# (.+)/);\n if (h1) { out.push('\\n' + c.bold.cyan(h1[1])); continue; }\n\n const h2 = line.match(/^## (.+)/);\n if (h2) { out.push('\\n' + c.bold.blue(h2[1])); continue; }\n\n const h3 = line.match(/^### (.+)/);\n if (h3) { out.push('\\n' + c.bold(h3[1])); continue; }\n\n const h4 = line.match(/^#### (.+)/);\n if (h4) { out.push(c.bold.underline(h4[1])); continue; }\n\n // --- Blockquotes / callouts ---\n if (line.startsWith('> ')) {\n out.push(c.yellow('▎ ') + renderInline(line.slice(2)));\n continue;\n }\n\n // --- Horizontal rule ---\n if (line === '---') {\n out.push(c.dim('─'.repeat(40)));\n continue;\n }\n\n // --- Frontmatter properties (key: value) ---\n const propMatch = line.match(/^([A-Za-z_][A-Za-z0-9_ ]*): (.+)$/);\n if (propMatch) {\n out.push(c.dim(propMatch[1] + ': ') + c.white(propMatch[2]));\n continue;\n }\n\n // --- Bullet list ---\n const bulletMatch = line.match(/^(\\s*)- (\\[[ x]\\] )?(.+)/);\n if (bulletMatch) {\n const indent = bulletMatch[1] ?? '';\n const checkbox = bulletMatch[2];\n const text = bulletMatch[3] ?? '';\n if (checkbox) {\n const checked = checkbox.trim() === '[x]';\n const box = checked ? c.green('☑') : c.dim('☐');\n out.push(indent + box + ' ' + renderInline(text));\n } else {\n out.push(indent + c.cyan('•') + ' ' + renderInline(text));\n }\n continue;\n }\n\n // --- Numbered list ---\n const numMatch = line.match(/^(\\s*)(\\d+)\\. (.+)/);\n if (numMatch) {\n const indent = numMatch[1] ?? '';\n const num = numMatch[2] ?? '';\n const text = numMatch[3] ?? '';\n out.push(indent + c.cyan(num + '.') + ' ' + renderInline(text));\n continue;\n }\n\n // --- Regular paragraph ---\n out.push(renderInline(line));\n }\n\n return out.join('\\n') + '\\n';\n}\n\n/** Apply inline markdown styles: bold, italic, code, strikethrough, links */\nfunction renderInline(text: string): string {\n // Use placeholders for inline code spans so other regexes don't touch their contents\n const codeSpans: string[] = [];\n let result = text.replace(/`([^`]+)`/g, (_, code) => {\n codeSpans.push(c.green(code));\n return `\\x00CODE${codeSpans.length - 1}\\x00`;\n });\n\n result = result\n // images (before links, since ![...] would match link pattern)\n .replace(/!\\[([^\\]]*)\\]\\([^)]+\\)/g, (_, alt) => alt ? c.dim(`[image: ${alt}]`) : c.dim('[image]'))\n // links [text](url)\n .replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (_, t, url) => c.cyan.underline(t) + c.dim(` (${url})`))\n // bold+italic\n .replace(/\\*\\*\\*(.+?)\\*\\*\\*/g, (_, t) => c.bold.italic(t))\n // bold\n .replace(/\\*\\*(.+?)\\*\\*/g, (_, t) => c.bold(t))\n // italic (both * and _)\n .replace(/(?<!\\*)\\*(?!\\*)(.+?)(?<!\\*)\\*(?!\\*)/g, (_, t) => c.italic(t))\n .replace(/(?<!_)_(?!_)(.+?)(?<!_)_(?!_)/g, (_, t) => c.italic(t))\n // strikethrough\n .replace(/~~(.+?)~~/g, (_, t) => c.strikethrough(t));\n\n // Restore code spans\n result = result.replace(/\\x00CODE(\\d+)\\x00/g, (_, i) => codeSpans[Number(i)] ?? '');\n\n return result;\n}\n","import { Command } from 'commander';\nimport { withErrorHandling } from '../../errors/error-handler.js';\nimport { resolveToken } from '../../config/token.js';\nimport { createNotionClient } from '../../notion/client.js';\nimport { parseNotionId } from '../../notion/url-parser.js';\nimport { fetchDatabaseSchema } from '../../services/database.service.js';\nimport { formatTable, formatJSON, isHumanMode } from '../../output/format.js';\n\nexport function dbSchemaCommand(): Command {\n return new Command('schema')\n .description('Show database schema (property names, types, and options)')\n .argument('<id>', 'Notion database ID or URL')\n .option('--json', 'Output raw JSON')\n .action(\n withErrorHandling(async (id: string, options: { json?: boolean }) => {\n const { token } = await resolveToken();\n const client = createNotionClient(token);\n const dbId = parseNotionId(id);\n const schema = await fetchDatabaseSchema(client, dbId);\n\n if (options.json) {\n process.stdout.write(formatJSON(schema) + '\\n');\n return;\n }\n\n // TTY: render as table — one row per property\n const headers = ['PROPERTY', 'TYPE', 'OPTIONS'];\n const rows = Object.values(schema.properties).map((prop) => [\n prop.name,\n prop.type,\n prop.options ? prop.options.map((o) => o.name).join(', ') : '',\n ]);\n process.stdout.write(formatTable(rows, headers) + '\\n');\n }),\n );\n}\n","import { Client, isFullPage } from '@notionhq/client';\nimport type {\n PageObjectResponse,\n QueryDataSourceParameters,\n} from '@notionhq/client/build/src/api-endpoints.js';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\nimport { paginateResults } from '../output/paginate.js';\n\nexport interface DatabaseSchema {\n id: string;\n title: string;\n // Property configs from schema — maps prop name to its type and options\n properties: Record<string, DatabasePropertyConfig>;\n}\n\nexport interface DatabasePropertyConfig {\n id: string;\n name: string;\n type: string; // 'select' | 'status' | 'number' | 'title' | 'rich_text' | 'date' | etc.\n // For select/status/multi_select: available options\n options?: Array<{ name: string; color?: string }>;\n}\n\nexport interface DatabaseEntry {\n id: string;\n // Property values — maps prop name to display string\n properties: Record<string, string>;\n // Raw page object for JSON output\n raw: PageObjectResponse;\n}\n\nexport interface DatabaseQueryOptions {\n filter?: QueryDataSourceParameters['filter'];\n sorts?: QueryDataSourceParameters['sorts'];\n // Subset of property names to include (undefined = all)\n columns?: string[];\n}\n\nexport async function fetchDatabaseSchema(\n client: Client,\n dbId: string,\n): Promise<DatabaseSchema> {\n // In Notion SDK v5, databases are exposed as \"data sources\"\n // client.dataSources.retrieve() returns DataSourceObjectResponse with .properties\n const ds = await client.dataSources.retrieve({ data_source_id: dbId });\n\n // Only full data sources have title and properties\n const title =\n 'title' in ds ? ds.title.map((rt) => rt.plain_text).join('') || dbId : dbId;\n\n const properties: Record<string, DatabasePropertyConfig> = {};\n\n if ('properties' in ds) {\n for (const [name, prop] of Object.entries(ds.properties)) {\n const config: DatabasePropertyConfig = {\n id: prop.id,\n name,\n type: prop.type,\n };\n // Extract options for enumerable types\n if (prop.type === 'select' && 'select' in prop) {\n config.options = prop.select.options;\n } else if (prop.type === 'status' && 'status' in prop) {\n config.options = prop.status.options;\n } else if (prop.type === 'multi_select' && 'multi_select' in prop) {\n config.options = prop.multi_select.options;\n }\n properties[name] = config;\n }\n }\n\n return { id: dbId, title, properties };\n}\n\nexport async function queryDatabase(\n client: Client,\n dbId: string,\n opts: DatabaseQueryOptions = {},\n): Promise<DatabaseEntry[]> {\n // In Notion SDK v5, querying a database uses client.dataSources.query()\n const rawPages = await paginateResults((cursor) =>\n client.dataSources.query({\n data_source_id: dbId,\n filter: opts.filter,\n sorts: opts.sorts,\n start_cursor: cursor,\n page_size: 100,\n }),\n );\n\n return rawPages.filter(isFullPage).map((page) => {\n const propValues: Record<string, string> = {};\n for (const [name, prop] of Object.entries(page.properties)) {\n // Skip columns not requested (if --columns specified)\n if (opts.columns && !opts.columns.includes(name)) continue;\n propValues[name] = displayPropertyValue(prop);\n }\n return { id: page.id, properties: propValues, raw: page };\n });\n}\n\nexport function buildFilter(\n filterStrings: string[],\n schema: DatabaseSchema,\n): QueryDataSourceParameters['filter'] | undefined {\n if (!filterStrings.length) return undefined;\n\n const filters = filterStrings.map((raw) => {\n const eqIdx = raw.indexOf('=');\n if (eqIdx === -1) {\n throw new CliError(\n ErrorCodes.INVALID_ARG,\n `Invalid filter syntax: \"${raw}\"`,\n 'Use format: --filter \"PropertyName=Value\"',\n );\n }\n const propName = raw.slice(0, eqIdx).trim();\n const value = raw.slice(eqIdx + 1).trim();\n const propConfig = schema.properties[propName];\n if (!propConfig) {\n const available = Object.keys(schema.properties).join(', ');\n throw new CliError(\n ErrorCodes.INVALID_ARG,\n `Property \"${propName}\" not found`,\n `Available properties: ${available}`,\n );\n }\n return buildPropertyFilter(propName, propConfig.type, value);\n });\n\n return filters.length === 1\n ? (filters[0] as QueryDataSourceParameters['filter'])\n : ({ and: filters } as QueryDataSourceParameters['filter']);\n}\n\nfunction buildPropertyFilter(\n property: string,\n type: string,\n value: string,\n): object {\n switch (type) {\n case 'select':\n return { property, select: { equals: value } };\n case 'status':\n return { property, status: { equals: value } };\n case 'multi_select':\n return { property, multi_select: { contains: value } };\n case 'checkbox':\n return { property, checkbox: { equals: value.toLowerCase() === 'true' } };\n case 'number':\n return { property, number: { equals: Number(value) } };\n case 'title':\n return { property, title: { contains: value } };\n case 'rich_text':\n return { property, rich_text: { contains: value } };\n case 'url':\n return { property, url: { contains: value } };\n case 'email':\n return { property, email: { contains: value } };\n default:\n throw new CliError(\n ErrorCodes.INVALID_ARG,\n `Filtering by property type \"${type}\" is not supported`,\n );\n }\n}\n\nexport function buildSorts(\n sortStrings: string[],\n): NonNullable<QueryDataSourceParameters['sorts']> {\n return sortStrings.map((raw) => {\n const colonIdx = raw.lastIndexOf(':');\n if (colonIdx === -1) {\n return { property: raw.trim(), direction: 'ascending' as const };\n }\n const property = raw.slice(0, colonIdx).trim();\n const dir = raw.slice(colonIdx + 1).trim().toLowerCase();\n return {\n property,\n direction:\n dir === 'desc' || dir === 'descending'\n ? ('descending' as const)\n : ('ascending' as const),\n };\n });\n}\n\nexport function displayPropertyValue(\n prop: PageObjectResponse['properties'][string],\n): string {\n switch (prop.type) {\n case 'title':\n return prop.title.map((r) => r.plain_text).join('').replace(/\\n/g, ' ');\n case 'rich_text':\n return prop.rich_text.map((r) => r.plain_text).join('').replace(/\\n/g, ' ');\n case 'number':\n return prop.number !== null && prop.number !== undefined\n ? String(prop.number)\n : '';\n case 'select':\n return prop.select?.name ?? '';\n case 'status':\n return prop.status?.name ?? '';\n case 'multi_select':\n return prop.multi_select.map((s) => s.name).join(', ');\n case 'date':\n return prop.date\n ? prop.date.end\n ? `${prop.date.start} → ${prop.date.end}`\n : prop.date.start\n : '';\n case 'checkbox':\n return prop.checkbox ? '✓' : '✗';\n case 'url':\n return prop.url ?? '';\n case 'email':\n return prop.email ?? '';\n case 'phone_number':\n return prop.phone_number ?? '';\n case 'people':\n return prop.people\n .map((p) => ('name' in p && p.name ? p.name : p.id))\n .join(', ');\n case 'relation':\n return prop.relation.length > 0 ? `[${prop.relation.length}]` : '';\n case 'formula': {\n const f = prop.formula;\n if (f.type === 'string') return f.string ?? '';\n if (f.type === 'number')\n return f.number !== null && f.number !== undefined\n ? String(f.number)\n : '';\n if (f.type === 'boolean') return f.boolean ? 'true' : 'false';\n if (f.type === 'date') return f.date?.start ?? '';\n return '';\n }\n case 'created_time':\n return prop.created_time;\n case 'last_edited_time':\n return prop.last_edited_time;\n case 'unique_id':\n return prop.unique_id.prefix\n ? `${prop.unique_id.prefix}-${prop.unique_id.number}`\n : String(prop.unique_id.number ?? '');\n default:\n return '';\n }\n}\n","import { Command } from 'commander';\nimport { withErrorHandling } from '../../errors/error-handler.js';\nimport { resolveToken } from '../../config/token.js';\nimport { createNotionClient } from '../../notion/client.js';\nimport { parseNotionId } from '../../notion/url-parser.js';\nimport {\n DatabaseSchema,\n fetchDatabaseSchema,\n queryDatabase,\n buildFilter,\n buildSorts,\n} from '../../services/database.service.js';\nimport { formatTable, formatJSON, isHumanMode } from '../../output/format.js';\n\n// Types that produce poor table output — skip in auto-column selection\nconst SKIP_TYPES_IN_AUTO = new Set(['relation', 'rich_text', 'people']);\n\n/**\n * Pick columns that fit within the terminal width.\n * - Skips relation/rich_text/people by default (noisy in tables)\n * - Stops adding columns once estimated width would exceed terminal width\n */\nfunction autoSelectColumns(schema: DatabaseSchema, entries: { properties: Record<string, string> }[]): string[] {\n const termWidth = process.stdout.columns || 120;\n const COL_SEP = 2; // two spaces between columns\n\n // Candidate columns: skip low-value types\n const candidates = Object.values(schema.properties)\n .filter((p) => !SKIP_TYPES_IN_AUTO.has(p.type))\n .map((p) => p.name);\n\n // Estimate each column's display width (max of header vs data)\n const widths = candidates.map((col) => {\n const header = col.toUpperCase().length;\n const maxData = entries.reduce((max, e) => Math.max(max, (e.properties[col] ?? '').length), 0);\n return Math.min(Math.max(header, maxData), 40); // respect DEFAULT_MAX_COL_WIDTH\n });\n\n // Greedily add columns until we'd exceed terminal width\n const selected: string[] = [];\n let usedWidth = 0;\n for (let i = 0; i < candidates.length; i++) {\n const needed = (selected.length > 0 ? COL_SEP : 0) + widths[i];\n if (usedWidth + needed > termWidth) break;\n selected.push(candidates[i]);\n usedWidth += needed;\n }\n\n // Always include at least the first column (title) even if it's wide\n if (selected.length === 0 && candidates.length > 0) {\n selected.push(candidates[0]);\n }\n\n return selected;\n}\n\nexport function dbQueryCommand(): Command {\n return new Command('query')\n .description('Query database entries with optional filtering and sorting')\n .argument('<id>', 'Notion database ID or URL')\n .option('--filter <filter>', 'Filter entries (repeatable): --filter \"Status=Done\"', collect, [])\n .option('--sort <sort>', 'Sort entries (repeatable): --sort \"Name:asc\"', collect, [])\n .option('--columns <columns>', 'Comma-separated list of columns to display: --columns \"Title,Status\"')\n .option('--json', 'Output raw JSON')\n .action(\n withErrorHandling(\n async (\n id: string,\n options: { filter: string[]; sort: string[]; columns?: string; json?: boolean },\n ) => {\n const { token } = await resolveToken();\n const client = createNotionClient(token);\n const dbId = parseNotionId(id);\n\n // Always fetch schema first (needed for filter building + column ordering)\n const schema = await fetchDatabaseSchema(client, dbId);\n\n const columns = options.columns\n ? options.columns.split(',').map((c) => c.trim())\n : undefined;\n\n const filter = options.filter.length\n ? buildFilter(options.filter, schema)\n : undefined;\n\n const sorts = options.sort.length ? buildSorts(options.sort) : undefined;\n\n const entries = await queryDatabase(client, dbId, { filter, sorts, columns });\n\n if (options.json) {\n process.stdout.write(formatJSON(entries.map((e) => e.raw)) + '\\n');\n return;\n }\n\n if (entries.length === 0) {\n process.stdout.write('No entries found.\\n');\n return;\n }\n\n // TTY: render as table\n // Use requested columns, or auto-select columns that fit the terminal\n const displayColumns = columns ?? autoSelectColumns(schema, entries);\n const headers = displayColumns.map((c) => c.toUpperCase());\n const rows = entries.map((entry) =>\n displayColumns.map((col) => entry.properties[col] ?? ''),\n );\n process.stdout.write(formatTable(rows, headers) + '\\n');\n process.stderr.write(`${entries.length} entries\\n`);\n },\n ),\n );\n}\n\n// Commander value collector helper for repeatable flags\nfunction collect(value: string, previous: string[]): string[] {\n return previous.concat([value]);\n}\n","import { Command } from 'commander';\nimport { parseNotionId, toUuid } from '../notion/url-parser.js';\nimport { resolveToken } from '../config/token.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { reportTokenSource } from '../output/stderr.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\nimport { addComment } from '../services/write.service.js';\n\nexport function commentAddCommand(): Command {\n const cmd = new Command('comment');\n\n cmd\n .description('add a comment to a Notion page')\n .argument('<id/url>', 'Notion page ID or URL')\n .requiredOption('-m, --message <text>', 'comment text to post')\n .action(withErrorHandling(async (idOrUrl: string, opts: { message: string }) => {\n const { token, source } = await resolveToken();\n reportTokenSource(source);\n const client = createNotionClient(token);\n\n const id = parseNotionId(idOrUrl);\n const uuid = toUuid(id);\n\n await addComment(client, uuid, opts.message, { asUser: source === 'oauth' });\n\n process.stdout.write('Comment added.\\n');\n }));\n\n return cmd;\n}\n","import { Client } from '@notionhq/client';\nimport type { BlockObjectRequest } from '@notionhq/client/build/src/api-endpoints.js';\n\nexport async function addComment(\n client: Client,\n pageId: string,\n text: string,\n options: { asUser?: boolean } = {},\n): Promise<void> {\n await client.comments.create({\n parent: { page_id: pageId },\n rich_text: [\n {\n type: 'text',\n text: { content: text, link: null },\n annotations: {\n bold: false,\n italic: false,\n strikethrough: false,\n underline: false,\n code: false,\n color: 'default',\n },\n },\n ],\n ...(options.asUser && { display_name: { type: 'user' } }),\n });\n}\n\nexport async function appendBlocks(\n client: Client,\n blockId: string,\n blocks: BlockObjectRequest[],\n): Promise<void> {\n await client.blocks.children.append({\n block_id: blockId,\n children: blocks,\n });\n}\n\nexport async function createPage(\n client: Client,\n parentId: string,\n title: string,\n blocks: BlockObjectRequest[],\n): Promise<string> {\n const response = await client.pages.create({\n parent: { type: 'page_id', page_id: parentId },\n properties: {\n title: {\n title: [{ type: 'text', text: { content: title, link: null } }],\n },\n },\n children: blocks,\n });\n return (response as { url: string }).url;\n}\n","import { Command } from 'commander';\nimport { parseNotionId, toUuid } from '../notion/url-parser.js';\nimport { resolveToken } from '../config/token.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { reportTokenSource } from '../output/stderr.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\nimport { mdToBlocks } from '../blocks/md-to-blocks.js';\nimport { appendBlocks } from '../services/write.service.js';\n\nexport function appendCommand(): Command {\n const cmd = new Command('append');\n\n cmd\n .description('append markdown content to a Notion page')\n .argument('<id/url>', 'Notion page ID or URL')\n .requiredOption('-m, --message <markdown>', 'markdown content to append')\n .action(withErrorHandling(async (idOrUrl: string, opts: { message: string }) => {\n const { token, source } = await resolveToken();\n reportTokenSource(source);\n const client = createNotionClient(token);\n\n const pageId = parseNotionId(idOrUrl);\n const uuid = toUuid(pageId);\n\n const blocks = mdToBlocks(opts.message);\n if (blocks.length === 0) {\n process.stdout.write('Nothing to append.\\n');\n return;\n }\n\n await appendBlocks(client, uuid, blocks);\n\n process.stdout.write(`Appended ${blocks.length} block(s).\\n`);\n }));\n\n return cmd;\n}\n","import type {\n BlockObjectRequest,\n RichTextItemRequest,\n} from '@notionhq/client/build/src/api-endpoints.js';\n\n// Inline regex: captures bold, italic (both * and _), inline code, links, and plain text\nconst INLINE_RE =\n /(\\*\\*[^*]+\\*\\*|_[^_]+_|\\*[^*]+\\*|`[^`]+`|\\[[^\\]]+\\]\\([^)]+\\)|[^*_`\\[]+)/g;\n\nexport function parseInlineMarkdown(text: string): RichTextItemRequest[] {\n const result: RichTextItemRequest[] = [];\n let match: RegExpExecArray | null;\n\n INLINE_RE.lastIndex = 0;\n\n while ((match = INLINE_RE.exec(text)) !== null) {\n const segment = match[0];\n\n // Bold: **text**\n if (segment.startsWith('**') && segment.endsWith('**')) {\n const content = segment.slice(2, -2);\n result.push({\n type: 'text',\n text: { content, link: null },\n annotations: { bold: true, italic: false, strikethrough: false, underline: false, code: false, color: 'default' },\n } as RichTextItemRequest);\n continue;\n }\n\n // Italic: _text_ or *text*\n if (\n (segment.startsWith('_') && segment.endsWith('_')) ||\n (segment.startsWith('*') && segment.endsWith('*'))\n ) {\n const content = segment.slice(1, -1);\n result.push({\n type: 'text',\n text: { content, link: null },\n annotations: { bold: false, italic: true, strikethrough: false, underline: false, code: false, color: 'default' },\n } as RichTextItemRequest);\n continue;\n }\n\n // Inline code: `text`\n if (segment.startsWith('`') && segment.endsWith('`')) {\n const content = segment.slice(1, -1);\n result.push({\n type: 'text',\n text: { content, link: null },\n annotations: { bold: false, italic: false, strikethrough: false, underline: false, code: true, color: 'default' },\n } as RichTextItemRequest);\n continue;\n }\n\n // Link: [label](url)\n const linkMatch = segment.match(/^\\[([^\\]]+)\\]\\(([^)]+)\\)$/);\n if (linkMatch) {\n const [, label, url] = linkMatch;\n result.push({\n type: 'text',\n text: { content: label, link: { url } },\n annotations: { bold: false, italic: false, strikethrough: false, underline: false, code: false, color: 'default' },\n } as RichTextItemRequest);\n continue;\n }\n\n // Plain text\n result.push({\n type: 'text',\n text: { content: segment, link: null },\n annotations: { bold: false, italic: false, strikethrough: false, underline: false, code: false, color: 'default' },\n } as RichTextItemRequest);\n }\n\n return result;\n}\n\nfunction makeRichText(text: string): RichTextItemRequest[] {\n return parseInlineMarkdown(text);\n}\n\nexport function mdToBlocks(md: string): BlockObjectRequest[] {\n if (!md) return [];\n\n const lines = md.split('\\n');\n const blocks: BlockObjectRequest[] = [];\n\n let inFence = false;\n let fenceLang = '';\n const fenceLines: string[] = [];\n\n for (const line of lines) {\n // Code fence start/end detection\n if (!inFence && line.startsWith('```')) {\n inFence = true;\n fenceLang = line.slice(3).trim() || 'plain text';\n fenceLines.length = 0;\n continue;\n }\n\n if (inFence) {\n if (line.startsWith('```')) {\n // End of code fence — emit code block\n const content = fenceLines.join('\\n');\n blocks.push({\n type: 'code',\n code: {\n rich_text: [\n {\n type: 'text',\n text: { content, link: null },\n annotations: { bold: false, italic: false, strikethrough: false, underline: false, code: false, color: 'default' },\n } as RichTextItemRequest,\n ],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n language: fenceLang as any,\n },\n } as BlockObjectRequest);\n inFence = false;\n fenceLang = '';\n fenceLines.length = 0;\n } else {\n fenceLines.push(line);\n }\n continue;\n }\n\n // Skip blank lines\n if (line.trim() === '') continue;\n\n // Heading 1: # text\n const h1 = line.match(/^# (.+)$/);\n if (h1) {\n blocks.push({\n type: 'heading_1',\n heading_1: { rich_text: makeRichText(h1[1]) },\n } as BlockObjectRequest);\n continue;\n }\n\n // Heading 2: ## text\n const h2 = line.match(/^## (.+)$/);\n if (h2) {\n blocks.push({\n type: 'heading_2',\n heading_2: { rich_text: makeRichText(h2[1]) },\n } as BlockObjectRequest);\n continue;\n }\n\n // Heading 3: ### text\n const h3 = line.match(/^### (.+)$/);\n if (h3) {\n blocks.push({\n type: 'heading_3',\n heading_3: { rich_text: makeRichText(h3[1]) },\n } as BlockObjectRequest);\n continue;\n }\n\n // Bulleted list item: - text or * text\n const bullet = line.match(/^[-*] (.+)$/);\n if (bullet) {\n blocks.push({\n type: 'bulleted_list_item',\n bulleted_list_item: { rich_text: makeRichText(bullet[1]) },\n } as BlockObjectRequest);\n continue;\n }\n\n // Numbered list item: 1. text\n const numbered = line.match(/^\\d+\\. (.+)$/);\n if (numbered) {\n blocks.push({\n type: 'numbered_list_item',\n numbered_list_item: { rich_text: makeRichText(numbered[1]) },\n } as BlockObjectRequest);\n continue;\n }\n\n // Quote: > text\n const quote = line.match(/^> (.+)$/);\n if (quote) {\n blocks.push({\n type: 'quote',\n quote: { rich_text: makeRichText(quote[1]) },\n } as BlockObjectRequest);\n continue;\n }\n\n // Default: paragraph\n blocks.push({\n type: 'paragraph',\n paragraph: { rich_text: makeRichText(line) },\n } as BlockObjectRequest);\n }\n\n // If we ended in a code fence (no closing ```), emit as code block anyway\n if (inFence && fenceLines.length > 0) {\n const content = fenceLines.join('\\n');\n blocks.push({\n type: 'code',\n code: {\n rich_text: [\n {\n type: 'text',\n text: { content, link: null },\n annotations: { bold: false, italic: false, strikethrough: false, underline: false, code: false, color: 'default' },\n } as RichTextItemRequest,\n ],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n language: fenceLang as any,\n },\n } as BlockObjectRequest);\n }\n\n return blocks;\n}\n","import { Command } from 'commander';\nimport { parseNotionId, toUuid } from '../notion/url-parser.js';\nimport { resolveToken } from '../config/token.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { reportTokenSource } from '../output/stderr.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\nimport { mdToBlocks } from '../blocks/md-to-blocks.js';\nimport { createPage } from '../services/write.service.js';\n\nasync function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n return Buffer.concat(chunks).toString('utf-8');\n}\n\nexport function createPageCommand(): Command {\n const cmd = new Command('create-page');\n\n cmd\n .description('create a new Notion page under a parent page')\n .requiredOption('--parent <id/url>', 'parent page ID or URL')\n .requiredOption('--title <title>', 'page title')\n .option('-m, --message <markdown>', 'inline markdown content for the page body')\n .action(withErrorHandling(async (opts: { parent: string; title: string; message?: string }) => {\n const { token, source } = await resolveToken();\n reportTokenSource(source);\n const client = createNotionClient(token);\n\n let markdown = '';\n if (opts.message) {\n markdown = opts.message;\n } else if (!process.stdin.isTTY) {\n markdown = await readStdin();\n }\n\n const blocks = mdToBlocks(markdown);\n const parentUuid = toUuid(parseNotionId(opts.parent));\n const url = await createPage(client, parentUuid, opts.title, blocks);\n\n process.stdout.write(url + '\\n');\n }));\n\n return cmd;\n}\n"],"mappings":"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","names":["Command","join","error","error","isNotionClientError","Command","Command","Command","Command","config","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","readFile","join","parse","join","readFile","parse","globalConfig","Command","Command","isFullPageOrDataSource","getTitle","displayType","Command","isFullPageOrDataSource","Command","input","Command","Command","Command","Command","Command","Command","url","Chalk","Chalk","Command","Command","isFullPage","isFullPage","Command","Command","Command","c","Command","Command","Command","Command","Command","Command","join","Command"]}
|