@andrzejchm/notion-cli 0.6.0 → 0.7.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 +10 -0
- package/dist/cli.js +262 -31
- package/dist/cli.js.map +1 -1
- package/docs/FEATURE-PARITY.md +189 -0
- package/docs/README.agents.md +42 -0
- package/docs/skills/using-notion-cli/SKILL.md +28 -18
- package/docs/testing-setup.md +250 -0
- package/package.json +5 -3
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/commands/append.ts","../src/errors/cli-error.ts","../src/errors/codes.ts","../src/oauth/oauth-client.ts","../src/config/config.ts","../src/config/paths.ts","../src/oauth/token-store.ts","../src/config/local-config.ts","../src/config/token.ts","../src/errors/error-handler.ts","../src/errors/notion-errors.ts","../src/notion/client.ts","../src/notion/url-parser.ts","../src/output/color.ts","../src/output/stderr.ts","../src/services/write.service.ts","../src/utils/stdin.ts","../src/commands/auth/index.ts","../src/commands/auth/login.ts","../src/oauth/oauth-flow.ts","../src/commands/auth/logout.ts","../src/commands/auth/status.ts","../src/commands/comment-add.ts","../src/commands/comments.ts","../src/output/format.ts","../src/output/paginate.ts","../src/commands/completion.ts","../src/commands/create-page.ts","../src/commands/db/query.ts","../src/services/database.service.ts","../src/commands/db/schema.ts","../src/commands/edit-page.ts","../src/commands/init.ts","../src/commands/ls.ts","../src/commands/open.ts","../src/commands/profile/list.ts","../src/commands/profile/remove.ts","../src/commands/profile/use.ts","../src/commands/read.ts","../src/output/markdown.ts","../src/services/page.service.ts","../src/commands/search.ts","../src/commands/users.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { Command } from 'commander';\nimport { appendCommand } from './commands/append.js';\nimport { authDefaultAction } from './commands/auth/index.js';\nimport { loginCommand } from './commands/auth/login.js';\nimport { logoutCommand } from './commands/auth/logout.js';\nimport { statusCommand } from './commands/auth/status.js';\nimport { commentAddCommand } from './commands/comment-add.js';\nimport { commentsCommand } from './commands/comments.js';\nimport { completionCommand } from './commands/completion.js';\nimport { createPageCommand } from './commands/create-page.js';\nimport { dbQueryCommand } from './commands/db/query.js';\nimport { dbSchemaCommand } from './commands/db/schema.js';\nimport { editPageCommand } from './commands/edit-page.js';\nimport { initCommand } from './commands/init.js';\nimport { lsCommand } from './commands/ls.js';\nimport { openCommand } from './commands/open.js';\nimport { profileListCommand } from './commands/profile/list.js';\nimport { profileRemoveCommand } from './commands/profile/remove.js';\nimport { profileUseCommand } from './commands/profile/use.js';\nimport { readCommand } from './commands/read.js';\nimport { searchCommand } from './commands/search.js';\nimport { usersCommand } from './commands/users.js';\nimport { setColorForced } from './output/color.js';\nimport { setOutputMode } from './output/format.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// Read version from package.json\nconst pkg = JSON.parse(\n readFileSync(join(__dirname, '../package.json'), 'utf-8'),\n) 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<{\n color?: boolean;\n verbose?: boolean;\n json?: boolean;\n md?: boolean;\n }>();\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 ---\n// auth subcommand group\nconst authCmd = new Command('auth').description('manage Notion authentication');\nauthCmd.action(authDefaultAction(authCmd)); // fires when no subcommand given\nauthCmd.addCommand(loginCommand());\nauthCmd.addCommand(logoutCommand());\nauthCmd.addCommand(statusCommand());\nauthCmd.addCommand(profileListCommand());\nauthCmd.addCommand(profileUseCommand());\nauthCmd.addCommand(profileRemoveCommand());\nprogram.addCommand(authCmd);\n\n// Backward-compat aliases (hidden from help)\nprogram.addCommand(initCommand(), { hidden: true });\n\nconst profileCmd = new Command('profile').description(\n 'manage authentication profiles',\n);\nprofileCmd.addCommand(profileListCommand());\nprofileCmd.addCommand(profileUseCommand());\nprofileCmd.addCommand(profileRemoveCommand());\nprogram.addCommand(profileCmd, { hidden: true });\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());\nprogram.addCommand(editPageCommand());\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 { Command } from 'commander';\nimport { resolveToken } from '../config/token.js';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\nimport {\n isNotionValidationError,\n SELECTOR_HINT,\n} from '../errors/notion-errors.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { parseNotionId, toUuid } from '../notion/url-parser.js';\nimport { reportTokenSource } from '../output/stderr.js';\nimport { appendMarkdown } from '../services/write.service.js';\nimport { readStdin } from '../utils/stdin.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 .option('-m, --message <markdown>', 'markdown content to append')\n .option(\n '--after <selector>',\n 'insert after matched content — ellipsis selector, e.g. \"## Section...end of section\"',\n )\n .action(\n withErrorHandling(\n async (idOrUrl: string, opts: { message?: string; after?: 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 } else {\n throw new CliError(\n ErrorCodes.INVALID_ARG,\n 'No content to append.',\n 'Pass markdown via -m/--message or pipe it through stdin',\n );\n }\n\n if (!markdown.trim()) {\n process.stdout.write('Nothing to append.\\n');\n return;\n }\n\n const pageId = parseNotionId(idOrUrl);\n const uuid = toUuid(pageId);\n\n try {\n await appendMarkdown(\n client,\n uuid,\n markdown,\n opts.after ? { after: opts.after } : undefined,\n );\n } catch (error) {\n if (opts.after && isNotionValidationError(error)) {\n // biome-ignore lint/nursery/useErrorCause: cause passed as 4th positional arg to CliError\n throw new CliError(\n ErrorCodes.INVALID_ARG,\n `Selector not found: \"${opts.after}\". ${(error as Error).message}`,\n SELECTOR_HINT,\n error,\n );\n }\n throw error;\n }\n\n process.stdout.write('Appended.\\n');\n },\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 cause?: unknown,\n ) {\n super(message, { cause });\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 { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\n\n// OAuth app credentials — XOR-encoded and split across arrays to avoid plain-text\n// indexing by grep, strings, GitHub code search, and automated secret scanners.\n// This is obfuscation, not encryption — per RFC 8252, client secrets in native\n// apps are not confidential. The real security boundary is Notion's redirect URI lock.\n// To regenerate chunks:\n// node -e \"\n// const key = 0x5a;\n// const val = 'YOUR_VALUE_HERE';\n// const enc = Buffer.from(val.split('').map(c => c.charCodeAt(0) ^ key)).toString('base64');\n// console.log(enc.match(/.{1,4}/g).map(c => \\`'\\${c}'\\`).join(', '));\n// \"\nconst _k = 0x5a;\nconst _d = (parts: string[]) =>\n Buffer.from(parts.join(''), 'base64')\n .toString()\n .split('')\n .map((c) => String.fromCharCode(c.charCodeAt(0) ^ _k))\n .join('');\n\nconst OAUTH_CLIENT_ID = _d([\n 'aWtu',\n 'PmJt',\n 'aDh3',\n 'b2Nu',\n 'OXdi',\n 'a2I+',\n 'd2I5',\n 'amh3',\n 'ampp',\n 'bTtj',\n 'Pm44',\n 'P2s8',\n]);\nconst OAUTH_CLIENT_SECRET = _d([\n 'KT85',\n 'KD8u',\n 'BWMM',\n 'axcx',\n 'P28P',\n 'ahYp',\n 'MCti',\n 'MQtt',\n 'Hj4V',\n 'NywV',\n 'I2sp',\n 'bzlv',\n 'ECIK',\n 'NTAx',\n 'IGwA',\n 'ETU7',\n 'ahU=',\n]);\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(\n 'base64',\n );\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 {\n error?: string;\n error_description?: string;\n };\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(\n refreshToken: string,\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: '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 {\n error?: string;\n error_description?: string;\n };\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 { mkdir, readFile, rename, writeFile } from 'node:fs/promises';\nimport { parse, stringify } from 'yaml';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\nimport type { GlobalConfig } from '../types/config.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 // biome-ignore lint/nursery/useErrorCause: cause passed as 4th positional arg to CliError\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 err,\n );\n }\n\n try {\n const parsed = parse(raw) as GlobalConfig;\n return parsed ?? {};\n } catch (err) {\n // biome-ignore lint/nursery/useErrorCause: cause passed as 4th positional arg to CliError\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 err,\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 (err) {\n // biome-ignore lint/nursery/useErrorCause: cause passed as 4th positional arg to CliError\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 err,\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 (err) {\n // biome-ignore lint/nursery/useErrorCause: cause passed as 4th positional arg to CliError\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 err,\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 { 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 && {\n oauth_user_id: response.owner.user.id,\n }),\n ...(response.owner?.user?.name != null && {\n oauth_user_name: response.owner.user.name,\n }),\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 { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { parse } from 'yaml';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\nimport type { LocalConfig } from '../types/config.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 // biome-ignore lint/nursery/useErrorCause: cause passed as 4th positional arg to CliError\n throw new CliError(\n ErrorCodes.CONFIG_READ_ERROR,\n `Failed to read local config: ${localConfigPath}`,\n 'Check file permissions',\n err,\n );\n }\n\n let parsed: LocalConfig;\n try {\n parsed = (parse(raw) as LocalConfig) ?? {};\n } catch (err) {\n // biome-ignore lint/nursery/useErrorCause: cause passed as 4th positional arg to CliError\n throw new CliError(\n ErrorCodes.CONFIG_INVALID,\n `Failed to parse .notion.yaml`,\n 'Check that the file contains valid YAML',\n err,\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 { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\nimport { refreshAccessToken } from '../oauth/oauth-client.js';\nimport { clearOAuthTokens, saveOAuthTokens } from '../oauth/token-store.js';\nimport type { ProfileConfig, TokenResult } from '../types/config.js';\nimport { readGlobalConfig } from './config.js';\nimport { readLocalConfig } from './local-config.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 (err) {\n await clearOAuthTokens(profileName);\n // biome-ignore lint/nursery/useErrorCause: cause passed as 4th positional arg to CliError\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 err,\n );\n }\n}\n\n/**\n * Resolves a token from a named profile, preferring OAuth over integration tokens.\n * Returns null if the profile has no usable token.\n */\nasync function resolveProfileToken(\n profileName: string,\n profile: ProfileConfig,\n): Promise<TokenResult | null> {\n const oauthToken = await resolveOAuthToken(profileName, profile);\n if (oauthToken) {\n return { token: oauthToken, source: 'oauth' };\n }\n if (profile.token) {\n return { token: profile.token, source: `profile: ${profileName}` };\n }\n return null;\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 const result = await resolveProfileToken(localConfig.profile, profile);\n if (result) return result;\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 const result = await resolveProfileToken(\n globalConfig.active_profile,\n profile,\n );\n if (result) return result;\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 { 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// biome-ignore lint/suspicious/noExplicitAny: generic wrapper must accept any argument list\nexport function withErrorHandling<T extends (...args: any[]) => Promise<void>>(\n fn: T,\n): 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","export const SELECTOR_HINT =\n 'Use an ellipsis selector matching page content, e.g. \"## Section...end of section\". Run `notion read <id>` to see the page content.';\n\nexport function isNotionValidationError(error: unknown): boolean {\n return (\n typeof error === 'object' &&\n error !== null &&\n 'code' in error &&\n (error as { code: unknown }).code === 'validation_error'\n );\n}\n","import { APIErrorCode, Client, 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 (\n isNotionClientError(error) &&\n error.code === APIErrorCode.Unauthorized\n ) {\n // biome-ignore lint/nursery/useErrorCause: cause passed as 4th positional arg to CliError\n throw new CliError(\n ErrorCodes.AUTH_INVALID,\n 'Invalid integration token.',\n 'Check your token at notion.so/profile/integrations/internal',\n error,\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 { 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 =\n /^[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 =\n /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 { 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","import type { CliError } from '../errors/cli-error.js';\nimport type { TokenResult } from '../types/config.js';\nimport { error as colorError, dim } 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 type { Client } from '@notionhq/client';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\n\nexport interface AppendOptions {\n /** Insert after this content selector instead of appending to the end. */\n after?: string;\n}\n\nexport interface ReplaceOptions {\n /** Use this content_range instead of auto-building one from the full page. */\n range?: string;\n /** Allow deleting content. Defaults to true for full-page, false for partial. */\n allowDeletingContent?: boolean;\n}\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\n/**\n * Appends markdown content to an existing Notion page using the native\n * PATCH /v1/pages/:id/markdown endpoint (insert_content mode).\n *\n * When `options.after` is provided, content is inserted after the matched\n * selector instead of at the end of the page.\n */\nexport async function appendMarkdown(\n client: Client,\n pageId: string,\n markdown: string,\n options?: AppendOptions,\n): Promise<void> {\n await client.pages.updateMarkdown({\n page_id: pageId,\n type: 'insert_content',\n insert_content: {\n content: markdown,\n ...(options?.after != null && { after: options.after }),\n },\n });\n}\n\n/**\n * Returns the number of non-overlapping occurrences of `sub` in `text`.\n */\nfunction countOccurrences(text: string, sub: string): number {\n if (!sub) return 0;\n let count = 0;\n let pos = text.indexOf(sub, 0);\n while (pos !== -1) {\n count++;\n pos = text.indexOf(sub, pos + sub.length);\n }\n return count;\n}\n\n/**\n * Builds a \"start...end\" content_range selector that uniquely identifies the\n * entire content of the page. Grows the end snippet until it appears exactly\n * once in the text, to avoid ambiguity with repeated structural elements\n * (e.g. multiple identical tables).\n */\nfunction buildContentRange(content: string): string {\n const START_LEN = 15;\n const STEP = 10;\n\n if (content.length <= START_LEN * 2) {\n return content;\n }\n\n const start = content.slice(0, START_LEN);\n\n for (\n let endLen = START_LEN;\n endLen < content.length - START_LEN;\n endLen += STEP\n ) {\n const end = content.slice(-endLen);\n if (countOccurrences(content, end) === 1) {\n return `${start}...${end}`;\n }\n }\n\n // Entire content is used as the range as a last resort\n return content;\n}\n\n/**\n * Replaces page content with the given markdown.\n *\n * When called without options, replaces the entire page (existing behavior).\n * When `options.range` is provided, uses it as the content_range for a\n * surgical partial replace.\n *\n * `allow_deleting_content` defaults to `true` for full-page replaces and\n * `false` for partial (range-scoped) replaces, but can be overridden via\n * `options.allowDeletingContent`.\n *\n * If the page is empty, falls back to insert_content regardless of options.\n */\nexport async function replaceMarkdown(\n client: Client,\n pageId: string,\n newMarkdown: string,\n options?: ReplaceOptions,\n): Promise<void> {\n const current = await client.pages.retrieveMarkdown({ page_id: pageId });\n const currentContent = current.markdown.trim();\n\n if (current.truncated && !options?.range) {\n throw new CliError(\n ErrorCodes.API_ERROR,\n 'Page content is too large for full-page replace (markdown was truncated by the API).',\n 'Use --range to replace a specific section instead.',\n );\n }\n\n if (!currentContent) {\n // Empty page — just insert (range is irrelevant)\n if (options?.range) {\n process.stderr.write(\n 'Warning: page is empty, --range ignored, content inserted as-is.\\n',\n );\n }\n if (newMarkdown.trim()) {\n await client.pages.updateMarkdown({\n page_id: pageId,\n type: 'insert_content',\n insert_content: { content: newMarkdown },\n });\n }\n return;\n }\n\n const contentRange = options?.range ?? buildContentRange(currentContent);\n const allowDeletingContent =\n options?.allowDeletingContent ?? options?.range == null;\n\n await client.pages.updateMarkdown({\n page_id: pageId,\n type: 'replace_content_range',\n replace_content_range: {\n content: newMarkdown,\n content_range: contentRange,\n allow_deleting_content: allowDeletingContent,\n },\n });\n}\n\n/**\n * Creates a new Notion page under a parent page with the given markdown content.\n *\n * Uses the native POST /v1/pages `markdown` field (server-side parsing).\n */\nexport async function createPage(\n client: Client,\n parentId: string,\n title: string,\n markdown: string,\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 ...(markdown.trim() ? { markdown } : {}),\n });\n const url = 'url' in response ? response.url : response.id;\n return url;\n}\n","export async 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","import type { Command } from 'commander';\n\n/**\n * Default action for `notion auth` (no subcommand) — show help.\n */\nexport function authDefaultAction(authCmd: Command): () => Promise<void> {\n return async () => {\n authCmd.help();\n };\n}\n","import { input } from '@inquirer/prompts';\nimport { Command } from 'commander';\nimport { readGlobalConfig, writeGlobalConfig } from '../../config/config.js';\nimport { CliError } from '../../errors/cli-error.js';\nimport { ErrorCodes } from '../../errors/codes.js';\nimport { withErrorHandling } from '../../errors/error-handler.js';\nimport { exchangeCode } from '../../oauth/oauth-client.js';\nimport { runOAuthFlow } from '../../oauth/oauth-flow.js';\nimport { saveOAuthTokens } from '../../oauth/token-store.js';\nimport { dim, success } from '../../output/color.js';\nimport { stderrWrite } from '../../output/stderr.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')\n .option('--profile <name>', 'profile name to store credentials in')\n .option(\n '--manual',\n 'print auth URL instead of opening browser (for headless OAuth)',\n )\n .action(\n withErrorHandling(async (opts: LoginOptions) => {\n if (!process.stdin.isTTY && !opts.manual) {\n throw new CliError(\n ErrorCodes.AUTH_NO_TOKEN,\n 'Cannot run interactive login in non-TTY mode.',\n 'Use --manual flag to get an auth URL you can open in a browser',\n );\n }\n\n const result = await runOAuthFlow({ manual: opts.manual });\n const response = await exchangeCode(result.code);\n\n const userName = response.owner?.user?.name ?? 'unknown user';\n const workspaceName = response.workspace_name ?? 'unknown workspace';\n\n const config = await readGlobalConfig();\n const existingProfiles = config.profiles ?? {};\n\n let profileName = opts.profile;\n if (!profileName) {\n const suggested =\n workspaceName\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '') || 'default';\n profileName = await input({\n message: 'Profile name to save this account under:',\n default: suggested,\n });\n }\n\n const isUpdate = Boolean(existingProfiles[profileName]);\n const isFirst = Object.keys(existingProfiles).length === 0;\n\n if (isUpdate) {\n stderrWrite(dim(`Updating existing profile \"${profileName}\"...`));\n }\n\n await saveOAuthTokens(profileName, response);\n\n // Set as active if it's the first profile saved\n if (isFirst) {\n const updated = await readGlobalConfig();\n await writeGlobalConfig({\n ...updated,\n active_profile: profileName,\n });\n }\n\n stderrWrite(\n success(`✓ Logged in as ${userName} to workspace ${workspaceName}`),\n );\n stderrWrite(dim(`Saved as profile \"${profileName}\".`));\n if (!isFirst && !isUpdate) {\n stderrWrite(\n dim(\n `Run \"notion auth use ${profileName}\" to switch to this profile.`,\n ),\n );\n }\n stderrWrite(\n dim(\n 'Your comments and pages will now be attributed to your Notion account.',\n ),\n );\n }),\n );\n\n return cmd;\n}\n","import { spawn } from 'node:child_process';\nimport { randomBytes } from 'node:crypto';\nimport {\n createServer,\n type IncomingMessage,\n type ServerResponse,\n} from 'node:http';\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\ninterface CallbackContext {\n expectedState: string;\n settled: boolean;\n timeoutHandle: ReturnType<typeof setTimeout> | null;\n resolve: (result: OAuthFlowResult) => void;\n reject: (err: unknown) => void;\n server: ReturnType<typeof createServer>;\n sockets: Set<import('node:net').Socket>;\n}\n\nfunction closeServer(ctx: CallbackContext, cb: () => void): void {\n for (const socket of ctx.sockets) {\n socket.destroy();\n }\n ctx.sockets.clear();\n ctx.server.close(cb);\n}\n\nfunction handleCallbackRequest(\n req: IncomingMessage,\n res: ServerResponse,\n ctx: CallbackContext,\n): void {\n if (ctx.settled) {\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(\n '<html><body><h1>Already handled. You can close this tab.</h1></body></html>',\n );\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 ctx.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 (ctx.timeoutHandle) clearTimeout(ctx.timeoutHandle);\n closeServer(ctx, () => {\n ctx.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 !== ctx.expectedState) {\n ctx.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 (ctx.timeoutHandle) clearTimeout(ctx.timeoutHandle);\n closeServer(ctx, () => {\n ctx.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 ctx.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 (ctx.timeoutHandle) clearTimeout(ctx.timeoutHandle);\n closeServer(ctx, () => {\n ctx.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/**\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?: {\n manual?: boolean;\n}): Promise<OAuthFlowResult> {\n const state = randomBytes(16).toString('hex');\n const authUrl = buildAuthUrl(state);\n\n if (options?.manual) {\n return manualFlow(authUrl);\n }\n\n return new Promise<OAuthFlowResult>((resolve, reject) => {\n const ctx: CallbackContext = {\n expectedState: state,\n settled: false,\n timeoutHandle: null,\n resolve,\n reject,\n // assigned below after server is created\n server: null as unknown as ReturnType<typeof createServer>,\n sockets: new Set(),\n };\n\n const server = createServer((req, res) =>\n handleCallbackRequest(req, res, ctx),\n );\n ctx.server = server;\n\n server.on('connection', (socket) => {\n ctx.sockets.add(socket);\n socket.once('close', () => ctx.sockets.delete(socket));\n });\n\n server.on('error', (err) => {\n if (ctx.settled) return;\n ctx.settled = true;\n if (ctx.timeoutHandle) clearTimeout(ctx.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 const browserOpened = openBrowser(authUrl);\n\n if (!browserOpened) {\n server.close();\n ctx.settled = true;\n if (ctx.timeoutHandle) clearTimeout(ctx.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 ctx.timeoutHandle = setTimeout(() => {\n if (ctx.settled) return;\n ctx.settled = true;\n closeServer(ctx, () => {\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 { select } from '@inquirer/prompts';\nimport { Command } from 'commander';\nimport { readGlobalConfig, writeGlobalConfig } from '../../config/config.js';\nimport { CliError } from '../../errors/cli-error.js';\nimport { ErrorCodes } from '../../errors/codes.js';\nimport { withErrorHandling } from '../../errors/error-handler.js';\nimport { bold, dim, success } from '../../output/color.js';\nimport { stderrWrite } from '../../output/stderr.js';\n\ninterface LogoutOptions {\n profile?: string;\n}\n\nfunction profileLabel(\n name: string,\n profile: {\n token?: string;\n oauth_access_token?: string;\n oauth_user_name?: string;\n workspace_name?: string;\n },\n): string {\n const parts: string[] = [];\n if (profile.oauth_access_token)\n parts.push(\n `OAuth${profile.oauth_user_name ? ` (${profile.oauth_user_name})` : ''}`,\n );\n if (profile.token) parts.push('integration token');\n const authDesc = parts.length > 0 ? parts.join(' + ') : 'no credentials';\n const workspace = profile.workspace_name\n ? dim(` — ${profile.workspace_name}`)\n : '';\n return `${bold(name)} ${dim(authDesc)}${workspace}`;\n}\n\nexport function logoutCommand(): Command {\n const cmd = new Command('logout');\n\n cmd\n .description('remove a profile and its credentials')\n .option(\n '--profile <name>',\n 'profile name to remove (skips interactive selector)',\n )\n .action(\n withErrorHandling(async (opts: LogoutOptions) => {\n const config = await readGlobalConfig();\n const profiles = config.profiles ?? {};\n const profileNames = Object.keys(profiles);\n\n if (profileNames.length === 0) {\n stderrWrite('No profiles configured.');\n return;\n }\n\n let profileName = opts.profile;\n\n if (!profileName) {\n if (!process.stdin.isTTY) {\n throw new CliError(\n ErrorCodes.AUTH_NO_TOKEN,\n 'Cannot run interactive logout in non-TTY mode.',\n 'Use --profile <name> to specify the profile to remove',\n );\n }\n\n profileName = await select({\n message: 'Which profile do you want to log out of?',\n choices: profileNames.map((name) => ({\n // biome-ignore lint/style/noNonNullAssertion: key is from Object.keys, always present\n name: profileLabel(name, profiles[name]!),\n value: name,\n })),\n });\n }\n\n if (!profiles[profileName]) {\n throw new CliError(\n ErrorCodes.AUTH_PROFILE_NOT_FOUND,\n `Profile \"${profileName}\" not found.`,\n `Run \"notion auth list\" to see available profiles`,\n );\n }\n\n const updatedProfiles = { ...profiles };\n delete updatedProfiles[profileName];\n\n const newActiveProfile =\n config.active_profile === profileName\n ? undefined\n : config.active_profile;\n\n await writeGlobalConfig({\n ...config,\n profiles: updatedProfiles,\n active_profile: newActiveProfile,\n });\n\n stderrWrite(success(`✓ Logged out of profile \"${profileName}\".`));\n if (\n newActiveProfile === undefined &&\n Object.keys(updatedProfiles).length > 0\n ) {\n stderrWrite(\n dim(`Run \"notion auth use <name>\" to set a new active profile.`),\n );\n }\n }),\n );\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { readGlobalConfig } from '../../config/config.js';\nimport { withErrorHandling } from '../../errors/error-handler.js';\nimport { error as colorError, dim, success } from '../../output/color.js';\nimport { stderrWrite } from '../../output/stderr.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(\n ` ${colorError('✗')} No profile found (run 'notion init' to create one)`,\n );\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(\n ` OAuth: ${success('✓')} Logged in as ${userName} (user: ${userId})`,\n );\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(\n ` Internal token: ${success('✓')} Configured (${tokenPreview})`,\n );\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(\n ` Active method: Internal integration token (bot-attributed)`,\n );\n } else {\n stderrWrite(\n dim(\n ` Active method: None (run 'notion auth login' or 'notion init')`,\n ),\n );\n }\n }),\n );\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { resolveToken } from '../config/token.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { parseNotionId, toUuid } from '../notion/url-parser.js';\nimport { reportTokenSource } from '../output/stderr.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(\n 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, {\n asUser: source === 'oauth',\n });\n\n process.stdout.write('Comment added.\\n');\n }),\n );\n\n return cmd;\n}\n","import type { CommentObjectResponse } from '@notionhq/client/build/src/api-endpoints.js';\nimport { Command } from 'commander';\nimport { resolveToken } from '../config/token.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { parseNotionId, toUuid } from '../notion/url-parser.js';\nimport { printOutput, setOutputMode } from '../output/format.js';\nimport { paginateResults } from '../output/paginate.js';\nimport { reportTokenSource } from '../output/stderr.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(\n 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\n return cmd;\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.map((h, i) => h.padEnd(colWidths[i])).join(colSep);\n\n // Build separator row\n const separatorRow = colWidths.map((w) => sep.repeat(w)).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","export async function paginateResults<T>(\n fetcher: (\n cursor?: string,\n ) => 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 { 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(\n 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\n return cmd;\n}\n","import { Command } from 'commander';\nimport { resolveToken } from '../config/token.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { parseNotionId, toUuid } from '../notion/url-parser.js';\nimport { reportTokenSource } from '../output/stderr.js';\nimport { createPage } from '../services/write.service.js';\nimport { readStdin } from '../utils/stdin.js';\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(\n '-m, --message <markdown>',\n 'inline markdown content for the page body',\n )\n .action(\n withErrorHandling(\n 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 parentUuid = toUuid(parseNotionId(opts.parent));\n const url = await createPage(\n client,\n parentUuid,\n opts.title,\n markdown,\n );\n\n process.stdout.write(`${url}\\n`);\n },\n ),\n );\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { resolveToken } from '../../config/token.js';\nimport { withErrorHandling } from '../../errors/error-handler.js';\nimport { createNotionClient } from '../../notion/client.js';\nimport { parseNotionId } from '../../notion/url-parser.js';\nimport { formatJSON, formatTable } from '../../output/format.js';\nimport {\n buildFilter,\n buildSorts,\n type DatabaseSchema,\n fetchDatabaseSchema,\n queryDatabase,\n} from '../../services/database.service.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(\n schema: DatabaseSchema,\n entries: { properties: Record<string, string> }[],\n): 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(\n (max, e) => Math.max(max, (e.properties[col] ?? '').length),\n 0,\n );\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(\n '--filter <filter>',\n 'Filter entries (repeatable): --filter \"Status=Done\"',\n collect,\n [],\n )\n .option(\n '--sort <sort>',\n 'Sort entries (repeatable): --sort \"Name:asc\"',\n collect,\n [],\n )\n .option(\n '--columns <columns>',\n 'Comma-separated list of columns to display: --columns \"Title,Status\"',\n )\n .option('--json', 'Output raw JSON')\n .action(\n withErrorHandling(\n async (\n id: string,\n options: {\n filter: string[];\n sort: string[];\n columns?: string;\n json?: boolean;\n },\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\n ? buildSorts(options.sort)\n : undefined;\n\n const entries = await queryDatabase(client, dbId, {\n filter,\n sorts,\n columns,\n });\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 { type 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\n .slice(colonIdx + 1)\n .trim()\n .toLowerCase();\n return {\n property,\n direction:\n dir === 'desc' || dir === 'descending'\n ? ('descending' as const)\n : ('ascending' as const),\n };\n });\n}\n\ntype PropValue = PageObjectResponse['properties'][string];\ntype FormulaValue = Extract<PropValue, { type: 'formula' }>['formula'];\n\nfunction displayFormula(f: FormulaValue): string {\n if (f.type === 'string') return f.string ?? '';\n if (f.type === 'number')\n return f.number !== null && f.number !== undefined ? String(f.number) : '';\n if (f.type === 'boolean') return f.boolean ? 'true' : 'false';\n if (f.type === 'date') return f.date?.start ?? '';\n return '';\n}\n\nfunction displayDate(\n date: { start: string; end: string | null } | null,\n): string {\n if (!date) return '';\n return date.end ? `${date.start} → ${date.end}` : date.start;\n}\n\nexport function displayPropertyValue(prop: PropValue): string {\n switch (prop.type) {\n case 'title':\n return prop.title\n .map((r) => r.plain_text)\n .join('')\n .replace(/\\n/g, ' ');\n case 'rich_text':\n return prop.rich_text\n .map((r) => r.plain_text)\n .join('')\n .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 displayDate(prop.date);\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 return displayFormula(prop.formula);\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 { resolveToken } from '../../config/token.js';\nimport { withErrorHandling } from '../../errors/error-handler.js';\nimport { createNotionClient } from '../../notion/client.js';\nimport { parseNotionId } from '../../notion/url-parser.js';\nimport { formatJSON, formatTable } from '../../output/format.js';\nimport { fetchDatabaseSchema } from '../../services/database.service.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 { Command } from 'commander';\nimport { resolveToken } from '../config/token.js';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\nimport {\n isNotionValidationError,\n SELECTOR_HINT,\n} from '../errors/notion-errors.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { parseNotionId, toUuid } from '../notion/url-parser.js';\nimport { reportTokenSource } from '../output/stderr.js';\nimport { replaceMarkdown } from '../services/write.service.js';\nimport { readStdin } from '../utils/stdin.js';\n\ninterface EditPageOpts {\n message?: string;\n range?: string;\n allowDeletingContent?: boolean;\n}\n\nexport function editPageCommand(): Command {\n const cmd = new Command('edit-page');\n\n cmd\n .description(\n \"replace a Notion page's content \\u2014 full page or a targeted section\",\n )\n .argument('<id/url>', 'Notion page ID or URL')\n .option(\n '-m, --message <markdown>',\n 'new markdown content for the page body',\n )\n .option(\n '--range <selector>',\n 'ellipsis selector to replace only a section, e.g. \"## My Section...last line\"',\n )\n .option(\n '--allow-deleting-content',\n 'allow deletion when using --range (always true for full-page replace)',\n )\n .action(\n withErrorHandling(async (idOrUrl: string, opts: EditPageOpts) => {\n const { token, source } = await resolveToken();\n reportTokenSource(source);\n const client = createNotionClient(token);\n\n if (opts.allowDeletingContent && !opts.range) {\n process.stderr.write(\n 'Warning: --allow-deleting-content has no effect without --range (full-page replace always allows deletion).\\n',\n );\n }\n\n let markdown = '';\n if (opts.message) {\n markdown = opts.message;\n } else if (!process.stdin.isTTY) {\n // Stricter than `append` — empty content would wipe the page, so we reject it.\n markdown = await readStdin();\n if (!markdown.trim()) {\n throw new CliError(\n ErrorCodes.INVALID_ARG,\n 'No content provided (stdin was empty).',\n 'Pass markdown via -m/--message or pipe non-empty content through stdin',\n );\n }\n } else {\n throw new CliError(\n ErrorCodes.INVALID_ARG,\n 'No content provided.',\n 'Pass markdown via -m/--message or pipe it through stdin',\n );\n }\n\n const pageId = parseNotionId(idOrUrl);\n const uuid = toUuid(pageId);\n\n try {\n if (opts.range) {\n await replaceMarkdown(client, uuid, markdown, {\n range: opts.range,\n allowDeletingContent: opts.allowDeletingContent ?? false,\n });\n } else {\n await replaceMarkdown(client, uuid, markdown);\n }\n } catch (error) {\n if (opts.range && isNotionValidationError(error)) {\n // biome-ignore lint/nursery/useErrorCause: cause passed as 4th positional arg to CliError\n throw new CliError(\n ErrorCodes.INVALID_ARG,\n `Selector not found: \"${opts.range}\". ${(error as Error).message}`,\n SELECTOR_HINT,\n error,\n );\n }\n throw error;\n }\n\n process.stdout.write('Page content replaced.\\n');\n }),\n );\n\n return cmd;\n}\n","import { confirm, input, password } from '@inquirer/prompts';\nimport { Command } from 'commander';\nimport { readGlobalConfig, writeGlobalConfig } from '../config/config.js';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\nimport { createNotionClient, validateToken } from '../notion/client.js';\nimport { bold, dim, success } from '../output/color.js';\nimport { stderrWrite } from '../output/stderr.js';\n\n/**\n * Pure flow function: prompt for integration token, validate, save profile.\n * Caller is responsible for TTY guarding before calling this function.\n */\nexport async function runInitFlow(): Promise<void> {\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:\n '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(\n success(\n `✓ Integration has access to content in ${bold(workspaceName)}.`,\n ),\n );\n }\n } catch {\n // Non-fatal — don't block init if the probe fails for any reason\n stderrWrite(\n dim('(Could not verify integration access — run `notion ls` to check)'),\n );\n }\n\n stderrWrite('');\n stderrWrite(\n dim('Write commands (comment, append, create-page) require additional'),\n );\n stderrWrite(dim('capabilities in your integration settings:'));\n stderrWrite(\n dim(' notion.so/profile/integrations/internal → your integration →'),\n );\n stderrWrite(\n dim(\n ' Capabilities: enable \"Read content\", \"Insert content\", \"Read comments\", \"Insert comments\"',\n ),\n );\n stderrWrite('');\n stderrWrite(\n dim('To post comments and create pages attributed to your user account:'),\n );\n stderrWrite(dim(' notion auth login'));\n}\n\nexport function initCommand(): Command {\n const cmd = new Command('init');\n\n cmd.description('authenticate with Notion and save a profile').action(\n 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 await runInitFlow();\n }),\n );\n\n return cmd;\n}\n","import { isFullPageOrDataSource } from '@notionhq/client';\nimport type {\n DataSourceObjectResponse,\n PageObjectResponse,\n} from '@notionhq/client/build/src/api-endpoints.js';\nimport { Command } from 'commander';\nimport { resolveToken } from '../config/token.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { printOutput, setOutputMode } from '../output/format.js';\nimport { reportTokenSource } from '../output/stderr.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(\n (p) => p.type === 'title',\n );\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(\n item: PageObjectResponse | DataSourceObjectResponse,\n): 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(\n '--type <type>',\n 'filter by object type (page or database)',\n (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 )\n .option(\n '--cursor <cursor>',\n 'start from this pagination cursor (from a previous --next hint)',\n )\n .option('--json', 'force JSON output')\n .action(\n withErrorHandling(\n async (opts: {\n type?: 'page' | 'database';\n cursor?: string;\n json?: boolean;\n }) => {\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) =>\n isFullPageOrDataSource(r),\n ) as (PageObjectResponse | DataSourceObjectResponse)[];\n\n if (opts.type) {\n const filterType = opts.type;\n items = items.filter((r) =>\n filterType === 'database'\n ? r.object === 'data_source'\n : 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 `\\n --next: notion ls --cursor ${response.next_cursor}\\n`,\n );\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 { withErrorHandling } from '../errors/error-handler.js';\nimport { parseNotionId } from '../notion/url-parser.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(\n 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'\n ? 'open'\n : platform === 'win32'\n ? 'start'\n : 'xdg-open'; // Linux\n\n await execAsync(`${opener} \"${url}\"`);\n process.stdout.write(`Opening ${url}\\n`);\n }),\n );\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { readGlobalConfig } from '../../config/config.js';\nimport { withErrorHandling } from '../../errors/error-handler.js';\nimport { bold, dim } from '../../output/color.js';\n\nexport function profileListCommand(): Command {\n const cmd = new Command('list');\n\n cmd.description('list all authentication profiles').action(\n 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(\n 'No profiles configured. Run `notion auth login` to get started.\\n',\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\n ? dim(` — ${profile.workspace_name}`)\n : '';\n\n process.stdout.write(\n `${marker}${name}${activeLabel}${workspaceInfo}\\n`,\n );\n }\n }),\n );\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { readGlobalConfig, writeGlobalConfig } from '../../config/config.js';\nimport { CliError } from '../../errors/cli-error.js';\nimport { ErrorCodes } from '../../errors/codes.js';\nimport { withErrorHandling } from '../../errors/error-handler.js';\nimport { success } from '../../output/color.js';\nimport { stderrWrite } from '../../output/stderr.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(\n 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 auth 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\n return cmd;\n}\n","import { Command } from 'commander';\nimport { readGlobalConfig, writeGlobalConfig } from '../../config/config.js';\nimport { CliError } from '../../errors/cli-error.js';\nimport { ErrorCodes } from '../../errors/codes.js';\nimport { withErrorHandling } from '../../errors/error-handler.js';\nimport { success } from '../../output/color.js';\nimport { stderrWrite } from '../../output/stderr.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(\n 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 auth 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\n return cmd;\n}\n","import { Command } from 'commander';\nimport { resolveToken } from '../config/token.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { parseNotionId } from '../notion/url-parser.js';\nimport { getOutputMode, isatty } from '../output/format.js';\nimport { renderMarkdown } from '../output/markdown.js';\nimport { fetchPageMarkdown } from '../services/page.service.js';\n\nexport function readCommand(): Command {\n return (\n new Command('read')\n .description('Read a Notion page as markdown')\n .argument('<id>', 'Notion page ID or URL')\n // Note: --json and --md are inherited from the root program global options.\n // Do NOT redefine them here — Commander routes them to the root program,\n // which sets the output mode via the preAction hook. Read them via getOutputMode().\n .action(\n withErrorHandling(async (id: string) => {\n const { token } = await resolveToken();\n const client = createNotionClient(token);\n const pageId = parseNotionId(id);\n const pageWithMarkdown = await fetchPageMarkdown(client, pageId);\n\n const mode = getOutputMode();\n if (mode === 'json') {\n process.stdout.write(\n `${JSON.stringify(pageWithMarkdown, null, 2)}\\n`,\n );\n } else {\n const { markdown } = pageWithMarkdown;\n if (mode === 'md' || !isatty()) {\n // Raw markdown — piped output or explicit --md flag\n process.stdout.write(markdown);\n } else {\n // TTY: render with terminal styling\n process.stdout.write(renderMarkdown(markdown));\n }\n }\n }),\n )\n );\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\ninterface FenceState {\n inFence: boolean;\n fenceLang: string;\n fenceLines: string[];\n}\n\n/** Returns non-null if `line` opens or closes a fenced code block. */\nfunction handleFenceLine(\n line: string,\n state: FenceState,\n out: string[],\n): boolean {\n const fenceMatch = line.match(/^```(\\w*)$/);\n if (fenceMatch && !state.inFence) {\n state.inFence = true;\n state.fenceLang = fenceMatch[1] ?? '';\n state.fenceLines = [];\n return true;\n }\n if (line === '```' && state.inFence) {\n state.inFence = false;\n const header = state.fenceLang ? c.dim(`[${state.fenceLang}]`) : '';\n if (header) out.push(header);\n for (const fl of state.fenceLines) {\n out.push(c.green(` ${fl}`));\n }\n out.push('');\n return true;\n }\n return false;\n}\n\nfunction handleHeading(line: string, out: string[]): boolean {\n const h1 = line.match(/^# (.+)/);\n if (h1) {\n out.push(`\\n${c.bold.cyan(h1[1])}`);\n return true;\n }\n const h2 = line.match(/^## (.+)/);\n if (h2) {\n out.push(`\\n${c.bold.blue(h2[1])}`);\n return true;\n }\n const h3 = line.match(/^### (.+)/);\n if (h3) {\n out.push(`\\n${c.bold(h3[1])}`);\n return true;\n }\n const h4 = line.match(/^#### (.+)/);\n if (h4) {\n out.push(c.bold.underline(h4[1]));\n return true;\n }\n return false;\n}\n\nfunction handleListLine(line: string, out: string[]): boolean {\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 return true;\n }\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 return true;\n }\n return false;\n}\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 const fence: FenceState = { inFence: false, fenceLang: '', fenceLines: [] };\n\n for (const line of lines) {\n if (handleFenceLine(line, fence, out)) continue;\n\n if (fence.inFence) {\n fence.fenceLines.push(line);\n continue;\n }\n\n // YAML frontmatter separator / horizontal rule\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())) continue;\n\n if (handleHeading(line, out)) continue;\n\n // Blockquotes / callouts\n if (line.startsWith('> ')) {\n out.push(c.yellow('▎ ') + renderInline(line.slice(2)));\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 if (handleListLine(line, out)) continue;\n\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) =>\n alt ? c.dim(`[image: ${alt}]`) : c.dim('[image]'),\n )\n // links [text](url)\n .replace(\n /\\[([^\\]]+)\\]\\(([^)]+)\\)/g,\n (_, t, url) => c.cyan.underline(t) + c.dim(` (${url})`),\n )\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 — \\x00 is used intentionally as a sentinel character\n result = result.replace(\n // biome-ignore lint/suspicious/noControlCharactersInRegex: sentinel chars are intentional\n /\\x00CODE(\\d+)\\x00/g,\n (_, i) => codeSpans[Number(i)] ?? '',\n );\n\n return result;\n}\n","import type { Client } from '@notionhq/client';\nimport type { PageObjectResponse } from '@notionhq/client/build/src/api-endpoints.js';\n\nexport interface PageWithMarkdown {\n page: PageObjectResponse;\n markdown: string;\n}\n\n/**\n * Fetches a page's metadata and its content as markdown using the native\n * Notion markdown endpoint (GET /v1/pages/:id/markdown).\n */\nexport async function fetchPageMarkdown(\n client: Client,\n pageId: string,\n): Promise<PageWithMarkdown> {\n const [page, markdownResponse] = await Promise.all([\n client.pages.retrieve({ page_id: pageId }) as Promise<PageObjectResponse>,\n client.pages.retrieveMarkdown({ page_id: pageId }),\n ]);\n\n return { page, markdown: markdownResponse.markdown };\n}\n","import { isFullPageOrDataSource } from '@notionhq/client';\nimport type {\n DataSourceObjectResponse,\n PageObjectResponse,\n} from '@notionhq/client/build/src/api-endpoints.js';\nimport { Command } from 'commander';\nimport { resolveToken } from '../config/token.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { printOutput, setOutputMode } from '../output/format.js';\nimport { reportTokenSource } from '../output/stderr.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(\n (p) => p.type === 'title',\n );\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(\n item: PageObjectResponse | DataSourceObjectResponse,\n): 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(\n '--type <type>',\n 'filter by object type (page or database)',\n (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 )\n .option(\n '--cursor <cursor>',\n 'start from this pagination cursor (from a previous --next hint)',\n )\n .option('--json', 'force JSON output')\n .action(\n withErrorHandling(\n async (\n query: string,\n opts: { type?: 'page' | 'database'; cursor?: string; json?: boolean },\n ) => {\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) =>\n isFullPageOrDataSource(r),\n ) as (PageObjectResponse | DataSourceObjectResponse)[];\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 `\\n --next: notion search \"${query}\" --cursor ${response.next_cursor}\\n`,\n );\n }\n },\n ),\n );\n\n return cmd;\n}\n","import type { UserObjectResponse } from '@notionhq/client/build/src/api-endpoints.js';\nimport { Command } from 'commander';\nimport { resolveToken } from '../config/token.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { printOutput, setOutputMode } from '../output/format.js';\nimport { paginateResults } from '../output/paginate.js';\nimport { reportTokenSource } from '../output/stderr.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\n | { workspace_name?: string | null }\n | Record<string, never>;\n return 'workspace_name' in bot && bot.workspace_name\n ? bot.workspace_name\n : '—';\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(\n 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(\n (u) => u.name !== undefined,\n );\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\n return cmd;\n}\n"],"mappings":"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","names":["join","Command","c","readFile","join","parse","join","readFile","parse","globalConfig","error","isNotionClientError","error","error","input","error","authCmd","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","c","Command","Command","Command","Command","error","input","Command","input","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Chalk","Chalk","Command","isFullPageOrDataSource","Command","getTitle","displayType","Command","isFullPageOrDataSource","Command","Command","join","Command"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/commands/append.ts","../src/errors/cli-error.ts","../src/errors/codes.ts","../src/oauth/oauth-client.ts","../src/config/config.ts","../src/config/paths.ts","../src/oauth/token-store.ts","../src/config/local-config.ts","../src/config/token.ts","../src/errors/error-handler.ts","../src/errors/notion-errors.ts","../src/notion/client.ts","../src/notion/url-parser.ts","../src/output/color.ts","../src/output/stderr.ts","../src/services/write.service.ts","../src/utils/stdin.ts","../src/commands/auth/index.ts","../src/commands/auth/login.ts","../src/oauth/oauth-flow.ts","../src/commands/auth/logout.ts","../src/commands/auth/status.ts","../src/commands/comment-add.ts","../src/commands/comments.ts","../src/output/format.ts","../src/output/paginate.ts","../src/commands/completion.ts","../src/commands/create-page.ts","../src/commands/db/query.ts","../src/services/database.service.ts","../src/commands/db/schema.ts","../src/commands/edit-page.ts","../src/commands/init.ts","../src/commands/ls.ts","../src/commands/open.ts","../src/commands/profile/list.ts","../src/commands/profile/remove.ts","../src/commands/profile/use.ts","../src/commands/read.ts","../src/output/markdown.ts","../src/services/page.service.ts","../src/commands/search.ts","../src/commands/update.ts","../src/services/update.service.ts","../src/commands/users.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { Command } from 'commander';\nimport { appendCommand } from './commands/append.js';\nimport { authDefaultAction } from './commands/auth/index.js';\nimport { loginCommand } from './commands/auth/login.js';\nimport { logoutCommand } from './commands/auth/logout.js';\nimport { statusCommand } from './commands/auth/status.js';\nimport { commentAddCommand } from './commands/comment-add.js';\nimport { commentsCommand } from './commands/comments.js';\nimport { completionCommand } from './commands/completion.js';\nimport { createPageCommand } from './commands/create-page.js';\nimport { dbQueryCommand } from './commands/db/query.js';\nimport { dbSchemaCommand } from './commands/db/schema.js';\nimport { editPageCommand } from './commands/edit-page.js';\nimport { initCommand } from './commands/init.js';\nimport { lsCommand } from './commands/ls.js';\nimport { openCommand } from './commands/open.js';\nimport { profileListCommand } from './commands/profile/list.js';\nimport { profileRemoveCommand } from './commands/profile/remove.js';\nimport { profileUseCommand } from './commands/profile/use.js';\nimport { readCommand } from './commands/read.js';\nimport { searchCommand } from './commands/search.js';\nimport { updateCommand } from './commands/update.js';\nimport { usersCommand } from './commands/users.js';\nimport { setColorForced } from './output/color.js';\nimport { setOutputMode } from './output/format.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// Read version from package.json\nconst pkg = JSON.parse(\n readFileSync(join(__dirname, '../package.json'), 'utf-8'),\n) 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<{\n color?: boolean;\n verbose?: boolean;\n json?: boolean;\n md?: boolean;\n }>();\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 ---\n// auth subcommand group\nconst authCmd = new Command('auth').description('manage Notion authentication');\nauthCmd.action(authDefaultAction(authCmd)); // fires when no subcommand given\nauthCmd.addCommand(loginCommand());\nauthCmd.addCommand(logoutCommand());\nauthCmd.addCommand(statusCommand());\nauthCmd.addCommand(profileListCommand());\nauthCmd.addCommand(profileUseCommand());\nauthCmd.addCommand(profileRemoveCommand());\nprogram.addCommand(authCmd);\n\n// Backward-compat aliases (hidden from help)\nprogram.addCommand(initCommand(), { hidden: true });\n\nconst profileCmd = new Command('profile').description(\n 'manage authentication profiles',\n);\nprofileCmd.addCommand(profileListCommand());\nprofileCmd.addCommand(profileUseCommand());\nprofileCmd.addCommand(profileRemoveCommand());\nprogram.addCommand(profileCmd, { hidden: true });\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());\nprogram.addCommand(editPageCommand());\nprogram.addCommand(updateCommand());\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 { Command } from 'commander';\nimport { resolveToken } from '../config/token.js';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\nimport {\n isNotionValidationError,\n SELECTOR_HINT,\n} from '../errors/notion-errors.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { parseNotionId, toUuid } from '../notion/url-parser.js';\nimport { reportTokenSource } from '../output/stderr.js';\nimport { appendMarkdown } from '../services/write.service.js';\nimport { readStdin } from '../utils/stdin.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 .option('-m, --message <markdown>', 'markdown content to append')\n .option(\n '--after <selector>',\n 'insert after matched content — ellipsis selector, e.g. \"## Section...end of section\"',\n )\n .action(\n withErrorHandling(\n async (idOrUrl: string, opts: { message?: string; after?: 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 } else {\n throw new CliError(\n ErrorCodes.INVALID_ARG,\n 'No content to append.',\n 'Pass markdown via -m/--message or pipe it through stdin',\n );\n }\n\n if (!markdown.trim()) {\n process.stdout.write('Nothing to append.\\n');\n return;\n }\n\n const pageId = parseNotionId(idOrUrl);\n const uuid = toUuid(pageId);\n\n try {\n await appendMarkdown(\n client,\n uuid,\n markdown,\n opts.after ? { after: opts.after } : undefined,\n );\n } catch (error) {\n if (opts.after && isNotionValidationError(error)) {\n // biome-ignore lint/nursery/useErrorCause: cause passed as 4th positional arg to CliError\n throw new CliError(\n ErrorCodes.INVALID_ARG,\n `Selector not found: \"${opts.after}\". ${(error as Error).message}`,\n SELECTOR_HINT,\n error,\n );\n }\n throw error;\n }\n\n process.stdout.write('Appended.\\n');\n },\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 cause?: unknown,\n ) {\n super(message, { cause });\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 { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\n\n// OAuth app credentials — XOR-encoded and split across arrays to avoid plain-text\n// indexing by grep, strings, GitHub code search, and automated secret scanners.\n// This is obfuscation, not encryption — per RFC 8252, client secrets in native\n// apps are not confidential. The real security boundary is Notion's redirect URI lock.\n// To regenerate chunks:\n// node -e \"\n// const key = 0x5a;\n// const val = 'YOUR_VALUE_HERE';\n// const enc = Buffer.from(val.split('').map(c => c.charCodeAt(0) ^ key)).toString('base64');\n// console.log(enc.match(/.{1,4}/g).map(c => \\`'\\${c}'\\`).join(', '));\n// \"\nconst _k = 0x5a;\nconst _d = (parts: string[]) =>\n Buffer.from(parts.join(''), 'base64')\n .toString()\n .split('')\n .map((c) => String.fromCharCode(c.charCodeAt(0) ^ _k))\n .join('');\n\nconst OAUTH_CLIENT_ID = _d([\n 'aWtu',\n 'PmJt',\n 'aDh3',\n 'b2Nu',\n 'OXdi',\n 'a2I+',\n 'd2I5',\n 'amh3',\n 'ampp',\n 'bTtj',\n 'Pm44',\n 'P2s8',\n]);\nconst OAUTH_CLIENT_SECRET = _d([\n 'KT85',\n 'KD8u',\n 'BWMM',\n 'axcx',\n 'P28P',\n 'ahYp',\n 'MCti',\n 'MQtt',\n 'Hj4V',\n 'NywV',\n 'I2sp',\n 'bzlv',\n 'ECIK',\n 'NTAx',\n 'IGwA',\n 'ETU7',\n 'ahU=',\n]);\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(\n 'base64',\n );\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 {\n error?: string;\n error_description?: string;\n };\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(\n refreshToken: string,\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: '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 {\n error?: string;\n error_description?: string;\n };\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 { mkdir, readFile, rename, writeFile } from 'node:fs/promises';\nimport { parse, stringify } from 'yaml';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\nimport type { GlobalConfig } from '../types/config.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 // biome-ignore lint/nursery/useErrorCause: cause passed as 4th positional arg to CliError\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 err,\n );\n }\n\n try {\n const parsed = parse(raw) as GlobalConfig;\n return parsed ?? {};\n } catch (err) {\n // biome-ignore lint/nursery/useErrorCause: cause passed as 4th positional arg to CliError\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 err,\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 (err) {\n // biome-ignore lint/nursery/useErrorCause: cause passed as 4th positional arg to CliError\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 err,\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 (err) {\n // biome-ignore lint/nursery/useErrorCause: cause passed as 4th positional arg to CliError\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 err,\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 { 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 && {\n oauth_user_id: response.owner.user.id,\n }),\n ...(response.owner?.user?.name != null && {\n oauth_user_name: response.owner.user.name,\n }),\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 { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { parse } from 'yaml';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\nimport type { LocalConfig } from '../types/config.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 // biome-ignore lint/nursery/useErrorCause: cause passed as 4th positional arg to CliError\n throw new CliError(\n ErrorCodes.CONFIG_READ_ERROR,\n `Failed to read local config: ${localConfigPath}`,\n 'Check file permissions',\n err,\n );\n }\n\n let parsed: LocalConfig;\n try {\n parsed = (parse(raw) as LocalConfig) ?? {};\n } catch (err) {\n // biome-ignore lint/nursery/useErrorCause: cause passed as 4th positional arg to CliError\n throw new CliError(\n ErrorCodes.CONFIG_INVALID,\n `Failed to parse .notion.yaml`,\n 'Check that the file contains valid YAML',\n err,\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 { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\nimport { refreshAccessToken } from '../oauth/oauth-client.js';\nimport { clearOAuthTokens, saveOAuthTokens } from '../oauth/token-store.js';\nimport type { ProfileConfig, TokenResult } from '../types/config.js';\nimport { readGlobalConfig } from './config.js';\nimport { readLocalConfig } from './local-config.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 (err) {\n await clearOAuthTokens(profileName);\n // biome-ignore lint/nursery/useErrorCause: cause passed as 4th positional arg to CliError\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 err,\n );\n }\n}\n\n/**\n * Resolves a token from a named profile, preferring OAuth over integration tokens.\n * Returns null if the profile has no usable token.\n */\nasync function resolveProfileToken(\n profileName: string,\n profile: ProfileConfig,\n): Promise<TokenResult | null> {\n const oauthToken = await resolveOAuthToken(profileName, profile);\n if (oauthToken) {\n return { token: oauthToken, source: 'oauth' };\n }\n if (profile.token) {\n return { token: profile.token, source: `profile: ${profileName}` };\n }\n return null;\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 const result = await resolveProfileToken(localConfig.profile, profile);\n if (result) return result;\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 const result = await resolveProfileToken(\n globalConfig.active_profile,\n profile,\n );\n if (result) return result;\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 { 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// biome-ignore lint/suspicious/noExplicitAny: generic wrapper must accept any argument list\nexport function withErrorHandling<T extends (...args: any[]) => Promise<void>>(\n fn: T,\n): 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","export const SELECTOR_HINT =\n 'Use an ellipsis selector matching page content, e.g. \"## Section...end of section\". Run `notion read <id>` to see the page content.';\n\nexport function isNotionValidationError(error: unknown): boolean {\n return (\n typeof error === 'object' &&\n error !== null &&\n 'code' in error &&\n (error as { code: unknown }).code === 'validation_error'\n );\n}\n","import { APIErrorCode, Client, 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 (\n isNotionClientError(error) &&\n error.code === APIErrorCode.Unauthorized\n ) {\n // biome-ignore lint/nursery/useErrorCause: cause passed as 4th positional arg to CliError\n throw new CliError(\n ErrorCodes.AUTH_INVALID,\n 'Invalid integration token.',\n 'Check your token at notion.so/profile/integrations/internal',\n error,\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 { 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 =\n /^[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 =\n /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 { 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","import type { CliError } from '../errors/cli-error.js';\nimport type { TokenResult } from '../types/config.js';\nimport { error as colorError, dim } 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 type { Client } from '@notionhq/client';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\n\nexport interface AppendOptions {\n /** Insert after this content selector instead of appending to the end. */\n after?: string;\n}\n\nexport interface ReplaceOptions {\n /** Use this content_range instead of auto-building one from the full page. */\n range?: string;\n /** Allow deleting content. Defaults to true for full-page, false for partial. */\n allowDeletingContent?: boolean;\n}\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\n/**\n * Appends markdown content to an existing Notion page using the native\n * PATCH /v1/pages/:id/markdown endpoint (insert_content mode).\n *\n * When `options.after` is provided, content is inserted after the matched\n * selector instead of at the end of the page.\n */\nexport async function appendMarkdown(\n client: Client,\n pageId: string,\n markdown: string,\n options?: AppendOptions,\n): Promise<void> {\n await client.pages.updateMarkdown({\n page_id: pageId,\n type: 'insert_content',\n insert_content: {\n content: markdown,\n ...(options?.after != null && { after: options.after }),\n },\n });\n}\n\n/**\n * Returns the number of non-overlapping occurrences of `sub` in `text`.\n */\nfunction countOccurrences(text: string, sub: string): number {\n if (!sub) return 0;\n let count = 0;\n let pos = text.indexOf(sub, 0);\n while (pos !== -1) {\n count++;\n pos = text.indexOf(sub, pos + sub.length);\n }\n return count;\n}\n\n/**\n * Builds a \"start...end\" content_range selector that uniquely identifies the\n * entire content of the page. Grows the end snippet until it appears exactly\n * once in the text, to avoid ambiguity with repeated structural elements\n * (e.g. multiple identical tables).\n */\nfunction buildContentRange(content: string): string {\n const START_LEN = 15;\n const STEP = 10;\n\n if (content.length <= START_LEN * 2) {\n return content;\n }\n\n const start = content.slice(0, START_LEN);\n\n for (\n let endLen = START_LEN;\n endLen < content.length - START_LEN;\n endLen += STEP\n ) {\n const end = content.slice(-endLen);\n if (countOccurrences(content, end) === 1) {\n return `${start}...${end}`;\n }\n }\n\n // Entire content is used as the range as a last resort\n return content;\n}\n\n/**\n * Search-and-replace content on a Notion page using the `update_content` API.\n *\n * Each update pairs an `oldStr` (text to find) with a `newStr` (replacement).\n * When `replaceAll` is true, all occurrences of each `oldStr` are replaced.\n */\nexport async function searchAndReplace(\n client: Client,\n pageId: string,\n updates: Array<{ oldStr: string; newStr: string }>,\n options?: { replaceAll?: boolean; allowDeletingContent?: boolean },\n): Promise<void> {\n await client.pages.updateMarkdown({\n page_id: pageId,\n type: 'update_content',\n update_content: {\n content_updates: updates.map((u) => ({\n old_str: u.oldStr,\n new_str: u.newStr,\n ...(options?.replaceAll && { replace_all_matches: true }),\n })),\n ...(options?.allowDeletingContent && { allow_deleting_content: true }),\n },\n });\n}\n\n/**\n * Replace the entire content of a Notion page using the `replace_content` API.\n */\nexport async function replacePageContent(\n client: Client,\n pageId: string,\n newContent: string,\n options?: { allowDeletingContent?: boolean },\n): Promise<void> {\n await client.pages.updateMarkdown({\n page_id: pageId,\n type: 'replace_content',\n replace_content: {\n new_str: newContent,\n ...(options?.allowDeletingContent && { allow_deleting_content: true }),\n },\n });\n}\n\n/**\n * @deprecated Use `replacePageContent` for full-page replace or `searchAndReplace` for partial updates.\n * Kept for backward compatibility with the `--range` flag.\n *\n * Replaces page content with the given markdown using the legacy `replace_content_range` API.\n *\n * When called without options, replaces the entire page (existing behavior).\n * When `options.range` is provided, uses it as the content_range for a\n * surgical partial replace.\n *\n * `allow_deleting_content` defaults to `true` for full-page replaces and\n * `false` for partial (range-scoped) replaces, but can be overridden via\n * `options.allowDeletingContent`.\n *\n * If the page is empty, falls back to insert_content regardless of options.\n */\nexport async function replaceMarkdown(\n client: Client,\n pageId: string,\n newMarkdown: string,\n options?: ReplaceOptions,\n): Promise<void> {\n const current = await client.pages.retrieveMarkdown({ page_id: pageId });\n const currentContent = current.markdown.trim();\n\n if (current.truncated && !options?.range) {\n throw new CliError(\n ErrorCodes.API_ERROR,\n 'Page content is too large for full-page replace (markdown was truncated by the API).',\n 'Use --range to replace a specific section instead.',\n );\n }\n\n if (!currentContent) {\n // Empty page — just insert (range is irrelevant)\n if (options?.range) {\n process.stderr.write(\n 'Warning: page is empty, --range ignored, content inserted as-is.\\n',\n );\n }\n if (newMarkdown.trim()) {\n await client.pages.updateMarkdown({\n page_id: pageId,\n type: 'insert_content',\n insert_content: { content: newMarkdown },\n });\n }\n return;\n }\n\n const contentRange = options?.range ?? buildContentRange(currentContent);\n const allowDeletingContent =\n options?.allowDeletingContent ?? options?.range == null;\n\n await client.pages.updateMarkdown({\n page_id: pageId,\n type: 'replace_content_range',\n replace_content_range: {\n content: newMarkdown,\n content_range: contentRange,\n allow_deleting_content: allowDeletingContent,\n },\n });\n}\n\n/**\n * Creates a new Notion page under a parent page with the given markdown content.\n *\n * Uses the native POST /v1/pages `markdown` field (server-side parsing).\n */\nexport async function createPage(\n client: Client,\n parentId: string,\n title: string,\n markdown: string,\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 ...(markdown.trim() ? { markdown } : {}),\n });\n const url = 'url' in response ? response.url : response.id;\n return url;\n}\n","export async 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","import type { Command } from 'commander';\n\n/**\n * Default action for `notion auth` (no subcommand) — show help.\n */\nexport function authDefaultAction(authCmd: Command): () => Promise<void> {\n return async () => {\n authCmd.help();\n };\n}\n","import { input } from '@inquirer/prompts';\nimport { Command } from 'commander';\nimport { readGlobalConfig, writeGlobalConfig } from '../../config/config.js';\nimport { CliError } from '../../errors/cli-error.js';\nimport { ErrorCodes } from '../../errors/codes.js';\nimport { withErrorHandling } from '../../errors/error-handler.js';\nimport { exchangeCode } from '../../oauth/oauth-client.js';\nimport { runOAuthFlow } from '../../oauth/oauth-flow.js';\nimport { saveOAuthTokens } from '../../oauth/token-store.js';\nimport { dim, success } from '../../output/color.js';\nimport { stderrWrite } from '../../output/stderr.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')\n .option('--profile <name>', 'profile name to store credentials in')\n .option(\n '--manual',\n 'print auth URL instead of opening browser (for headless OAuth)',\n )\n .action(\n withErrorHandling(async (opts: LoginOptions) => {\n if (!process.stdin.isTTY && !opts.manual) {\n throw new CliError(\n ErrorCodes.AUTH_NO_TOKEN,\n 'Cannot run interactive login in non-TTY mode.',\n 'Use --manual flag to get an auth URL you can open in a browser',\n );\n }\n\n const result = await runOAuthFlow({ manual: opts.manual });\n const response = await exchangeCode(result.code);\n\n const userName = response.owner?.user?.name ?? 'unknown user';\n const workspaceName = response.workspace_name ?? 'unknown workspace';\n\n const config = await readGlobalConfig();\n const existingProfiles = config.profiles ?? {};\n\n let profileName = opts.profile;\n if (!profileName) {\n const suggested =\n workspaceName\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '') || 'default';\n profileName = await input({\n message: 'Profile name to save this account under:',\n default: suggested,\n });\n }\n\n const isUpdate = Boolean(existingProfiles[profileName]);\n const isFirst = Object.keys(existingProfiles).length === 0;\n\n if (isUpdate) {\n stderrWrite(dim(`Updating existing profile \"${profileName}\"...`));\n }\n\n await saveOAuthTokens(profileName, response);\n\n // Set as active if it's the first profile saved\n if (isFirst) {\n const updated = await readGlobalConfig();\n await writeGlobalConfig({\n ...updated,\n active_profile: profileName,\n });\n }\n\n stderrWrite(\n success(`✓ Logged in as ${userName} to workspace ${workspaceName}`),\n );\n stderrWrite(dim(`Saved as profile \"${profileName}\".`));\n if (!isFirst && !isUpdate) {\n stderrWrite(\n dim(\n `Run \"notion auth use ${profileName}\" to switch to this profile.`,\n ),\n );\n }\n stderrWrite(\n dim(\n 'Your comments and pages will now be attributed to your Notion account.',\n ),\n );\n }),\n );\n\n return cmd;\n}\n","import { spawn } from 'node:child_process';\nimport { randomBytes } from 'node:crypto';\nimport {\n createServer,\n type IncomingMessage,\n type ServerResponse,\n} from 'node:http';\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\ninterface CallbackContext {\n expectedState: string;\n settled: boolean;\n timeoutHandle: ReturnType<typeof setTimeout> | null;\n resolve: (result: OAuthFlowResult) => void;\n reject: (err: unknown) => void;\n server: ReturnType<typeof createServer>;\n sockets: Set<import('node:net').Socket>;\n}\n\nfunction closeServer(ctx: CallbackContext, cb: () => void): void {\n for (const socket of ctx.sockets) {\n socket.destroy();\n }\n ctx.sockets.clear();\n ctx.server.close(cb);\n}\n\nfunction handleCallbackRequest(\n req: IncomingMessage,\n res: ServerResponse,\n ctx: CallbackContext,\n): void {\n if (ctx.settled) {\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(\n '<html><body><h1>Already handled. You can close this tab.</h1></body></html>',\n );\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 ctx.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 (ctx.timeoutHandle) clearTimeout(ctx.timeoutHandle);\n closeServer(ctx, () => {\n ctx.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 !== ctx.expectedState) {\n ctx.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 (ctx.timeoutHandle) clearTimeout(ctx.timeoutHandle);\n closeServer(ctx, () => {\n ctx.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 ctx.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 (ctx.timeoutHandle) clearTimeout(ctx.timeoutHandle);\n closeServer(ctx, () => {\n ctx.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/**\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?: {\n manual?: boolean;\n}): Promise<OAuthFlowResult> {\n const state = randomBytes(16).toString('hex');\n const authUrl = buildAuthUrl(state);\n\n if (options?.manual) {\n return manualFlow(authUrl);\n }\n\n return new Promise<OAuthFlowResult>((resolve, reject) => {\n const ctx: CallbackContext = {\n expectedState: state,\n settled: false,\n timeoutHandle: null,\n resolve,\n reject,\n // assigned below after server is created\n server: null as unknown as ReturnType<typeof createServer>,\n sockets: new Set(),\n };\n\n const server = createServer((req, res) =>\n handleCallbackRequest(req, res, ctx),\n );\n ctx.server = server;\n\n server.on('connection', (socket) => {\n ctx.sockets.add(socket);\n socket.once('close', () => ctx.sockets.delete(socket));\n });\n\n server.on('error', (err) => {\n if (ctx.settled) return;\n ctx.settled = true;\n if (ctx.timeoutHandle) clearTimeout(ctx.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 const browserOpened = openBrowser(authUrl);\n\n if (!browserOpened) {\n server.close();\n ctx.settled = true;\n if (ctx.timeoutHandle) clearTimeout(ctx.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 ctx.timeoutHandle = setTimeout(() => {\n if (ctx.settled) return;\n ctx.settled = true;\n closeServer(ctx, () => {\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 { select } from '@inquirer/prompts';\nimport { Command } from 'commander';\nimport { readGlobalConfig, writeGlobalConfig } from '../../config/config.js';\nimport { CliError } from '../../errors/cli-error.js';\nimport { ErrorCodes } from '../../errors/codes.js';\nimport { withErrorHandling } from '../../errors/error-handler.js';\nimport { bold, dim, success } from '../../output/color.js';\nimport { stderrWrite } from '../../output/stderr.js';\n\ninterface LogoutOptions {\n profile?: string;\n}\n\nfunction profileLabel(\n name: string,\n profile: {\n token?: string;\n oauth_access_token?: string;\n oauth_user_name?: string;\n workspace_name?: string;\n },\n): string {\n const parts: string[] = [];\n if (profile.oauth_access_token)\n parts.push(\n `OAuth${profile.oauth_user_name ? ` (${profile.oauth_user_name})` : ''}`,\n );\n if (profile.token) parts.push('integration token');\n const authDesc = parts.length > 0 ? parts.join(' + ') : 'no credentials';\n const workspace = profile.workspace_name\n ? dim(` — ${profile.workspace_name}`)\n : '';\n return `${bold(name)} ${dim(authDesc)}${workspace}`;\n}\n\nexport function logoutCommand(): Command {\n const cmd = new Command('logout');\n\n cmd\n .description('remove a profile and its credentials')\n .option(\n '--profile <name>',\n 'profile name to remove (skips interactive selector)',\n )\n .action(\n withErrorHandling(async (opts: LogoutOptions) => {\n const config = await readGlobalConfig();\n const profiles = config.profiles ?? {};\n const profileNames = Object.keys(profiles);\n\n if (profileNames.length === 0) {\n stderrWrite('No profiles configured.');\n return;\n }\n\n let profileName = opts.profile;\n\n if (!profileName) {\n if (!process.stdin.isTTY) {\n throw new CliError(\n ErrorCodes.AUTH_NO_TOKEN,\n 'Cannot run interactive logout in non-TTY mode.',\n 'Use --profile <name> to specify the profile to remove',\n );\n }\n\n profileName = await select({\n message: 'Which profile do you want to log out of?',\n choices: profileNames.map((name) => ({\n // biome-ignore lint/style/noNonNullAssertion: key is from Object.keys, always present\n name: profileLabel(name, profiles[name]!),\n value: name,\n })),\n });\n }\n\n if (!profiles[profileName]) {\n throw new CliError(\n ErrorCodes.AUTH_PROFILE_NOT_FOUND,\n `Profile \"${profileName}\" not found.`,\n `Run \"notion auth list\" to see available profiles`,\n );\n }\n\n const updatedProfiles = { ...profiles };\n delete updatedProfiles[profileName];\n\n const newActiveProfile =\n config.active_profile === profileName\n ? undefined\n : config.active_profile;\n\n await writeGlobalConfig({\n ...config,\n profiles: updatedProfiles,\n active_profile: newActiveProfile,\n });\n\n stderrWrite(success(`✓ Logged out of profile \"${profileName}\".`));\n if (\n newActiveProfile === undefined &&\n Object.keys(updatedProfiles).length > 0\n ) {\n stderrWrite(\n dim(`Run \"notion auth use <name>\" to set a new active profile.`),\n );\n }\n }),\n );\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { readGlobalConfig } from '../../config/config.js';\nimport { withErrorHandling } from '../../errors/error-handler.js';\nimport { error as colorError, dim, success } from '../../output/color.js';\nimport { stderrWrite } from '../../output/stderr.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(\n ` ${colorError('✗')} No profile found (run 'notion init' to create one)`,\n );\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(\n ` OAuth: ${success('✓')} Logged in as ${userName} (user: ${userId})`,\n );\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(\n ` Internal token: ${success('✓')} Configured (${tokenPreview})`,\n );\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(\n ` Active method: Internal integration token (bot-attributed)`,\n );\n } else {\n stderrWrite(\n dim(\n ` Active method: None (run 'notion auth login' or 'notion init')`,\n ),\n );\n }\n }),\n );\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { resolveToken } from '../config/token.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { parseNotionId, toUuid } from '../notion/url-parser.js';\nimport { reportTokenSource } from '../output/stderr.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(\n 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, {\n asUser: source === 'oauth',\n });\n\n process.stdout.write('Comment added.\\n');\n }),\n );\n\n return cmd;\n}\n","import type { CommentObjectResponse } from '@notionhq/client/build/src/api-endpoints.js';\nimport { Command } from 'commander';\nimport { resolveToken } from '../config/token.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { parseNotionId, toUuid } from '../notion/url-parser.js';\nimport { printOutput, setOutputMode } from '../output/format.js';\nimport { paginateResults } from '../output/paginate.js';\nimport { reportTokenSource } from '../output/stderr.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(\n 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\n return cmd;\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.map((h, i) => h.padEnd(colWidths[i])).join(colSep);\n\n // Build separator row\n const separatorRow = colWidths.map((w) => sep.repeat(w)).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","export async function paginateResults<T>(\n fetcher: (\n cursor?: string,\n ) => 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 { 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(\n 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\n return cmd;\n}\n","import { Command } from 'commander';\nimport { resolveToken } from '../config/token.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { parseNotionId, toUuid } from '../notion/url-parser.js';\nimport { reportTokenSource } from '../output/stderr.js';\nimport { createPage } from '../services/write.service.js';\nimport { readStdin } from '../utils/stdin.js';\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(\n '-m, --message <markdown>',\n 'inline markdown content for the page body',\n )\n .action(\n withErrorHandling(\n 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 parentUuid = toUuid(parseNotionId(opts.parent));\n const url = await createPage(\n client,\n parentUuid,\n opts.title,\n markdown,\n );\n\n process.stdout.write(`${url}\\n`);\n },\n ),\n );\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { resolveToken } from '../../config/token.js';\nimport { withErrorHandling } from '../../errors/error-handler.js';\nimport { createNotionClient } from '../../notion/client.js';\nimport { parseNotionId } from '../../notion/url-parser.js';\nimport { formatJSON, formatTable } from '../../output/format.js';\nimport {\n buildFilter,\n buildSorts,\n type DatabaseSchema,\n fetchDatabaseSchema,\n queryDatabase,\n} from '../../services/database.service.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(\n schema: DatabaseSchema,\n entries: { properties: Record<string, string> }[],\n): 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(\n (max, e) => Math.max(max, (e.properties[col] ?? '').length),\n 0,\n );\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(\n '--filter <filter>',\n 'Filter entries (repeatable): --filter \"Status=Done\"',\n collect,\n [],\n )\n .option(\n '--sort <sort>',\n 'Sort entries (repeatable): --sort \"Name:asc\"',\n collect,\n [],\n )\n .option(\n '--columns <columns>',\n 'Comma-separated list of columns to display: --columns \"Title,Status\"',\n )\n .option('--json', 'Output raw JSON')\n .action(\n withErrorHandling(\n async (\n id: string,\n options: {\n filter: string[];\n sort: string[];\n columns?: string;\n json?: boolean;\n },\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\n ? buildSorts(options.sort)\n : undefined;\n\n const entries = await queryDatabase(client, dbId, {\n filter,\n sorts,\n columns,\n });\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 { type 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\n .slice(colonIdx + 1)\n .trim()\n .toLowerCase();\n return {\n property,\n direction:\n dir === 'desc' || dir === 'descending'\n ? ('descending' as const)\n : ('ascending' as const),\n };\n });\n}\n\ntype PropValue = PageObjectResponse['properties'][string];\ntype FormulaValue = Extract<PropValue, { type: 'formula' }>['formula'];\n\nfunction displayFormula(f: FormulaValue): string {\n if (f.type === 'string') return f.string ?? '';\n if (f.type === 'number')\n return f.number !== null && f.number !== undefined ? String(f.number) : '';\n if (f.type === 'boolean') return f.boolean ? 'true' : 'false';\n if (f.type === 'date') return f.date?.start ?? '';\n return '';\n}\n\nfunction displayDate(\n date: { start: string; end: string | null } | null,\n): string {\n if (!date) return '';\n return date.end ? `${date.start} → ${date.end}` : date.start;\n}\n\nexport function displayPropertyValue(prop: PropValue): string {\n switch (prop.type) {\n case 'title':\n return prop.title\n .map((r) => r.plain_text)\n .join('')\n .replace(/\\n/g, ' ');\n case 'rich_text':\n return prop.rich_text\n .map((r) => r.plain_text)\n .join('')\n .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 displayDate(prop.date);\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 return displayFormula(prop.formula);\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 { resolveToken } from '../../config/token.js';\nimport { withErrorHandling } from '../../errors/error-handler.js';\nimport { createNotionClient } from '../../notion/client.js';\nimport { parseNotionId } from '../../notion/url-parser.js';\nimport { formatJSON, formatTable } from '../../output/format.js';\nimport { fetchDatabaseSchema } from '../../services/database.service.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 { Command } from 'commander';\nimport { resolveToken } from '../config/token.js';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\nimport {\n isNotionValidationError,\n SELECTOR_HINT,\n} from '../errors/notion-errors.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { parseNotionId, toUuid } from '../notion/url-parser.js';\nimport { reportTokenSource } from '../output/stderr.js';\nimport {\n replaceMarkdown,\n replacePageContent,\n searchAndReplace,\n} from '../services/write.service.js';\nimport { readStdin } from '../utils/stdin.js';\n\nfunction collect(val: string, acc: string[]): string[] {\n acc.push(val);\n return acc;\n}\n\ninterface EditPageOpts {\n message?: string;\n find: string[];\n replace: string[];\n all?: boolean;\n range?: string;\n allowDeletingContent?: boolean;\n}\n\nexport function editPageCommand(): Command {\n const cmd = new Command('edit-page');\n\n cmd\n .description(\n \"replace a Notion page's content — full page or a targeted section\",\n )\n .argument('<id/url>', 'Notion page ID or URL')\n .option(\n '-m, --message <markdown>',\n 'new markdown content for the page body',\n )\n .option(\n '--find <text>',\n 'text to find (repeatable, pair with --replace)',\n collect,\n [],\n )\n .option(\n '--replace <text>',\n 'replacement text (repeatable, pair with --find)',\n collect,\n [],\n )\n .option('--all', 'replace all matches of each --find pattern')\n .option(\n '--range <selector>',\n '[deprecated] ellipsis selector to replace only a section, e.g. \"## My Section...last line\"',\n )\n .option(\n '--allow-deleting-content',\n 'allow deletion of child pages/databases',\n )\n .action(\n withErrorHandling(async (idOrUrl: string, opts: EditPageOpts) => {\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 // Path 1: search-and-replace via --find/--replace\n if (opts.find.length > 0) {\n if (opts.find.length !== opts.replace.length) {\n throw new CliError(\n ErrorCodes.INVALID_ARG,\n `Mismatched --find/--replace: got ${opts.find.length} --find and ${opts.replace.length} --replace flags.`,\n 'Provide the same number of --find and --replace flags, paired by position.',\n );\n }\n\n const updates = opts.find.map((oldStr, i) => ({\n oldStr,\n newStr: opts.replace[i],\n }));\n\n await searchAndReplace(client, uuid, updates, {\n replaceAll: opts.all ?? false,\n allowDeletingContent: opts.allowDeletingContent ?? false,\n });\n\n process.stdout.write('Page content updated.\\n');\n return;\n }\n\n // Resolve markdown content from -m or stdin\n let markdown = '';\n if (opts.message) {\n markdown = opts.message;\n } else if (!process.stdin.isTTY) {\n markdown = await readStdin();\n if (!markdown.trim()) {\n throw new CliError(\n ErrorCodes.INVALID_ARG,\n 'No content provided (stdin was empty).',\n 'Pass content via -m/--message for full replacement, --find/--replace for targeted edits, or pipe content through stdin',\n );\n }\n } else {\n throw new CliError(\n ErrorCodes.INVALID_ARG,\n 'No content provided.',\n 'Pass content via -m/--message for full replacement, --find/--replace for targeted edits, or pipe content through stdin',\n );\n }\n\n // Path 2: deprecated --range (legacy replace_content_range)\n if (opts.range) {\n try {\n await replaceMarkdown(client, uuid, markdown, {\n range: opts.range,\n allowDeletingContent: opts.allowDeletingContent ?? false,\n });\n } catch (error) {\n if (isNotionValidationError(error)) {\n // biome-ignore lint/nursery/useErrorCause: cause passed as 4th positional arg to CliError\n throw new CliError(\n ErrorCodes.INVALID_ARG,\n `Selector not found: \"${opts.range}\". ${(error as Error).message}`,\n SELECTOR_HINT,\n error,\n );\n }\n throw error;\n }\n process.stdout.write('Page content replaced.\\n');\n return;\n }\n\n // Path 3: full-page replace via replace_content\n await replacePageContent(client, uuid, markdown, {\n allowDeletingContent: opts.allowDeletingContent ?? false,\n });\n\n process.stdout.write('Page content replaced.\\n');\n }),\n );\n\n return cmd;\n}\n","import { confirm, input, password } from '@inquirer/prompts';\nimport { Command } from 'commander';\nimport { readGlobalConfig, writeGlobalConfig } from '../config/config.js';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\nimport { createNotionClient, validateToken } from '../notion/client.js';\nimport { bold, dim, success } from '../output/color.js';\nimport { stderrWrite } from '../output/stderr.js';\n\n/**\n * Pure flow function: prompt for integration token, validate, save profile.\n * Caller is responsible for TTY guarding before calling this function.\n */\nexport async function runInitFlow(): Promise<void> {\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:\n '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(\n success(\n `✓ Integration has access to content in ${bold(workspaceName)}.`,\n ),\n );\n }\n } catch {\n // Non-fatal — don't block init if the probe fails for any reason\n stderrWrite(\n dim('(Could not verify integration access — run `notion ls` to check)'),\n );\n }\n\n stderrWrite('');\n stderrWrite(\n dim('Write commands (comment, append, create-page) require additional'),\n );\n stderrWrite(dim('capabilities in your integration settings:'));\n stderrWrite(\n dim(' notion.so/profile/integrations/internal → your integration →'),\n );\n stderrWrite(\n dim(\n ' Capabilities: enable \"Read content\", \"Insert content\", \"Read comments\", \"Insert comments\"',\n ),\n );\n stderrWrite('');\n stderrWrite(\n dim('To post comments and create pages attributed to your user account:'),\n );\n stderrWrite(dim(' notion auth login'));\n}\n\nexport function initCommand(): Command {\n const cmd = new Command('init');\n\n cmd.description('authenticate with Notion and save a profile').action(\n 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 await runInitFlow();\n }),\n );\n\n return cmd;\n}\n","import { isFullPageOrDataSource } from '@notionhq/client';\nimport type {\n DataSourceObjectResponse,\n PageObjectResponse,\n} from '@notionhq/client/build/src/api-endpoints.js';\nimport { Command } from 'commander';\nimport { resolveToken } from '../config/token.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { printOutput, setOutputMode } from '../output/format.js';\nimport { reportTokenSource } from '../output/stderr.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(\n (p) => p.type === 'title',\n );\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(\n item: PageObjectResponse | DataSourceObjectResponse,\n): 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(\n '--type <type>',\n 'filter by object type (page or database)',\n (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 )\n .option(\n '--cursor <cursor>',\n 'start from this pagination cursor (from a previous --next hint)',\n )\n .option('--json', 'force JSON output')\n .action(\n withErrorHandling(\n async (opts: {\n type?: 'page' | 'database';\n cursor?: string;\n json?: boolean;\n }) => {\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) =>\n isFullPageOrDataSource(r),\n ) as (PageObjectResponse | DataSourceObjectResponse)[];\n\n if (opts.type) {\n const filterType = opts.type;\n items = items.filter((r) =>\n filterType === 'database'\n ? r.object === 'data_source'\n : 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 `\\n --next: notion ls --cursor ${response.next_cursor}\\n`,\n );\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 { withErrorHandling } from '../errors/error-handler.js';\nimport { parseNotionId } from '../notion/url-parser.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(\n 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'\n ? 'open'\n : platform === 'win32'\n ? 'start'\n : 'xdg-open'; // Linux\n\n await execAsync(`${opener} \"${url}\"`);\n process.stdout.write(`Opening ${url}\\n`);\n }),\n );\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { readGlobalConfig } from '../../config/config.js';\nimport { withErrorHandling } from '../../errors/error-handler.js';\nimport { bold, dim } from '../../output/color.js';\n\nexport function profileListCommand(): Command {\n const cmd = new Command('list');\n\n cmd.description('list all authentication profiles').action(\n 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(\n 'No profiles configured. Run `notion auth login` to get started.\\n',\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\n ? dim(` — ${profile.workspace_name}`)\n : '';\n\n process.stdout.write(\n `${marker}${name}${activeLabel}${workspaceInfo}\\n`,\n );\n }\n }),\n );\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { readGlobalConfig, writeGlobalConfig } from '../../config/config.js';\nimport { CliError } from '../../errors/cli-error.js';\nimport { ErrorCodes } from '../../errors/codes.js';\nimport { withErrorHandling } from '../../errors/error-handler.js';\nimport { success } from '../../output/color.js';\nimport { stderrWrite } from '../../output/stderr.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(\n 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 auth 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\n return cmd;\n}\n","import { Command } from 'commander';\nimport { readGlobalConfig, writeGlobalConfig } from '../../config/config.js';\nimport { CliError } from '../../errors/cli-error.js';\nimport { ErrorCodes } from '../../errors/codes.js';\nimport { withErrorHandling } from '../../errors/error-handler.js';\nimport { success } from '../../output/color.js';\nimport { stderrWrite } from '../../output/stderr.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(\n 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 auth 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\n return cmd;\n}\n","import { Command } from 'commander';\nimport { resolveToken } from '../config/token.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { parseNotionId } from '../notion/url-parser.js';\nimport { getOutputMode, isatty } from '../output/format.js';\nimport { renderMarkdown } from '../output/markdown.js';\nimport { fetchPageMarkdown } from '../services/page.service.js';\n\nexport function readCommand(): Command {\n return (\n new Command('read')\n .description('Read a Notion page as markdown')\n .argument('<id>', 'Notion page ID or URL')\n // Note: --json and --md are inherited from the root program global options.\n // Do NOT redefine them here — Commander routes them to the root program,\n // which sets the output mode via the preAction hook. Read them via getOutputMode().\n .action(\n withErrorHandling(async (id: string) => {\n const { token } = await resolveToken();\n const client = createNotionClient(token);\n const pageId = parseNotionId(id);\n const pageWithMarkdown = await fetchPageMarkdown(client, pageId);\n\n const mode = getOutputMode();\n if (mode === 'json') {\n process.stdout.write(\n `${JSON.stringify(pageWithMarkdown, null, 2)}\\n`,\n );\n } else {\n const { markdown } = pageWithMarkdown;\n if (mode === 'md' || !isatty()) {\n // Raw markdown — piped output or explicit --md flag\n process.stdout.write(markdown);\n } else {\n // TTY: render with terminal styling\n process.stdout.write(renderMarkdown(markdown));\n }\n }\n }),\n )\n );\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\ninterface FenceState {\n inFence: boolean;\n fenceLang: string;\n fenceLines: string[];\n}\n\n/** Returns non-null if `line` opens or closes a fenced code block. */\nfunction handleFenceLine(\n line: string,\n state: FenceState,\n out: string[],\n): boolean {\n const fenceMatch = line.match(/^```(\\w*)$/);\n if (fenceMatch && !state.inFence) {\n state.inFence = true;\n state.fenceLang = fenceMatch[1] ?? '';\n state.fenceLines = [];\n return true;\n }\n if (line === '```' && state.inFence) {\n state.inFence = false;\n const header = state.fenceLang ? c.dim(`[${state.fenceLang}]`) : '';\n if (header) out.push(header);\n for (const fl of state.fenceLines) {\n out.push(c.green(` ${fl}`));\n }\n out.push('');\n return true;\n }\n return false;\n}\n\nfunction handleHeading(line: string, out: string[]): boolean {\n const h1 = line.match(/^# (.+)/);\n if (h1) {\n out.push(`\\n${c.bold.cyan(h1[1])}`);\n return true;\n }\n const h2 = line.match(/^## (.+)/);\n if (h2) {\n out.push(`\\n${c.bold.blue(h2[1])}`);\n return true;\n }\n const h3 = line.match(/^### (.+)/);\n if (h3) {\n out.push(`\\n${c.bold(h3[1])}`);\n return true;\n }\n const h4 = line.match(/^#### (.+)/);\n if (h4) {\n out.push(c.bold.underline(h4[1]));\n return true;\n }\n return false;\n}\n\nfunction handleListLine(line: string, out: string[]): boolean {\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 return true;\n }\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 return true;\n }\n return false;\n}\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 const fence: FenceState = { inFence: false, fenceLang: '', fenceLines: [] };\n\n for (const line of lines) {\n if (handleFenceLine(line, fence, out)) continue;\n\n if (fence.inFence) {\n fence.fenceLines.push(line);\n continue;\n }\n\n // YAML frontmatter separator / horizontal rule\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())) continue;\n\n if (handleHeading(line, out)) continue;\n\n // Blockquotes / callouts\n if (line.startsWith('> ')) {\n out.push(c.yellow('▎ ') + renderInline(line.slice(2)));\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 if (handleListLine(line, out)) continue;\n\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) =>\n alt ? c.dim(`[image: ${alt}]`) : c.dim('[image]'),\n )\n // links [text](url)\n .replace(\n /\\[([^\\]]+)\\]\\(([^)]+)\\)/g,\n (_, t, url) => c.cyan.underline(t) + c.dim(` (${url})`),\n )\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 — \\x00 is used intentionally as a sentinel character\n result = result.replace(\n // biome-ignore lint/suspicious/noControlCharactersInRegex: sentinel chars are intentional\n /\\x00CODE(\\d+)\\x00/g,\n (_, i) => codeSpans[Number(i)] ?? '',\n );\n\n return result;\n}\n","import type { Client } from '@notionhq/client';\nimport type { PageObjectResponse } from '@notionhq/client/build/src/api-endpoints.js';\n\nexport interface PageWithMarkdown {\n page: PageObjectResponse;\n markdown: string;\n}\n\n/**\n * Fetches a page's metadata and its content as markdown using the native\n * Notion markdown endpoint (GET /v1/pages/:id/markdown).\n */\nexport async function fetchPageMarkdown(\n client: Client,\n pageId: string,\n): Promise<PageWithMarkdown> {\n const [page, markdownResponse] = await Promise.all([\n client.pages.retrieve({ page_id: pageId }) as Promise<PageObjectResponse>,\n client.pages.retrieveMarkdown({ page_id: pageId }),\n ]);\n\n return { page, markdown: markdownResponse.markdown };\n}\n","import { isFullPageOrDataSource } from '@notionhq/client';\nimport type {\n DataSourceObjectResponse,\n PageObjectResponse,\n} from '@notionhq/client/build/src/api-endpoints.js';\nimport { Command } from 'commander';\nimport { resolveToken } from '../config/token.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { printOutput, setOutputMode } from '../output/format.js';\nimport { reportTokenSource } from '../output/stderr.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(\n (p) => p.type === 'title',\n );\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(\n item: PageObjectResponse | DataSourceObjectResponse,\n): 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(\n '--type <type>',\n 'filter by object type (page or database)',\n (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 )\n .option(\n '--cursor <cursor>',\n 'start from this pagination cursor (from a previous --next hint)',\n )\n .option('--json', 'force JSON output')\n .action(\n withErrorHandling(\n async (\n query: string,\n opts: { type?: 'page' | 'database'; cursor?: string; json?: boolean },\n ) => {\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) =>\n isFullPageOrDataSource(r),\n ) as (PageObjectResponse | DataSourceObjectResponse)[];\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 `\\n --next: notion search \"${query}\" --cursor ${response.next_cursor}\\n`,\n );\n }\n },\n ),\n );\n\n return cmd;\n}\n","import type { PageObjectResponse } from '@notionhq/client/build/src/api-endpoints.js';\nimport { Command } from 'commander';\nimport { resolveToken } from '../config/token.js';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { parseNotionId, toUuid } from '../notion/url-parser.js';\nimport { formatJSON, getOutputMode } from '../output/format.js';\nimport { reportTokenSource } from '../output/stderr.js';\nimport {\n buildPropertiesPayload,\n updatePageProperties,\n} from '../services/update.service.js';\n\ninterface UpdateOpts {\n prop: string[];\n title?: string;\n}\n\nfunction collectProps(val: string, acc: string[]): string[] {\n acc.push(val);\n return acc;\n}\n\nexport function updateCommand(): Command {\n const cmd = new Command('update');\n\n cmd\n .description('update properties on a Notion page')\n .argument('<id/url>', 'Notion page ID or URL')\n .option(\n '--prop <property=value>',\n 'set a property value (repeatable)',\n collectProps,\n [],\n )\n .option('--title <title>', 'set the page title')\n .action(\n withErrorHandling(async (idOrUrl: string, opts: UpdateOpts) => {\n if (opts.title === undefined && opts.prop.length === 0) {\n throw new CliError(\n ErrorCodes.INVALID_ARG,\n 'No properties to update.',\n 'Provide at least one --prop \"Name=Value\" or --title \"New Title\"',\n );\n }\n\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 // Fetch the page to get property schema\n const page = (await client.pages.retrieve({\n page_id: uuid,\n })) as PageObjectResponse;\n\n // Build properties payload from --prop strings\n const properties = buildPropertiesPayload(opts.prop, page);\n\n // --title is a shortcut that sets the title property\n if (opts.title !== undefined) {\n // Find the title property in the schema\n const titleEntry = Object.entries(page.properties).find(\n ([, prop]) => prop.type === 'title',\n );\n if (!titleEntry) {\n throw new CliError(\n ErrorCodes.INVALID_ARG,\n 'This page has no title property.',\n 'Use --prop to set properties by name instead',\n );\n }\n const [titlePropName] = titleEntry;\n properties[titlePropName] = {\n title: [{ type: 'text', text: { content: opts.title } }],\n };\n }\n\n const updatedPage = await updatePageProperties(\n client,\n uuid,\n properties,\n );\n\n const mode = getOutputMode();\n if (mode === 'json') {\n process.stdout.write(`${formatJSON(updatedPage)}\\n`);\n } else {\n process.stdout.write('Page updated.\\n');\n }\n }),\n );\n\n return cmd;\n}\n","import type { Client } from '@notionhq/client';\nimport type { PageObjectResponse } from '@notionhq/client/build/src/api-endpoints.js';\nimport { CliError } from '../errors/cli-error.js';\nimport { ErrorCodes } from '../errors/codes.js';\n\nconst UNSUPPORTED_TYPES = new Set([\n 'relation',\n 'formula',\n 'rollup',\n 'created_time',\n 'created_by',\n 'last_edited_time',\n 'last_edited_by',\n 'files',\n 'unique_id',\n 'verification',\n 'button',\n]);\n\n/**\n * Builds the Notion API property update object for a single property.\n * Returns null when value is empty string (signals \"clear the property\").\n * Throws CliError(INVALID_ARG) for unsupported property types.\n */\nexport function buildPropertyUpdate(\n propName: string,\n propType: string,\n value: string,\n): Record<string, unknown> | null {\n if (UNSUPPORTED_TYPES.has(propType)) {\n throw new CliError(\n ErrorCodes.INVALID_ARG,\n `Property \"${propName}\" has type \"${propType}\" which cannot be set via the CLI.`,\n 'Supported types: title, rich_text, select, status, multi_select, number, checkbox, url, email, phone_number, date',\n );\n }\n\n // Empty value → clear the property (null)\n if (value === '') {\n return null;\n }\n\n switch (propType) {\n case 'title':\n return { title: [{ type: 'text', text: { content: value } }] };\n\n case 'rich_text':\n return { rich_text: [{ type: 'text', text: { content: value } }] };\n\n case 'select':\n return { select: { name: value } };\n\n case 'status':\n return { status: { name: value } };\n\n case 'multi_select':\n return {\n multi_select: value\n .split(',')\n .map((v) => v.trim())\n .filter(Boolean)\n .map((v) => ({ name: v })),\n };\n\n case 'number': {\n const n = Number(value);\n if (Number.isNaN(n)) {\n throw new CliError(\n ErrorCodes.INVALID_ARG,\n `Invalid number value \"${value}\" for property \"${propName}\".`,\n 'Provide a numeric value, e.g. --prop \"Count=42\"',\n );\n }\n return { number: n };\n }\n\n case 'checkbox': {\n const lower = value.toLowerCase();\n return { checkbox: lower === 'true' || lower === 'yes' };\n }\n\n case 'url':\n return { url: value };\n\n case 'email':\n return { email: value };\n\n case 'phone_number':\n return { phone_number: value };\n\n case 'date': {\n const parts = value.split(',');\n const start = parts[0].trim();\n const end = parts[1]?.trim();\n return { date: end ? { start, end } : { start } };\n }\n\n default:\n throw new CliError(\n ErrorCodes.INVALID_ARG,\n `Property \"${propName}\" has unsupported type \"${propType}\".`,\n 'Supported types: title, rich_text, select, status, multi_select, number, checkbox, url, email, phone_number, date',\n );\n }\n}\n\n/**\n * Parses all `--prop \"Name=Value\"` strings against the page property schema\n * and returns a Notion API `properties` object ready for pages.update().\n *\n * Throws CliError(INVALID_ARG) when:\n * - a prop string has no \"=\" separator\n * - the property name is not found in the page schema\n * - the property type is unsupported\n */\nexport function buildPropertiesPayload(\n propStrings: string[],\n page: PageObjectResponse,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const propString of propStrings) {\n const eqIdx = propString.indexOf('=');\n if (eqIdx === -1) {\n throw new CliError(\n ErrorCodes.INVALID_ARG,\n `Invalid --prop value: \"${propString}\". Expected format: \"PropertyName=Value\".`,\n 'Example: --prop \"Status=Done\"',\n );\n }\n\n const propName = propString.slice(0, eqIdx).trim();\n const value = propString.slice(eqIdx + 1);\n\n const schemaProp = page.properties[propName];\n if (!schemaProp) {\n const available = Object.keys(page.properties).join(', ');\n throw new CliError(\n ErrorCodes.INVALID_ARG,\n `Property \"${propName}\" not found on this page.`,\n `Available properties: ${available}`,\n );\n }\n\n const propType = schemaProp.type;\n const payload = buildPropertyUpdate(propName, propType, value);\n result[propName] = payload;\n }\n\n return result;\n}\n\n/**\n * Calls the Notion API to update a page's properties.\n * Returns the full updated PageObjectResponse.\n */\nexport async function updatePageProperties(\n client: Client,\n pageId: string,\n properties: Record<string, unknown>,\n): Promise<PageObjectResponse> {\n const response = await client.pages.update({\n page_id: pageId,\n properties: properties as Parameters<\n typeof client.pages.update\n >[0]['properties'],\n });\n return response as PageObjectResponse;\n}\n","import type { UserObjectResponse } from '@notionhq/client/build/src/api-endpoints.js';\nimport { Command } from 'commander';\nimport { resolveToken } from '../config/token.js';\nimport { withErrorHandling } from '../errors/error-handler.js';\nimport { createNotionClient } from '../notion/client.js';\nimport { printOutput, setOutputMode } from '../output/format.js';\nimport { paginateResults } from '../output/paginate.js';\nimport { reportTokenSource } from '../output/stderr.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\n | { workspace_name?: string | null }\n | Record<string, never>;\n return 'workspace_name' in bot && bot.workspace_name\n ? bot.workspace_name\n : '—';\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(\n 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(\n (u) => u.name !== undefined,\n );\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\n return cmd;\n}\n"],"mappings":"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","names":["join","Command","c","readFile","join","parse","join","readFile","parse","globalConfig","error","isNotionClientError","error","error","input","error","authCmd","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","c","Command","Command","Command","collect","Command","error","input","Command","input","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Chalk","Chalk","Command","isFullPageOrDataSource","Command","getTitle","displayType","Command","isFullPageOrDataSource","Command","Command","Command","Command","join","Command"]}
|